当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 为你的程序换个皮肤

VC++
在类VC的界面实现中加入目录树
软件换肤技术在 BCB 中的实现
利用非模窗口生成MDI介面
报表输出轻松搞定
Windows 中不规则窗体的编程实现
解说Win32的窗口子类化
使用测试优先方法开发用户界面
一个简单的登录对话框的实现
一个简单的日记本程序
从资源中加载皮肤
一个在RichEdit中添加表情图象的类
ActiveSkin 4.3 软件换肤在VC中的实现
一种另类“关于(About)”对话框的动态显示方法
对话框打印预览及打印
关于如何换肤、子类化的解决方案
制作 MSN、QQ 的消息提示窗口
如何对 BCGControlBarPro 进行换肤
定制个性化的对话框窗口类
改变窗口中的光标形状
更新MFC中的视图,跟踪.NET Framework中的事件

VC++ 中的 为你的程序换个皮肤


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

为你的程序换个皮肤


作者/Kilo
 

下载源代码

(C)CopyRight, 2003-2004, IRS, All Rights Reserved


  目前这方面的小软件很多,我一直就想做这么一个东东,但是一直苦于时间有限,一直都没有做。最近一段时间,我发现这些方面的东西越来越多,而且都没有源代码,一些家伙在网站上给出这样那样的示例,其实都是在为自己的产品做广告,实在有违开源的思想。
  最近终于有了一段假期,反正没什么事做就来试试,经过一段时间的学习和摸索,终于实现了一段简单的程序。现在我就给出一个简单的例子和解释,让大家明白这是一个怎么回事,教你如何利用这个技术给一个按钮换肤?
  以前我们一直利用重载一个类的办法来实现丰富多彩的个性化控件,如GuiToolkit、CJ60LIB,都是这样的工具,使用起来还是要在程序中插入大量的语句,这样做一方面增加了程序的复杂性,另一方面也增加了程序高度的难度。当然现在也有像SkinMagic、EasySkin这样的工具,只需要在你的程序里增加两行代码就可以实现对常用控件的换肤,但是这些工具都没有源代码,对于想学习开发的人来说实在没什么帮助。为了让大家都了解这项技术,我决定开发一个这样的程序,并公布源程序,希望有兴趣的朋友都来看看,动手做做,同时欢迎大家公开你的源程序,和大家一起分享你的成功和快乐。
  首先,来给一个程序换肤,我们必须得到程序的句柄,然后给程序挂钩。下面的一段代码就实现了挂钩功能。

BOOL IRStartup( HINSTANCE hModule, DWORD dwThreadID ){	globalWndHookEx = SetWindowsHookEx(	WH_CALLWNDPROC, (HOOKPROC) IRCallWndProc, hModule, dwThreadID );	return TRUE;} 
这也是像SkinMagic一类工具的初始化函数。当然在退出时也要释放钩子的。
BOOL IRComplete( void ){	UnhookWindowsHookEx( globalWndHookEx );	return TRUE;} 
接下来,就是IRCallWndProc这个回调函数的编写,这是至关重要的一个环节,这个函数就是对所要换肤的类对象进行了监视,并改变其消息处理函数,实现换肤的目的。
LRESULT CALLBACK IRCallWndProc( int nCode, WPARAM wParam, LPARAM lParam ){	PCWPSTRUCT	pcs = (PCWPSTRUCT) lParam;	HWND	hWnd = pcs->hwnd;	if( hWnd ) {	char	sClassName[201] = "\0";	GetClassName( hWnd, sClassName, 200 );	if( strcmp( sClassName, "Button" ) == 0 ) {	CWnd	*pWnd = CWnd::FromHandle( hWnd );	DWORD	dwStyle = pWnd->GetStyle();	if( dwStyle == 0x50010000 ) {	WNDPROC	WndProc;	WndProc = (WNDPROC) GetWindowLong( hWnd, GWL_WNDPROC );	if( CButtonExt::m_cWndProc != NULL && \	WndProc != CButtonExt::m_cWndProc )	{	return CallNextHookEx( globalWndHookEx, nCode, wParam, lParam );	}	if( WndProc != (WNDPROC) CButtonExt::DefWindowProc ) {	WndProc = (WNDPROC) SetWindowLong( hWnd, GWL_WNDPROC, (LONG) CButtonExt::DefWindowProc );	CButtonExt::m_cWndProc = WndProc;	}	}	}	}	return CallNextHookEx( globalWndHookEx, nCode, wParam, lParam );} 
这样就对按钮的消息进行了挂钩处理了,就可以重新来绘制按钮了。紧接着就是给出按钮控件的绘制方法,我是用一个类来实现的,都是使用的静态函数直接调用的。
	#define STATUS_BUTTON_NORMAL	0x00000000#define STATUS_BUTTON_HOVER	0x00000001#define STATUS_BUTTON_DOWN	0x00000002class CButtonExt{public:	CButtonExt() {}	~CButtonExt() {}	static UINT	m_nStatus;	static WNDPROC	m_cWndProc;	static LRESULT DefWindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )	{	CWnd	*pWnd = NULL;	CPoint	point;	pWnd = CWnd::FromHandle( hWnd );	switch( message )	{	case WM_PAINT:	return OnPaint( pWnd );	break;	case WM_LBUTTONDOWN:	point.x = LOWORD(lParam);	point.y = HIWORD(lParam);	return OnLButtonDown( pWnd, 0, point );	break;	case WM_LBUTTONUP:	point.x = LOWORD(lParam);	point.y = HIWORD(lParam);	return OnLButtonUp( pWnd, 0, point );	break;	case WM_LBUTTONDBLCLK:	point.x = LOWORD(lParam);	point.y = HIWORD(lParam);	return OnLButtonDblClk( pWnd, 0, point );	break;	case WM_MOUSEMOVE:	point.x = LOWORD(lParam);	point.y = HIWORD(lParam);	return OnMouseMove( pWnd, 0, point );	break;	defa