關於如何換膚子類化的解決方案
對於應用程序的換膚及子類化下面是我嘗試過一些方法以在CAboutDlg中子類化其中的Button為例
第一種直接用現成的類
自己寫一個類class CButtonXP : public CButton{/**/}
用MessageMap處理感興趣的消息
用CButtonXP代替CButton來聲明變量m_btn;
在void CAboutDlg:DoDataExchange(CDataExchange* pDX)中加上一句
DDX_Control(pDX IDB_BUTTON m_edit);
或者在 InitDialog() 中加上
m_btnSubclassDlgItem(IDB_BUTTON this);
這兩種效果差不多的
第二種在 Hook 中使用現成的類
自己寫一個類 class CButtonXP : public CButton{/**/}
用 MessageMap 處理感興趣的消息
使用 SetWindowsHookEx 安裝一個鉤子
g_hWndProcHook = ::SetWindowsHookEx(WH_CALLWNDPROCWndProcHookNULL::GetCurrentThreadId());
在 WndProcHook 中處理窗口創建和銷毀的消息
LRESULT CALLBACK WndProcHook(int code WPARAM wParam LPARAM lParam){ if (code == HC_ACTION) { switch (((CWPSTRUCT*) lParam)>message) { case WM_CREATE: BeginSubclassing(((CWPSTRUCT*) lParam)>hwnd); break; case WM_NCDESTROY: // TODO: clear subclass info EndSubclassing(((CWPSTRUCT*) lParam)>hwnd); break; default: break; } } return CallNextHookEx(g_hWndProcHook code wParam lParam);}
在 BeginSubclassing 中用 GetClassName 得到類名
例如 "Button"
然後用 CButtonXP 類進行子類化
CButtonXP pButton = new CButtonXP;VERIFY(pButton >SubclassWindow(hWnd));
第三種 在Hook中使用窗口過程
自己寫一個按鈕的窗口過程
WNDPROC oldProc;LRESULT CALLBACK ProcButton(HWND hWnd UINT uMsg WPARAM wParam LPARAM lParam){ ASSERT(oldProc != ); if (oldProc == ) return TRUE; switch (uMsg) { case WM_ERASEBKGND: break; // default: break; } return CallWindowProc(oldProc hWnd uMsg wParam lParam);}
同第二種
同第二種
在 BeginSubclassing 中得到類名後
用 SetWindowLong 的方式子類化
oldProc = (WNDPROC) GetWindowLong(hWnd GWL_WNDPROC);SetWindowLong(hWnd GWL_WNDPROC (LONG) ProcButton);
第四種不用 Hook 在一個對話框的 OnInitDialog 中枚舉它的所有子窗體
例如用下面兩句來實現
hWnd=GetWindow(hDlgGW_CHILD); hWnd=GetWindow(hWndGW_HWNDNEXT);
對每個子窗體進行子類化處理處理過程同第二種與第三種
第五種如果是在XP下運行可以使用manifest也就是如下的一個XML文件 <?xml version="" encoding="UTF" standalone="yes"?> <assembly xmlns="urn:schemasmicrosoftcom:asmv" manifestVersion=""> <assemblyIdentity name="MicrosoftWindowsXXXX" processorArchitecture="x" version="" type="win"/> <description>Windows Shell</description> <dependency> <dependentAssembly> <assemblyIdentity type="win" name="MicrosoftWindowsCommonControls" version="" processorArchitecture="x" publicKeyToken="bccfdf" language="*"/> </dependentAssembly> </dependency> </assembly>
把它存為應用程序名
manifest
放到和應用程序對應的目錄下
或者把它作為資源類型為
的資源編譯進應用程序中
這樣程序在XP下就自動擁有了XP的風格
第六種使用第三方的庫Skin++()實現換膚 第七種用第三方應用程序給整個windows換膚(windowblinds) 以上七種方式各有優缺點
我在使用過程中也遇到不少問題
現在一一道來
希望和大家共同解決問題
先排除幾種不准備深入探討的方式
From:http://tw.wingwit.com/Article/program/c/201401/30250.html