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

VC++
VC++ 的常用编程技巧
VC++编译环境详解
Visual C++制作一个Sniffer实例
vc.net中实现启动画面来个淡入淡出效果
VC++中进程间相互通信的十一种方法
深入了解VC++编译器
VC++删除浮动工具条中“关闭”按钮
VISUAL C++中的OCX控件的使用方法
VC++:用VC++实现上网拨号功能
VC++:基于VC++中ATL创建ActiveX控件的探讨
VC++删除浮动工具条中“关闭”按钮
VC++:VC++中的面向对象和Windows编程
VC++:Vc++中线程的同步
VC++:更新命令用户接口(UI)消息
VC++:CDatabase类的那些事
VC++:小编谈VC++中 CDatabase类的那些事
VC++:小编泛谈MFC的ODBC类
VC++:小编分享线程的创建和终止
在VC资源文件中加入声音资源
C++的static关键字

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 43 ::
收藏到网摘: 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