软件换肤

     我一般给软件加上换肤功能,都是采用上海勇进公司的SKIN产品,调用比较简单,可以实习任意的换肤。现在直接来写。。

 

由于换肤功能是对程序框架的扩展,所以相关处理代码理所当然地要在主框架类中进行。为了使程序能具备换肤的能力,必须首先使程序具备换肤的基本条件。首先可以明确的是:处理对象为普通的工具条,其基类为CToolBar。通过MSDN帮助可以了解到该类及其"近亲"的继承关系如图所示。通过对这几个相关类的查阅,可以发现CReBar类比较特殊,它本身并不用于显示,而主要用于包容其他的工具条,例如,可以通过其成员函数AddBar()将工具条(ToolBar)、对话条(DialogBar)等类型的工具条加入到复合条(ReBar),使工具栏中可以显示多个工具条。所以可以得出这样的设计思路:程序框架的工具栏不再直接以工具条来实现,而是以复合条为基础,并通过CReBar的AddBar()函数将原先的工具条加入其中。皮肤则可以通过设置与CReBar相关的REBARBANDINFO结构而平铺于复合条之上,由于有工具条覆于其上,因此必须在创建工具条时修改其风格(Style),使其背景为透明,这样才能透出位于下层的皮肤。

2010052313533344.jpg

  由于在程序设计时使用了CReBar,在普通程序中实现起来比较麻烦,可以在创建工程时在第四步选中"Internet Explorer ReBars"选项,这样创建的工具栏将在复合条上添加一个工具条和一个对话条。只需从主框架类的头文件和实现文件的OnCreate()函数里将对话条CDialogBar的实例对象m_wndDlgBar的声明部分和部分相关代码去除即可。

  接下来在工具条创建时需要特别指定TBSTYLE_TRANSPARENT等窗口风格来使其背景透明,并在创建完复合条后通过AddBar()函数将背景透明的工具条添加其中:

  经过上述几步处理对程序的主框架作了改造,使其基本具备了动态换肤的必要条件。

m_wndToolBar.CreateEx(this,
TBSTYLE_FLAT|TBSTYLE_TRANSPARENT,
WS_CHILD|WS_VISIBLE|CBRS_ALIGN_TOP,
CRect(0,0,0,0),AFX_IDW_TOOLBAR)
……
m_wndReBar.AddBar(&m_wndToolBar,
NULL,NULL,
RBBS_GRIPPERALWAYS|RBBS_FIXEDBMP|RBBS_BREAK)

  皮肤的装载与动态更换

  皮肤一般是以外部资源的形式发布,在使用时再由程序动态装载。皮肤加载到工具栏的过程大致可分两步:先将皮肤从文件装载到内存,然后再由内存位图直接绘制到复合条上去。对于第一步,可用API函数LoadImage将外部文件back.bmp从文件按位图的格式装载到内存,返回的句柄可通过强制转换得到HBITMAP型的位图句柄m_bmpBack:

 m_bmpBack=(HBITMAP)LoadImage(AfxGetInstanceHandle(), //应用程序实例句柄
"back.bmp",IMAGE_BITMAP,0,0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION);

 皮肤装载到内存后,需要通过对REBARBANDINFO结构进行设置,才能实现皮肤位图在复合条中的平铺,该结构有二十多个成员变量,但在此只是用于设置背景位图的平铺,因此只需设置fMask为RBBIM_BACKGROUND以指定hbmBack有效,并将前面装载到内存的位图句柄m_bmpBack传递给该成员变量就完成了对皮肤的装载与显示,下面就是这部分实现的详细代码:

 CReBarCtrl& rc=m_wndReBar.GetReBarCtrl(); //获取复合条控件指针
REBARBANDINFO info;
memset(&info,0,sizeof(REBARBANDINFO)); //清零
info.cbSize=sizeof(info);
info.fMask=RBBIM_BACKGROUND; //指定hbmBack有效
//如果位图句柄不可用则仍为银灰色背景,否则以此位图作为复合条的背景
info.hbmBack=m_bmpBack!=INVALID_HANDLE_VALUE?m_bmpBack:NULL;
rc.SetBandInfo(0,&info); //进行设置
rc.UpdateWindow(); //更新窗口

 当皮肤已经显示到工具栏上而对其进行动态更换,则只需要简单的调用拷贝文件函数将新的皮肤插件以覆盖的形式复制到back.bmp,并再次调用上述两步对新的皮肤插件进行重新装载即可实现对程序的动态皮肤更换。拷贝文件函数一般用API函数CopyFile()来实现,该函数的前两个参数分别为源文件路径和目的文件路径。最后一个布尔型参数指定文件拷贝的方式,在此需要指定为FALSE,即如果目的文件已存在则对其覆盖,否则将无法实现对皮肤的更换。

  小结

  本文通过对复合条及CReBar类的使用实现了在VC下对应用程序的动态皮肤更换。CReBar类的功能非常丰富,本文限于篇幅未能做深入的介绍,关于该类的详细情况请参阅微软公司的MSDN帮助。本文所述程序在Windows下,由Microsoft Visual C++ 6.0编译通过。

转载于:https://www.cnblogs.com/lpbolg/archive/2010/05/23/1742031.html

目前这方面的软件很多,但大部分都是收费的,不收费大部分又换的不全,对于一个学生来说花钱买是有些奢侈了,所以我一直就想做一个换肤软件提供给学生,让他们做课程设计或毕业设计时能轻易给自己软件美化界面。 但是一直苦于时间有限。工作太忙有时只能在周末或晚上写上两行代码。现在终于成形了本打算开源,但是有些地方还不完善(现只支持VC MFC, Windows Type: Dialog, SDI),所以现在只讲下原理,提供部分源码供感兴趣的人研究。现在发出来与大家共享。 现在商业的换肤软件大部分都是采用的Hook技术(呵呵,猜的,也许采用的更高深的技术)。Hook窗体消息,对窗体消息进行截获最终换成自已的处理方式。所以本人写的SkinMaster也是采用了同样的技术原理。说很简单但做起来有些困难。下面是我做Skin时遇到的问题及处理方式。 1.对于Windows基本控件进行Hook则可完成绘制。 2.对于菜单会制则有些麻烦,程序运行时窗体菜单WM_MEASUREITEM只运行一次,所以会出现在动态换另一套皮肤时菜单项大小不会跟据皮肤改变,解决方法是所有菜单你要动态生成。 3.主窗体的绘制,没啥太深技术就是要处理大量的消息。 4.滚动条的绘制,滚动条全靠Hook消息就没办法完成了,这个东西微软做的不像基本控件那样工作,还要对滚动条的API进行Hook。 先写这些,有时间我会把更详细的方法给大家写出来。下面程序中TestSkin程序提供源码,并完成了按钮等控件的换肤
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值