关于如何换肤子类化的解决方案 对于应用程序的换肤及子类化下面是我尝试过一些方法以在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) 以上七种方式各有优缺点我在使用过程中也遇到不少问题现在一一道来希望和大家共同解决问题先排除几种不准备深入探讨的方式 |