当前位置: 首页 > 图文教程 > 开发语言 > 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   浏览: 110 ::
收藏到网摘: n/a

支持换肤功能的窗口实例
译者:李不言
原文来源:codeproject

下载本文示例代码

这个例子展示了如何绘制定制(自绘)窗口框架(包括标题、边框等)。


一、前言
如今,支持定制皮肤功能的软件越来越流行。这样用户就可以自己修改程序的外观。甚至Windows操作系统本身做到这点了。Windows XP提供的主题(theme)技术可以修改窗口、按钮、滚动条等的外观。

最近,我想用MFC设计一个可以换肤的程序。在网上我没有搜索到任何想要的东西,所以我决定自己写一个。这不是一个很难的问题,但是需要对Windows操作系统的绘制窗口的机制比较熟悉。

二、背景
我提供了下面的一些类:

1. CSkinWin----CSkinWin类是一个绘制定制(自绘)窗口的类。它绘制窗口上、下、左、右边框和标题栏按钮如最大化、关闭按钮。为了作到这一点,CSkinWin类从一个ini文件读入配置信息,在ini文件配置窗口各边框的位图。需要指出的是,ini文件的格式是从Windows Blinds(Stardock的杰作)的UIS格式拷贝过来的,因为我希望在我的程序里支持Windows Blinds的主题。

2. CSkinButton---CSkinButton类是绘制定制(自绘)按钮的类。它用四个位图分别代表正常、有焦点、按下和无效状态。位图格式也是Windows Blinds格式,参数在同一个ini文件中定义。因为一个窗口会有多个按钮实例,所以我设计了CSkinButtonResource类来存放定制(自绘)按钮的皮肤。

3. CMyBimtap 等--- 一些相关类,其中有些是来自Codeproject. 尽管我已经不记得这些作者了,但我还是要感谢它们.

三、用法

这些代码的用法很直接。我包含了一个MFC基于窗口的工程,关键代码列在下面。顺便提一下,这些代码在单文档的工程里也测试通过了。
//defines the following member in the dialog class	CSkinButtonResource	m_btnres;	//skin button resource	CSkinWin	m_skinWin;	//skin win	BOOL	m_bFirst;	//first time call	CObList m_wndList;	//hold button instance//In OnInitDialog	m_bFirst = TRUE;	SetSkin( "skin\\neostyle\\theme.ini" );//SetSkin is a function to change skinBOOL CSkinTestDlg::SetSkin(CString file){	m_skinWin.LoadSkin( file );	//load skin bitmap and parameters	m_btnres.LoadSkin( file );	if ( m_bFirst )	{	//if it''s the first time call, InstallSkin	m_skinWin.InstallSkin( this );	//call EnumChildWindows to subclass all buttons	EnumChildWindows( m_hWnd, EnumChildProc, (LPARAM)this );	m_bFirst = FALSE;	}	//redraw window after change skin	SetWindowPos( 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |SWP_FRAMECHANGED );	return TRUE;}//enum child window and take chance to subclass them#define GetWindowStyle(hwnd) ((DWORD)GetWindowLong(hwnd, GWL_STYLE))BOOL CALLBACK EnumChildProc( HWND hwnd, // handle to child window	LPARAM lParam // application-defined value	){	char classname[200];	CSkinTestDlg *dlg = (CSkinTestDlg *)lParam;	DWORD style;	GetClassName( hwnd, classname, 200 );	style = GetWindowStyle( hwnd );	if ( strcmp( classname, "Button" ) == 0 )	{	style = (UINT)GetWindowLong(hwnd, GWL_STYLE) & 0xff;	if ( style == BS_PUSHBUTTON || style == BS_DEFPUSHBUTTON )	dlg->SubClassButton( hwnd );	}	return TRUE;}//subclass push buttonsBOOL CSkinTestDlg::SubClassButton( HWND hwnd ){	CSkinButton * btn = new CSkinButton();	CWnd* pWnd = CWnd::FromHandlePermanent(hwnd);	if ( pWnd == NULL)	{	btn->SubclassWindow( hwnd );	btn->SetResource( &m_btnres );	return TRUE;	}	return FALSE;}//free CSkinButton instancesvoid CSkinTestDlg::OnDestroy() {	CDialog::OnDestroy();	// TODO: Add your message handler code here	POSITION pos;	pos = m_wndList.GetHeadPosition();	while( pos )	{	CObject *ob = m_wndLis