当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 关于如何换肤、子类化的解决方案

VC++
用VC实现支持多语言的程序
用鼠标手势动作来发送命令
在VC中使用MATLAB C/C++函数库
水晶报表在VC++6.0中的简单使用方法
关于限次软件的制作
可定制大小和数量的随机数函数
用vc.net实现记录开关机时间的程序
隐藏你的鼠标
一个黑客程序开发实例 -- IE终结者
修改QQ的程序
ACE自适配通信环境
超频软件原理探析
OutlookGrid:以Outlook样式分组和排列数据项(C#)
遍历和查找外部程序 Tree-View 中的项目
用 Win API 实现自绘按钮类
VC++ 6.0使用复选框和单选钮
对C#中的TreeView加背景图
在MFC中应用CTreeCtrl控件的技巧
CSortListCtrl 加强版
使用 VC.net 轻松实现按钮控件自绘

VC++ 中的 关于如何换肤、子类化的解决方案


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 116 ::
收藏到网摘: n/a

关于如何换肤、子类化的解决方案

作者:[email protected]

  对于应用程序的换肤及子类化。下面是我尝试过一些方法,以在CAboutDlg中子类化其中的Button为例:

第一种:直接用现成的类

1、自己写一个类class CButtonXP : public CButton{/*...*/}

用MessageMap处理感兴趣的消息。

2、用CButtonXP代替CButton来声明变量m_btn;

3、在void CAboutDlg:DoDataExchange(CDataExchange* pDX)中加上一句:

DDX_Control(pDX, IDB_BUTTON1, m_edit);

或者在 InitDialog() 中加上

m_btn.SubclassDlgItem(IDB_BUTTON1, this);

这两种效果差不多的。

第二种:在 Hook 中使用现成的类

1、自己写一个类 class CButtonXP : public CButton{/*...*/}

用 MessageMap 处理感兴趣的消息。

2、使用 SetWindowsHookEx 安装一个钩子:

g_hWndProcHook = ::SetWindowsHookEx(WH_CALLWNDPROC,WndProcHook,NULL,::GetCurrentThreadId());

3、在 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);} 
4、在 BeginSubclassing 中用 GetClassName 得到类名,例如 "Button",然后用 CButtonXP 类进行子类化。
CButtonXP pButton = new CButtonXP;VERIFY(pButton ->SubclassWindow(hWnd));

第三种 在Hook中使用窗口过程

1、自己写一个按钮的窗口过程

WNDPROC oldProc;LRESULT CALLBACK ProcButton(HWND hWnd,	UINT uMsg,	WPARAM wParam,	LPARAM lParam){	ASSERT(oldProc != 0);	if (oldProc == 0) return TRUE;	switch (uMsg)	{	case WM_ERASEBKGND:	break;	//......	default:	break;	}	return CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);} 
2、同第二种
3、同第二种

4、在 BeginSubclassing 中得到类名后,用 SetWindowLong 的方式子类化:
oldProc = (WNDPROC) GetWindowLong(hWnd, GWL_WNDPROC);SetWindowLong(hWnd, GWL_WNDPROC, (LONG) ProcButton); 
第四种:不用 Hook

在一个对话框的 OnInitDialog 中枚举它的所有子窗体,例如用下面两句来实现:
hWnd=GetWindow(hDlg,GW_CHILD); hWnd=GetWindow(hWnd,GW_HWNDNEXT);

对每个子窗体进行子类化处理,处理过程同第二种与第三种。

第五种:如果是在XP下运行,可以使用manifest,也就是如下的一个XML文件
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity name="Microsoft.Windows.XXXX" processorArchitecture="x86" version="5.1.0.0" type="win32"/> <description>Windows Shell</description> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"/> </dependentAssembly> </dependency> </assembly> 
  把它存为应用程序名 .manifest,放到和应用程序对应的目录下,或者把它作为资源类型为24的资源编译进应用程序中。这样程序在XP下就自动拥有了XP的风格。

第六种:使用第三方的库Skin++(www.uipower.com)实现换肤

第七种:用第三方应用程序给整个windows换肤(windowblinds)

  以上七种方式各有优缺点。我在使用过程中也遇到不少问题,现在一一道来,希望和大家共同解决问题。先排除几种不准备深入探讨的方式: