| 效果: 程序: #if !defined(_LJF_LJFHOOK_H) #define _LJF_LJFHOOK_H #if _MSC_VER > 1000 #pragma once #endif #include <afxtempl.h> #define sLjfDialogOldProcTag _T("CDialog_oldProc") #define SYSBTN_NON -1 #define SYSBTN_MIN 0 #define SYSBTN_NOM 1 #define SYSBTN_MAX 2 #define SYSBTN_CLS 3 #define SYSBTNSTATE_NOM 0 #define SYSBTNSTATE_OVER 1 #define SYSBTNSTATE_DOWN 2 #define SYSBTNSTATE_BLUR 3 #define SYSBTNSTATE_DIS 4 class CLjfDialogPrivateInfo { public: CLjfDialogPrivateInfo(); HICON hIcon; int iOrgCapHeight; int iOrgBorderWidth; CString strCaption; BOOL bNcActive; BOOL bNcLBtnDown; BOOL bHasMaxBtn; BOOL bHasMinBtn; BOOL bHasCloseBtn; RECT rWnd; RECT rwndbtnClose; RECT rwndbtnMax; RECT rwndbtnMin; RECT rwndC11; RECT rwndC12; RECT rwndC13; RECT rwndC21; RECT rwndC22; RECT rwndC23; RECT rwndC31; RECT rwndC32; RECT rwndC33;
RECT rwndC41; RECT rwndC42; RECT rwndC43; RECT rwndCaption; }; class CLjfDialogInfo { public: CLjfDialogInfo(); ~CLjfDialogInfo(); void PreparBitmapTranRgn(CBitmap* pBitmap); void SetLjfWindowRgn(HWND hWnd,CLjfDialogPrivateInfo *_p); bool GetInfoFromIniFile(CString sFileName); void SetWindRect(HWND hWnd,CBitmap* pBitmapWnd,CLjfDialogPrivateInfo *_p); CRgn rgnBmpTran; int capLeftspace; int capTopspace; int capFontHeight; int icoLeftspace; int icoWidth; int icoTopspace; int btnHeight; int btnWidth ; int btnInspace ; int btnRightspace ; int btnTopspace ; int bdyWidth; int bdyHeight; int bdyCaptionHeight ; int bdyBorderBottomHeight ; int bdyBorderLeftWidth ; int bdyBorderRightWidth ; int bdyCTop1Width ; int bdyCTop2Width ; int bdyCBottom1Width; int bdyCBottom2Width; int bdyCLeft1Height; int bdyCLeft2Height; int bdyCRight1Height; int bdyCRight2Height; RECT btnrClose; RECT btnrMax; RECT btnrMin; RECT btnrNom; RECT bdyrC11; RECT bdyrC12; RECT bdyrC13; RECT bdyrC21; RECT bdyrC22; RECT bdyrC23; RECT bdyrC31; RECT bdyrC32; RECT bdyrC33;
RECT bdyrC41; RECT bdyrC42; RECT bdyrC43; }; class CLjfDialog { // 構造 public: ??? CLjfDialog(HWND hWnd); ~CLjfDialog(); static void Install(CString sSkinIniFileName); static void UnInstall(); static bool AddSubClass( HWND &hWnd,TCHAR * oldProcTag,DWORD Proc); static CLjfDialog* AddWndHook(HWND hwnd); static CLjfDialog* GetWndHook(HWND hwnd);
static LRESULT CALLBACK LjfDialogProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK WindowHook (int code, WPARAM wParam, LPARAM lParam); static bool GetCBitmap(CString sFileName,CBitmap &cbmp); static bool FillRect(HWND hWnd,CDC *pDC, RECT rt, RECT rtbmp,CBitmap *pcbmp); static bool FillRect(CDC* pdcMem,CDC *pdcMemShow, RECT rt, RECT rtbmp); static bool FillButton(HWND hWnd,CDC* pdcMem,CDC *pdcMemShow,CLjfDialogPrivateInfo * _p,int intBtnNo,int intBtnState);// static bool FillButton(HWND hWnd,CLjfDialogPrivateInfo * _p,int intBtnNo,int intBtnState, CDC *pDC);// static void DrawNC(HWND hWnd,CLjfDialogPrivateInfo *_p,CDC* pDC);//畫非客戶區. static bool GetBtnRect(HWND hWnd,CLjfDialogPrivateInfo * _p,RECT &rbtn, RECT &rbtnWnd, int intBtnNo,int intState); // 消息 public: LRESULT OnNcCalcsize(WNDPROC lpPrevWndFunc,HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam); void NcCalcSize(RECT* rect); void OnShowWindow(BOOL bShow); void OnNcDestroy(); void OnCreate(LPCREATESTRUCT lpCreateStruct); void OnNcPaint(); UINT OnNcHitTest(WNDPROC lpPrevWndFunc,HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam); void OnNcActivate(BOOL bActive); void OnMove(int x, int y); void OnNcLButtonDown(UINT nHitTest, CPoint point); void OnNcLButtonUp(UINT nHitTest, CPoint point); void OnNcMouseMove(UINT nHitTest, CPoint point); void OnSize(); // 數據 protected: HWND m_hWnd; CLjfDialogPrivateInfo m_p;//對象私有信息 static CMap<HWND, HWND, CLjfDialog*, CLjfDialog*> m_map; ??? static HHOOK m_hHook; static CString m_sSkinName; static CLjfDialogInfo m_sif;//公用信息 static CBitmap m_cbmpDlgFocus; static CBitmap m_cbmpDlgBlur; static CBitmap m_cbmpSysBtn; };
#endif // !defined(_LJF_LJFHOOK_H) // #include "stdafx.h" #include "LjfIni.h" #include "LjfDialog.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif //靜態變量 CMap <HWND, HWND, CLjfDialog*, CLjfDialog*> CLjfDialog::m_map; HHOOK CLjfDialog::m_hHook = NULL; CString CLjfDialog::m_sSkinName = "skin"; CLjfDialogInfo CLjfDialog::m_sif; CBitmap CLjfDialog::m_cbmpDlgFocus; CBitmap CLjfDialog::m_cbmpDlgBlur; CBitmap CLjfDialog::m_cbmpSysBtn; //回調函數 LRESULT CALLBACK CLjfDialog::LjfDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { WNDPROC oldWndProc = (WNDPROC)GetProp(hWnd, sLjfDialogOldProcTag); ??? CLjfDialog* pWnd = GetWndHook(hWnd); UINT uMsg1=uMsg; if (pWnd == NULL) goto EndLjfDialogProc;
??? switch (uMsg) ??? { ?? case WM_NCCALCSIZE: ??? return pWnd->OnNcCalcsize(oldWndProc, hWnd, uMsg1, wParam, lParam); ?? case WM_NCPAINT: ??? pWnd->OnNcPaint(); ??? return HTNOWHERE; ?? case WM_SHOWWINDOW: ??? pWnd->OnShowWindow(wParam != NULL); ??? break; ?? case WM_NCDESTROY: ??? pWnd->OnNcDestroy(); ??? break; ?? case WM_CREATE: ??? pWnd->OnCreate((CREATESTRUCT *)lParam); ??? break; ?? case WM_NCHITTEST: ??? return pWnd->OnNcHitTest(oldWndProc, hWnd, uMsg1, wParam, lParam); ?? case WM_NCACTIVATE: ??? pWnd->OnNcActivate((BOOL)LOWORD(wParam)); ??? return HTCAPTION; ?? case 0x00AE://在windows最佳性能時依然在NCBUTTONDOWN和調整大小時 ?? case 0x00AF://有系統最大最小關閉按鈕出現,有待解決. ?? //case WM_NOTIFY: ??? return HTCAPTION; ?? case WM_MOVE: ??? pWnd->OnMove(LOWORD(lParam),HIWORD(lParam)); ??? break; ?? case WM_NCLBUTTONDOWN: ??? pWnd->OnNcLButtonDown((UINT)wParam,CPoint(LOWORD(lParam),HIWORD(lParam))); ??? break; ?? case WM_NCLBUTTONUP: ??? pWnd->OnNcLButtonUp((UINT)wParam,CPoint(LOWORD(lParam),HIWORD(lParam))); ??? break; ?? case WM_NCMOUSEMOVE: ??? pWnd->OnNcMouseMove((UINT)wParam,CPoint(LOWORD(lParam),HIWORD(lParam))); ??? break; ?? case WM_SIZE: ??? pWnd->OnSize(); ??? break; ??? } EndLjfDialogProc: if(IsWindow(hWnd)) ?? return CallWindowProc(oldWndProc, hWnd, uMsg1, wParam, lParam); else ?? return HTNOWHERE; } //消息處理函數 void CLjfDialog::OnCreate(LPCREATESTRUCT lpCreateStruct) { m_p.strCaption=lpCreateStruct->lpszName; RECT r;GetWindowRect(m_hWnd,&r);//整個窗口的相對于屏幕的矩形 CWnd::FromHandle(m_hWnd)->ScreenToClient(&r); m_p.iOrgCapHeight = -r.top; m_p.iOrgBorderWidth = -r.left; LONG lWindowStyle = GetWindowLong(m_hWnd,GWL_STYLE);?? if(!(lWindowStyle&WS_MINIMIZEBOX)) m_p.bHasMinBtn = FALSE; if(!(lWindowStyle&WS_MAXIMIZEBOX)) m_p.bHasMaxBtn = FALSE; if (!(lWindowStyle&WS_SYSMENU)) m_p.bHasCloseBtn = FALSE; //重設窗體大小 CRect rtOrg;GetWindowRect(m_hWnd,&rtOrg); int iEw=m_sif.bdyBorderLeftWidth+m_sif.bdyBorderRightWidth-2*m_p.iOrgBorderWidth; int iEh = m_sif.bdyCaptionHeight-m_p.iOrgCapHeight+m_sif.bdyBorderBottomHeight-m_p.iOrgBorderWidth; SetWindowPos(m_hWnd,HWND_TOP,0,0,rtOrg.Width()+iEw,rtOrg.Height()+iEh,SWP_NOMOVE); } void CLjfDialog::OnNcActivate(BOOL bActive) { m_p.bNcActive=bActive; OnNcPaint(); } void CLjfDialog::OnNcLButtonDown(UINT nHitTest, CPoint point) { //檢測最小,最大和關閉按鈕是否按下,然后更換. m_p.bNcLBtnDown = TRUE; POINT p; p.x = point.x-m_p.rWnd.left; p.y = point.y-m_p.rWnd.top; if (PtInRect(&m_p.rwndbtnMin,p) && m_p.bHasMinBtn) { ?? CWindowDC dc(CWnd::FromHandle(m_hWnd)); ?? FillButton(m_hWnd,&m_p,SYSBTN_MIN,SYSBTNSTATE_DOWN,&dc); ?? ReleaseDC(m_hWnd,dc); } else if (PtInRect(&m_p.rwndbtnMax,p) && m_p.bHasMaxBtn) { ?? CWindowDC dc(CWnd::FromHandle(m_hWnd));?? ?? FillButton(m_hWnd,&m_p,SYSBTN_MAX,SYSBTNSTATE_DOWN,&dc); ?? ReleaseDC(m_hWnd,dc); } else if (PtInRect(&m_p.rwndbtnClose,p) && m_p.bHasCloseBtn) { ?? CWindowDC dc(CWnd::FromHandle(m_hWnd)); ?? FillButton(m_hWnd,&m_p,SYSBTN_CLS,SYSBTNSTATE_DOWN,&dc); ?? ReleaseDC(m_hWnd,dc); } } void CLjfDialog::OnNcMouseMove(UINT nHitTest, CPoint point) { //檢測最小,最大和關閉按鈕是否有鼠標懸停,然后更換. if(m_p.bNcLBtnDown) { ?? m_p.bNcLBtnDown = false; ?? return; } POINT p; p.x = point.x-m_p.rWnd.left; p.y = point.y-m_p.rWnd.top; if (PtInRect(&m_p.rwndbtnMin,p) & m_p.bHasMinBtn) { ?? CWindowDC dc(CWnd::FromHandle(m_hWnd)); ?? FillButton(m_hWnd,&m_p,SYSBTN_MIN,SYSBTNSTATE_OVER,&dc); ?? ReleaseDC(m_hWnd,dc); } else if (PtInRect(&m_p.rwndbtnMax,p)) { ?? CWindowDC dc(CWnd::FromHandle(m_hWnd)); ?? FillButton(m_hWnd,&m_p,SYSBTN_MAX,SYSBTNSTATE_OVER,&dc); ?? ReleaseDC(m_hWnd,dc); } else if (PtInRect(&m_p.rwndbtnClose,p)) { ?? CWindowDC dc(CWnd::FromHandle(m_hWnd)); ?? FillButton(m_hWnd,&m_p,SYSBTN_CLS,SYSBTNSTATE_OVER,&dc); ?? ReleaseDC(m_hWnd,dc); } else { ?? CWindowDC dc(CWnd::FromHandle(m_hWnd)); ?? FillButton(m_hWnd,&m_p,SYSBTN_MIN,SYSBTNSTATE_NOM,&dc); ?? FillButton(m_hWnd,&m_p,SYSBTN_MAX,SYSBTNSTATE_NOM,&dc); ?? FillButton(m_hWnd,&m_p,SYSBTN_CLS,SYSBTNSTATE_NOM,&dc); ?? ReleaseDC(m_hWnd,dc); } } UINT CLjfDialog::OnNcHitTest(WNDPROC lpPrevWndFunc,HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam) { LRESULT lRet = CallWindowProc(lpPrevWndFunc,hWnd,Msg,wParam,lParam); if (lRet == HTZOOM || lRet == HTMINBUTTON || lRet == HTCLOSE ?? || HTHELP == lRet || lRet == HTTOP)//屏蔽最大最小關閉HITTEST. ?? lRet = HTCAPTION; if( HTCAPTION != lRet ) ?? return lRet; POINT p; p.x = LOWORD(lParam)-m_p.rWnd.left; p.y = HIWORD(lParam)-m_p.rWnd.top; if (PtInRect(&m_p.rwndbtnMin,p)) ?? m_p.bHasMinBtn?lRet = HTSYSMENU:lRet = HTCAPTION; if (PtInRect(&m_p.rwndbtnMax,p)) ?? m_p.bHasMaxBtn?lRet = HTSYSMENU:lRet = HTCAPTION; if (PtInRect(&m_p.rwndbtnClose,p)) ?? m_p.bHasCloseBtn?lRet = HTSYSMENU:lRet = HTCAPTION; return lRet; } void CLjfDialog::OnMove(int x, int y) { GetWindowRect(m_hWnd,&m_p.rWnd); } void CLjfDialog::OnNcLButtonUp(UINT nHitTest, CPoint point) { //檢測最小,最大和關閉按鈕LButtonUp,執行對應操作 POINT p; p.x = point.x-m_p.rWnd.left; p.y = point.y-m_p.rWnd.top; if (PtInRect(&m_p.rwndbtnMin,p) && m_p.bHasMinBtn) ?? SendMessage(m_hWnd,WM_SYSCOMMAND, SC_MINIMIZE, MAKELPARAM(point.x, point.y) ); else if (PtInRect(&m_p.rwndbtnMax,p) && m_p.bHasMaxBtn) ?? if (IsZoomed(m_hWnd)) ??? SendMessage(m_hWnd,WM_SYSCOMMAND, SC_RESTORE, MAKELPARAM(point.x, point.y)); ?? else ??? SendMessage(m_hWnd,WM_SYSCOMMAND, SC_MAXIMIZE, MAKELPARAM(point.x, point.y) ); else if (PtInRect(&m_p.rwndbtnClose,p) && m_p.bHasCloseBtn) ?? SendMessage(m_hWnd,WM_CLOSE,0,0); } LRESULT CLjfDialog::OnNcCalcsize(WNDPROC lpPrevWndFunc,HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam) { //重設NC度量為給定值 LRESULT lRet = CallWindowProc(lpPrevWndFunc,hWnd,Msg,wParam,lParam); ??? if ( (BOOL)wParam )??? { ?? NCCALCSIZE_PARAMS* lpncsp = (NCCALCSIZE_PARAMS*)lParam; ?? CRect oldrect = lpncsp->rgrc[0];??????? ?? NcCalcSize(lpncsp->rgrc);??????? ?? lpncsp->rgrc[1] = lpncsp->rgrc[0];??????? ?? lRet = 0;??? } return lRet; } void CLjfDialog::NcCalcSize(RECT* rect) { if (m_p.iOrgCapHeight>10)//has caption bar { ?? rect[0].left += m_sif.bdyBorderLeftWidth-m_p.iOrgBorderWidth;//窗體左邊框的寬度??????? ?? rect[0].right -= m_sif.bdyBorderRightWidth-m_p.iOrgBorderWidth;//窗體右邊框的寬度??????? ?? rect[0].top += m_sif.bdyCaptionHeight-m_p.iOrgCapHeight; //窗體標題欄的高度 ?? rect[0].bottom -= m_sif.bdyBorderBottomHeight-m_p.iOrgBorderWidth;//窗體底邊框的高度 } } void CLjfDialog::OnNcPaint() { ??? CWindowDC dc(CWnd::FromHandle(m_hWnd)); DrawNC(m_hWnd,&m_p,&dc); } void CLjfDialog::OnSize() { m_sif.SetLjfWindowRgn(m_hWnd,&m_p); } void CLjfDialog::OnNcDestroy(){delete this;} void CLjfDialog::OnShowWindow(BOOL bShow) { if (!bShow) ?? delete this; else { ?? //m_sif.SetLjfWindowRgn(m_hWnd,&m_cbmpDlgFocus,&m_p); ?? OnSize(); ?? m_p.hIcon=CWnd::FromHandle(m_hWnd)->GetIcon(true); ?? if(m_p.hIcon == NULL) m_p.hIcon = AfxGetApp()->LoadStandardIcon(IDI_APPLICATION); } } //Draw NC void CLjfDialog::DrawNC(HWND hWnd,CLjfDialogPrivateInfo *_p,CDC* pDC) { if (!hWnd) return; m_sif.SetWindRect(hWnd,&m_cbmpDlgFocus,_p);//按鈕,標題在窗口上的相對位置 CBitmap * pcbmp= &m_cbmpDlgFocus; int iBtnState=SYSBTNSTATE_NOM; if (!_p->bNcActive) { ?? pcbmp = &m_cbmpDlgBlur; ?? iBtnState=SYSBTNSTATE_BLUR; } CDC dcMem;dcMem.CreateCompatibleDC(pDC); CDC dcMemShow;dcMemShow.CreateCompatibleDC(pDC); CBitmap cbmpMemShow; cbmpMemShow.CreateCompatibleBitmap(pDC,_p->rWnd.right-_p->rWnd.left,_p->rWnd.bottom-_p->rWnd.top); dcMemShow.SelectObject(cbmpMemShow);
dcMem.SelectObject(pcbmp); FillRect(&dcMem,&dcMemShow,_p->rwndC11,m_sif.bdyrC11); FillRect(&dcMem,&dcMemShow,_p->rwndC13,m_sif.bdyrC13); FillRect(&dcMem,&dcMemShow,_p->rwndC12,m_sif.bdyrC12); FillRect(&dcMem,&dcMemShow,_p->rwndC21,m_sif.bdyrC21); FillRect(&dcMem,&dcMemShow,_p->rwndC23,m_sif.bdyrC23); FillRect(&dcMem,&dcMemShow,_p->rwndC22,m_sif.bdyrC22); FillRect(&dcMem,&dcMemShow,_p->rwndC31,m_sif.bdyrC31); FillRect(&dcMem,&dcMemShow,_p->rwndC33,m_sif.bdyrC33); FillRect(&dcMem,&dcMemShow,_p->rwndC32,m_sif.bdyrC32); FillRect(&dcMem,&dcMemShow,_p->rwndC41,m_sif.bdyrC41); FillRect(&dcMem,&dcMemShow,_p->rwndC43,m_sif.bdyrC43); FillRect(&dcMem,&dcMemShow,_p->rwndC42,m_sif.bdyrC42); dcMem.SelectObject(&m_cbmpSysBtn); FillButton(hWnd,&dcMem,&dcMemShow,_p,SYSBTN_MIN,iBtnState); FillButton(hWnd,&dcMem,&dcMemShow,_p,SYSBTN_MAX,iBtnState); FillButton(hWnd,&dcMem,&dcMemShow,_p,SYSBTN_CLS,iBtnState); //在dcMemShow中重畫icon DrawIconEx(dcMemShow.m_hDC, m_sif.icoLeftspace, m_sif.icoTopspace,_p->hIcon, m_sif.icoWidth, m_sif.icoWidth,0, NULL,DI_NORMAL); //在dcMemShow中重畫caption dcMemShow.SetBkMode(TRANSPARENT); dcMemShow.SetTextColor(RGB(150, 150, 150)); CFont font; font.CreateFont(m_sif.capFontHeight,0,0,0,FW_NORMAL,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS, ?? CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH | FF_SWISS,"宋體"); dcMemShow.SelectObject(&font); dcMemShow.DrawText(_T(_p->strCaption),&_p->rwndCaption,DT_LEFT|DT_TOP|DT_END_ELLIPSIS);//先畫Caption陰影. if(_p->bNcActive) ?? dcMemShow.SetTextColor(RGB(255, 255, 255)); else ?? dcMemShow.SetTextColor(RGB(100, 100, 100)); OffsetRect(&_p->rwndCaption,1,-1); dcMemShow.DrawText(_T(_p->strCaption),&_p->rwndCaption,DT_LEFT|DT_TOP|DT_END_ELLIPSIS);
//把dcMemShow中的圖像粘到pDC的NC區中。 CBitmap* pBt=dcMemShow.GetCurrentBitmap(); CBrush br;br.CreatePatternBrush(pBt); CRect rClient;CWnd::FromHandle(hWnd)->GetClientRect(&rClient); OffsetRect(&rClient,m_sif.bdyBorderLeftWidth,m_sif.bdyCaptionHeight); CRgn rgnClient;rgnClient.CreateRectRgn(rClient.left,rClient.top,rClient.right,rClient.bottom); CRgn rgnWindow;rgnWindow.CreateRectRgn(0,0,_p->rWnd.right-_p->rWnd.left,_p->rWnd.bottom-_p->rWnd.top); CRgn rgnNC;rgnNC.CreateRectRgn(0,0,0,0); rgnNC.CombineRgn(&rgnWindow,&rgnClient,RGN_DIFF); pDC->FillRgn(&rgnNC,&br); } //Draw NC end //添加Hook到m_map CLjfDialog* CLjfDialog::AddWndHook(HWND hwnd) { CLjfDialog* pWnd = NULL; if (m_map.Lookup(hwnd, pWnd)) return pWnd;//如果已有hwnd,返回得到的值。 pWnd = new CLjfDialog(hwnd); if (pWnd != NULL) { ?? m_map.SetAt(hwnd, pWnd); } return pWnd; } //得到m_map中的Hook CLjfDialog* CLjfDialog::GetWndHook(HWND hwnd) { ??? CLjfDialog* pWnd = NULL; ??? if (m_map.Lookup(hwnd, pWnd)) ??? { ??????? return pWnd; ??? } ??? return NULL; } bool CLjfDialog::FillRect(HWND hWnd,CDC *pDC, RECT rt, RECT rtbmp,CBitmap *pcbmp) { CDC MemDC;MemDC.CreateCompatibleDC (pDC); CBitmap *pOldBitmap=MemDC.SelectObject (pcbmp); pDC->StretchBlt(rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top,&MemDC, ?? rtbmp.left,rtbmp.top,rtbmp.right-rtbmp.left, rtbmp.bottom-rtbmp.top,SRCCOPY); MemDC.SelectObject (pOldBitmap); ReleaseDC(hWnd,MemDC.m_hDC); pOldBitmap->DeleteObject(); return true; } bool CLjfDialog::FillRect(CDC* pdcMem,CDC *pdcMemShow, RECT rt, RECT rtbmp) { pdcMemShow->StretchBlt(rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top,pdcMem, ?? rtbmp.left,rtbmp.top,rtbmp.right-rtbmp.left, rtbmp.bottom-rtbmp.top,SRCCOPY); return true; } //FillButton bool CLjfDialog::FillButton(HWND hWnd,CLjfDialogPrivateInfo * _p,int intBtnNo,int intBtnState, CDC *pDC) { RECT rbtn,rbtnWnd; if (GetBtnRect(hWnd,_p,rbtn, rbtnWnd, intBtnNo,intBtnState)) { ?? FillRect(hWnd,pDC,rbtnWnd,rbtn,&m_cbmpSysBtn); ?? return true; } return false; } bool CLjfDialog::FillButton(HWND hWnd,CDC* pdcMem,CDC *pdcMemShow,CLjfDialogPrivateInfo * _p,int intBtnNo,int intBtnState) { RECT rbtn,rbtnWnd; if (GetBtnRect(hWnd,_p,rbtn, rbtnWnd, intBtnNo,intBtnState)) { ?? FillRect(pdcMem,pdcMemShow,rbtnWnd,rbtn); ?? return true; } return false; } bool CLjfDialog::GetBtnRect(HWND hWnd,CLjfDialogPrivateInfo * _p,RECT &rbtn, RECT &rbtnWnd, int intBtnNo,int intBtnState) { int intState = intBtnState; if(intState <= SYSBTN_NON) return false; switch(intBtnNo) { case SYSBTN_MIN: ?? if(!_p->bHasMinBtn && !_p->bHasMaxBtn) return false; ?? if (!_p->bHasMinBtn) intState = SYSBTNSTATE_DIS; ?? rbtn = m_sif.btnrMin; ?? rbtnWnd = _p->rwndbtnMin; ?? break; case SYSBTN_NOM: case SYSBTN_MAX: ?? if(!_p->bHasMinBtn && !_p->bHasMaxBtn) return false; ?? if(!_p->bHasMaxBtn) intState = SYSBTNSTATE_DIS; ?? if(IsZoomed(hWnd)) ??? rbtn = m_sif.btnrNom; ?? else ??? rbtn = m_sif.btnrMax; ?? rbtnWnd = _p->rwndbtnMax; ?? break; case SYSBTN_CLS: ?? if(!_p->bHasCloseBtn) intState = SYSBTNSTATE_DIS; ?? rbtn = m_sif.btnrClose; ?? rbtnWnd = _p->rwndbtnClose; ?? break; } OffsetRect(&rbtn,intState*m_sif.btnWidth,0); return true; } //FillButton end //子類化 bool CLjfDialog::AddSubClass( HWND &hWnd,TCHAR * oldProcTag,DWORD Proc) { if (GetProp(hWnd, oldProcTag) != NULL ) return false;//已被子類化 VERIFY(AddWndHook(hWnd) != NULL); WNDPROC oldWndProc = (WNDPROC)(long)::GetWindowLong(hWnd, GWL_WNDPROC);// 取原來窗口過程 if (oldWndProc == NULL) return false; ASSERT((DWORD)(ULONG)oldWndProc != Proc); if (!SetProp(hWnd, oldProcTag, oldWndProc) ) return false;// 保存到窗口屬性 if (!SetWindowLong(hWnd, GWL_WNDPROC,Proc))// 子類化 ?? RemoveProp(hWnd, oldProcTag); return true; } bool CLjfDialog::GetCBitmap(CString sFileName,CBitmap &cbmp) { char cpath[100]; sprintf(cpath,"%s//%s.bmp",m_sSkinName,sFileName); HBITMAP hBitmap=(HBITMAP)::LoadImage(AfxGetInstanceHandle(), ?? cpath,IMAGE_BITMAP,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE); cbmp.Attach(hBitmap); return true; } //構造 CLjfDialog::CLjfDialog (HWND hWnd) : m_hWnd(hWnd) {} //析構 CLjfDialog::~CLjfDialog () { ??? WNDPROC oldWndProc = (WNDPROC)::GetProp(m_hWnd, sLjfDialogOldProcTag); ??? if (oldWndProc != NULL) ??? { ??????? SetWindowLong(m_hWnd, GWL_WNDPROC, (DWORD)(ULONG)oldWndProc); ??????? RemoveProp(m_hWnd, sLjfDialogOldProcTag); ??? } ??? m_map.RemoveKey(m_hWnd); } //安裝鉤子 void CLjfDialog::Install(CString sSkinIniFileName) { ??? if (m_hHook == NULL ) ??????? m_hHook = SetWindowsHookEx(WH_CALLWNDPROC, WindowHook,AfxGetApp()->m_hInstance,GetCurrentThreadId());
CLjfIni ini(sSkinIniFileName); m_sSkinName=ini.GetString("skin","skin",""); if(m_sSkinName == "") m_sSkinName = "skin";//默認 CString sIniPath;sIniPath.Format("%s\\skin.ini",m_sSkinName); m_sif.GetInfoFromIniFile(sIniPath); GetCBitmap("bodyfocus",m_cbmpDlgFocus); GetCBitmap("bodyblur",m_cbmpDlgBlur); GetCBitmap("sysbtn",m_cbmpSysBtn); m_sif.PreparBitmapTranRgn(&m_cbmpDlgFocus); } //卸載鉤子 void CLjfDialog::UnInstall() { ??? POSITION pos = m_map.GetStartPosition(); ??? while (pos != NULL) ??? { ??????? HWND hwnd; ??????? CLjfDialog* pHook; ??????? m_map.GetNextAssoc(pos, hwnd, pHook); ??????? delete pHook; ?? pHook = NULL; ??? } ??? m_map.RemoveAll(); m_cbmpSysBtn.DeleteObject(); m_cbmpDlgFocus.DeleteObject(); m_cbmpDlgBlur.DeleteObject();
??? if (m_hHook != NULL) UnhookWindowsHookEx(m_hHook); } //消息過程 LRESULT CALLBACK CLjfDialog::WindowHook(int code, WPARAM wParam, LPARAM lParam) { ??? CWPSTRUCT* pStruct = (CWPSTRUCT*)lParam; ??? if (code == HC_ACTION) ??? { ??????? HWND hWnd = pStruct->hwnd; ??????? if (pStruct->message != WM_CREATE && pStruct->message != 0x01E2) goto EndProc; ?? TCHAR strClassName[20]; ?? GetClassName (hWnd, strClassName, sizeof(strClassName)); ?? LPCSTR lpszClassName = CWnd::FromHandle(hWnd)->GetRuntimeClass()->m_lpszClassName; ?? TRACE(lpszClassName);TRACE("---------\r\n"); ?? //是CDialog類,無標題欄 ?? //if (_tcscmp(lpszClassName, _T("CDialog")) == 0 && GetWindowLong(hWnd,GWL_STYLE)&WS_CAPTION) ?? if (_tcscmp(strClassName, _T("#32770")) == 0 && GetWindowLong(hWnd,GWL_STYLE)&WS_CAPTION) ??? AddSubClass(hWnd,sLjfDialogOldProcTag,(DWORD)(ULONG)LjfDialogProc); } EndProc: ??? return CallNextHookEx (m_hHook, code, wParam, lParam); } CLjfDialogInfo::CLjfDialogInfo(){} CLjfDialogInfo::~CLjfDialogInfo() { rgnBmpTran.DeleteObject(); } CLjfDialogPrivateInfo::CLjfDialogPrivateInfo() : bHasMaxBtn(TRUE),bHasMinBtn(TRUE),bHasCloseBtn(TRUE) {} bool CLjfDialogInfo::GetInfoFromIniFile(CString sFileName) { CLjfIni ini(sFileName); capLeftspace = ini.GetInt("cap","capleftspace",0); capTopspace = ini.GetInt("cap","captopspace",0); capFontHeight= ini.GetInt("cap","capfontheight",0); icoLeftspace = ini.GetInt("icon","leftspace",0); icoTopspace = ini.GetInt("icon","topspace",0); icoWidth???? = ini.GetInt("icon","width",0); btnHeight =???? ini.GetInt("sysbtn","height",0); btnWidth =????? ini.GetInt("sysbtn","width",0); btnInspace =??? ini.GetInt("sysbtn","inspace",0); btnRightspace = ini.GetInt("sysbtn","rightspace",0); btnTopspace =?? ini.GetInt("sysbtn","topspace",0); bdyWidth =?????? ini.GetInt("body","width",0); bdyHeight =????? ini.GetInt("body","height",0); bdyCaptionHeight =????? ini.GetInt("body","border1",0); bdyBorderBottomHeight = ini.GetInt("body","border2",0); bdyBorderLeftWidth =??? ini.GetInt("body","border3",0); bdyBorderRightWidth =?? ini.GetInt("body","border4",0); bdyCTop1Width = ini.GetInt("body","c11w",0); bdyCTop2Width = ini.GetInt("body","c12w",0); bdyCBottom1Width = ini.GetInt("body","c21w",0); bdyCBottom2Width = ini.GetInt("body","c22w",0); bdyCLeft1Height = ini.GetInt("body","c31h",0); bdyCLeft2Height = ini.GetInt("body","c32h",0); bdyCRight1Height = ini.GetInt("body","c41h",0); bdyCRight2Height = ini.GetInt("body","c42h",0); //btnr在sysbtn圖片上位置 SetRect(&btnrMin,0,0,btnWidth,btnHeight); SetRect(&btnrNom,btnWidth*5,0,btnWidth*6,btnHeight);//多加一個Nom; SetRect(&btnrMax,btnWidth*10,0,btnWidth*11,btnHeight); SetRect(&btnrClose,btnWidth*15,0,btnWidth*16,btnHeight); SetRect(&bdyrC11,0,0,bdyCTop1Width,bdyCaptionHeight); SetRect(&bdyrC12,bdyWidth-bdyCTop2Width,0,bdyWidth,bdyCaptionHeight); SetRect(&bdyrC13,bdyCTop1Width,0,bdyWidth-bdyCTop2Width,bdyCaptionHeight); SetRect(&bdyrC21,bdyBorderLeftWidth,bdyHeight-bdyBorderBottomHeight,bdyBorderLeftWidth+bdyCBottom1Width,bdyHeight); SetRect(&bdyrC22,bdyWidth-bdyBorderRightWidth-bdyCBottom2Width,bdyHeight-bdyBorderBottomHeight,bdyWidth-bdyBorderRightWidth,bdyHeight); SetRect(&bdyrC23,bdyBorderLeftWidth+bdyCBottom1Width,bdyHeight-bdyBorderBottomHeight,bdyWidth-bdyBorderRightWidth-bdyCBottom2Width,bdyHeight); SetRect(&bdyrC31,0,bdyCaptionHeight,bdyBorderLeftWidth,bdyCaptionHeight+bdyCLeft1Height); SetRect(&bdyrC32,0,bdyHeight-bdyCLeft2Height,bdyBorderLeftWidth,bdyHeight); SetRect(&bdyrC33,0,bdyCaptionHeight+bdyCLeft1Height,bdyBorderLeftWidth,bdyHeight-bdyCLeft2Height); SetRect(&bdyrC41,bdyWidth-bdyBorderRightWidth,bdyCaptionHeight,bdyWidth,bdyCaptionHeight+bdyCRight1Height); SetRect(&bdyrC42,bdyWidth-bdyBorderRightWidth,bdyHeight-bdyCRight2Height,bdyWidth,bdyHeight); SetRect(&bdyrC43,bdyWidth-bdyBorderRightWidth,bdyCaptionHeight+bdyCRight1Height,bdyWidth,bdyHeight-bdyCRight2Height); return true; } void CLjfDialogInfo::SetWindRect(HWND hWnd,CBitmap* pBitmapWnd,CLjfDialogPrivateInfo *_p) { GetWindowRect(hWnd,&_p->rWnd);//整個窗口的相對于屏幕的矩形 int iWndWidth=_p->rWnd.right-_p->rWnd.left; int iWndHeight=_p->rWnd.bottom-_p->rWnd.top; int iEWidth = iWndWidth-bdyWidth; int iEHeight = iWndHeight - bdyHeight; //在窗體圖片上的相對位置 SetRect(&_p->rwndbtnMin ,bdyWidth-btnRightspace-3*btnWidth-2*btnInspace,btnTopspace,bdyWidth-btnRightspace-2*btnWidth-2*btnInspace,btnTopspace+btnHeight); SetRect(&_p->rwndbtnMax ,bdyWidth-btnRightspace-2*btnWidth-btnInspace ,btnTopspace,bdyWidth-btnRightspace-btnWidth-btnInspace,btnTopspace+btnHeight); SetRect(&_p->rwndbtnClose,bdyWidth-btnRightspace-btnWidth,btnTopspace,bdyWidth-btnRightspace,btnTopspace+btnHeight); //窗口實例上的位置 OffsetRect(&_p->rwndbtnClose,iEWidth,0); OffsetRect(&_p->rwndbtnMax,iEWidth,0); OffsetRect(&_p->rwndbtnMin,iEWidth,0); _p->rwndC11=bdyrC11; _p->rwndC12=bdyrC12; _p->rwndC13=bdyrC13; _p->rwndC21=bdyrC21; _p->rwndC22=bdyrC22; _p->rwndC23=bdyrC23; _p->rwndC31=bdyrC31; _p->rwndC32=bdyrC32; _p->rwndC33=bdyrC33;
_p->rwndC41=bdyrC41; _p->rwndC42=bdyrC42; _p->rwndC43=bdyrC43; OffsetRect(&_p->rwndC11,0,0); OffsetRect(&_p->rwndC12,iEWidth,0); _p->rwndC13.right+=iEWidth; OffsetRect(&_p->rwndC21,0,iEHeight); OffsetRect(&_p->rwndC22,iEWidth,iEHeight); OffsetRect(&_p->rwndC23,0,iEHeight); _p->rwndC23.right+=iEWidth; OffsetRect(&_p->rwndC31,0,0); OffsetRect(&_p->rwndC32,0,iEHeight); _p->rwndC33.bottom+=iEHeight;
OffsetRect(&_p->rwndC41,iEWidth,0); OffsetRect(&_p->rwndC42,iEWidth,iEHeight); OffsetRect(&_p->rwndC43,iEWidth,0); _p->rwndC43.bottom+=iEHeight; SetRect(&_p->rwndCaption,capLeftspace,capTopspace,_p->rwndbtnMin.left-5,bdyCaptionHeight); } void CLjfDialogInfo::SetLjfWindowRgn(HWND hWnd,CLjfDialogPrivateInfo *_p) { CRgn rgnWnd; rgnWnd.CreateRectRgn(0,0,_p->rWnd.right-_p->rWnd.left,_p->rWnd.bottom-_p->rWnd.top); CRgn rgnTran;rgnTran.CreateRectRgn(0,0,0,0);rgnTran.CopyRgn(&rgnBmpTran); int iEWidth = _p->rWnd.right-_p->rWnd.left-bdyWidth; int iEHeight = _p->rWnd.bottom-_p->rWnd.top - bdyHeight; CRgn rgnTopLeft; rgnTopLeft.CreateRectRgn(bdyrC11.left,bdyrC11.top,bdyrC11.right,bdyrC11.bottom); rgnTopLeft.CombineRgn(&rgnTopLeft,&rgnTran,RGN_AND); CRgn rgnTopRight; rgnTopRight.CreateRectRgn(bdyrC12.left,bdyrC12.top,bdyrC12.right,bdyrC12.bottom); rgnTopRight.CombineRgn(&rgnTopRight,&rgnTran,RGN_AND); rgnTopRight.OffsetRgn(iEWidth,0); CRgn rgnBottomLeft; rgnBottomLeft.CreateRectRgn(bdyrC32.left,bdyrC32.top,bdyrC32.right,bdyrC32.bottom); rgnBottomLeft.CombineRgn(&rgnBottomLeft,&rgnTran,RGN_AND); rgnBottomLeft.OffsetRgn(0,iEHeight); CRgn rgnBottomRight; rgnBottomRight.CreateRectRgn(bdyrC42.left,bdyrC42.top,bdyrC42.right,bdyrC42.bottom); rgnBottomRight.CombineRgn(&rgnBottomRight,&rgnTran,RGN_AND); rgnBottomRight.OffsetRgn(iEWidth,iEHeight); rgnTran.DeleteObject();rgnTran.CreateRectRgn(0,0,0,0); rgnTran.CombineRgn(&rgnTran,&rgnTopLeft,RGN_OR); rgnTran.CombineRgn(&rgnTran,&rgnTopRight,RGN_OR); rgnTran.CombineRgn(&rgnTran,&rgnBottomLeft,RGN_OR); rgnTran.CombineRgn(&rgnTran,&rgnBottomRight,RGN_OR); rgnWnd.CombineRgn(&rgnWnd,&rgnTran,RGN_DIFF); SetWindowRgn(hWnd,rgnWnd,true); } void CLjfDialogInfo::PreparBitmapTranRgn(CBitmap* pBitmap) { CDC dcImage;dcImage.CreateCompatibleDC (NULL);dcImage.SelectObject (pBitmap); COLORREF clTransparent=dcImage.GetPixel(0, 0);//第一行第一列的像素為透明參考色。 CRect r(0,0,bdyWidth,bdyHeight);
CRgn rgnTra;rgnTra.CreateRectRgn(0,0,0,0); for (int y=r.top; y<=r.bottom; y++)//遍歷r所在的行 { ?? if (y<=bdyrC11.bottom || y>=max(bdyrC32.top,bdyrC42.top)) ?? { ??? for (int x=r.left; x<r.right; x++)//遍歷r所在的列 ??? { ???? if (x<=bdyrC11.right || x>=bdyrC12.left) ???? { ????? if (dcImage.GetPixel(x, y) == clTransparent)//透明 ????? { ?????? CRgn rgnAdd; ?????? rgnAdd.CreateRectRgn (r.left+x,r.top+y, r.left+x+1, r.top+y+1); ?????? rgnTra.CombineRgn (&rgnTra, &rgnAdd, RGN_OR); ?????? rgnAdd.DeleteObject(); ????? } ???? } ??? } ?? } } rgnBmpTran.DeleteObject(); rgnBmpTran.CreateRectRgn(0,0,0,0); rgnBmpTran.CopyRgn(&rgnTra); } ljfIni.h: class CLjfIni { public: CLjfIni(CString filename); CString GetString(CString Section,CString Key,CString sDefault); bool SetString(CString Section,CString Key,CString sValue); int GetInt(CString Section,CString Key,int iDefault); bool SetInt(CString Section,CString Key,int iValue); private: CString m_sFileName; bool GetFilePath(char * c); }; #include "stdafx.h" #include "ljfIni.h" CLjfIni::CLjfIni(CString filename){ m_sFileName=filename; } CString CLjfIni::GetString(CString Section,CString Key,CString sDefault){ CString sReturn; try{ ?? LPTSTR lpszm_sFilePath = new TCHAR[MAX_PATH]; ?? GetFilePath(lpszm_sFilePath); ?? GetPrivateProfileString(Section,Key,sDefault, ??? sReturn.GetBuffer(MAX_PATH),MAX_PATH,lpszm_sFilePath); } catch (...) { ?? sReturn="error"; } return sReturn; } bool CLjfIni::SetString(CString Section,CString Key,CString sValue){ LPTSTR lpszm_sFilePath = new TCHAR[MAX_PATH]; GetFilePath(lpszm_sFilePath); BOOL bResult=WritePrivateProfileString(Section,Key,sValue,lpszm_sFilePath); if (bResult == FALSE) return false; return true; } int CLjfIni::GetInt(CString Section,CString Key,int iDefault){ int iReturn; try{ ?? LPTSTR lpszm_sFilePath = new TCHAR[MAX_PATH]; ?? GetFilePath(lpszm_sFilePath); ?? iReturn=GetPrivateProfileInt(Section,Key,(INT)iDefault,lpszm_sFilePath); } catch (...) { ?? iReturn=-1; } return iReturn; } bool CLjfIni::SetInt(CString Section,CString Key,int iValue){ CString siValue; siValue.Format("%d",iValue); return SetString(Section,Key,siValue); } bool CLjfIni::GetFilePath(char * c) { char pBuf[MAX_PATH];GetModuleFileName(NULL, pBuf, MAX_PATH); (_tcsrchr(pBuf, _T('\\')))[1] = 0; sprintf(c,"%s\\%s",pBuf,m_sFileName); return true; } |