茂名市电白地图:用VC编写具有动态换肤功能的应用程序
来源:百度文库 编辑:中财网 时间:2024/05/08 13:25:44
摘要: 本文介绍了一种为应用程序工具条添加及动态更换皮肤的程序设计方法。
引言
如果能在自己的程序中也具备动态更换皮肤的能力,将使软件平添几分亮点从而更易博得用户的青睐。具笔者了解,当前介绍这种技术的文章资料较少,与其流行程度很不协调,而且现有的少量资料也多是针对对话框进行的,无非是在对话框上覆盖一层图片,并通过更换图片来实现程序的动态换肤。虽然这也是动态换肤的一种,但由于技术过于简单,本文将着重介绍另外一种动态换肤技术--工具栏的动态换肤技术,这也是IE浏览器等软件所普遍采用的一种换肤技术。
程序支持动态换肤
由于换肤功能是对程序框架的扩展,所以相关处理代码理所当然地要在主框架类中进行。为了使程序能具备换肤的能力,必须首先使程序具备换肤的基本条件。首先可以明确的是:处理对象为普通的工具条,其基类为CToolBar。通过MSDN帮助可以了解到该类及其"近亲"的继承关系如图所示。通过对这几个相关类的查阅,可以发现CReBar类比较特殊,它本身并不用于显示,而主要用于包容其他的工具条,例如,可以通过其成员函数AddBar()将工具条(ToolBar)、对话条(DialogBar)等类型的工具条加入到复合条(ReBar),使工具栏中可以显示多个工具条。所以可以得出这样的设计思路:程序框架的工具栏不再直接以工具条来实现,而是以复合条为基础,并通过CReBar的AddBar()函数将原先的工具条加入其中。皮肤则可以通过设置与CReBar相关的REBARBANDINFO结构而平铺于复合条之上,由于有工具条覆于其上,因此必须在创建工具条时修改其风格(Style),使其背景为透明,这样才能透出位于下层的皮肤。
由于在程序设计时使用了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 98下,由Microsoft VisualC++ 6.0编译通过。
引言
如果能在自己的程序中也具备动态更换皮肤的能力,将使软件平添几分亮点从而更易博得用户的青睐。具笔者了解,当前介绍这种技术的文章资料较少,与其流行程度很不协调,而且现有的少量资料也多是针对对话框进行的,无非是在对话框上覆盖一层图片,并通过更换图片来实现程序的动态换肤。虽然这也是动态换肤的一种,但由于技术过于简单,本文将着重介绍另外一种动态换肤技术--工具栏的动态换肤技术,这也是IE浏览器等软件所普遍采用的一种换肤技术。
程序支持动态换肤
由于换肤功能是对程序框架的扩展,所以相关处理代码理所当然地要在主框架类中进行。为了使程序能具备换肤的能力,必须首先使程序具备换肤的基本条件。首先可以明确的是:处理对象为普通的工具条,其基类为CToolBar。通过MSDN帮助可以了解到该类及其"近亲"的继承关系如图所示。通过对这几个相关类的查阅,可以发现CReBar类比较特殊,它本身并不用于显示,而主要用于包容其他的工具条,例如,可以通过其成员函数AddBar()将工具条(ToolBar)、对话条(DialogBar)等类型的工具条加入到复合条(ReBar),使工具栏中可以显示多个工具条。所以可以得出这样的设计思路:程序框架的工具栏不再直接以工具条来实现,而是以复合条为基础,并通过CReBar的AddBar()函数将原先的工具条加入其中。皮肤则可以通过设置与CReBar相关的REBARBANDINFO结构而平铺于复合条之上,由于有工具条覆于其上,因此必须在创建工具条时修改其风格(Style),使其背景为透明,这样才能透出位于下层的皮肤。
由于在程序设计时使用了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 98下,由Microsoft VisualC++ 6.0编译通过。
用VC#编写记事本的保存功能
用vc调用delphi编写的动态库老是出现Access Violation这个错误
关于用VC++/MFC编写天气信息管理应用程序的问题
请问哪里可以下载用VB编写的学生档案管理系统,具有报表打印功能?非常感谢!
VC++是不是很少用于编写数据库应用程序
如何让软件具有换肤功能(VB)
用vc++编写的实现计算器的功能包括:加、减、乘、除、阶乘、正弦、余弦和指数运算。
在VC中如何编写1-100%动态显示的程序
在VC中如何编写向杀毒软件一样的文件动态扫描程序
vc编写动态连接库时,插入对话框遇到的问题?
vc++中用API编写的串口通信,怎样动态更改串口号?
用c语言编写的应用程序
怎样用VC++实现让Enter键具有Tab键的功能?
在vc++中什么函数具有随机产生数字的功能 ?
请问我编写一个同样功能的程序为什么vc的300k,vb20k
VC++是不是一般不用于编写数据库应用程序
怎样用VC编写网络应用程序?(求源码)
怎么用vc编写一个打印机的计数器?
求 用vc++编写埃特金迭代法求解的程序
用VC++编写的程序能用到单片机中吗?
VC++是用什么语言编写的啊?
VC++软件是用什么语言编写的?
不死锁的哲学家问题,用Vc怎么编写
VB与VC++是用什么语言编写的?