动态库实现界面换肤

一:动态载入DLL并获取DLL中函数

//在全局区创建一个函数指针
typedef void (_stdcall* funShowDlg)();//获取动态库,LoadLibrary为动态库文件的存放位置HMODULE hMod=LoadLibrary("../SkinDll/Debug/SkinDll.dll");funShowDlg ShowDlg;if(hMod){//获取动态链接库中ShowDlg函数的地址ShowDlg=(funShowDlg)GetProcAddress(hMod,_T("ShowDlg"));if(ShowDlg)ShowDlg();FreeLibrary(hMod);}

二:在动态链接库中载入位图

//AfxGetResourceHandle用于获取当前资源模块句柄,
//而AfxSetResourceHandle则用于设置程序目前要使用的资源模块句柄。
//为了程序能够访问动态链接库中的位图资源,动态库需要使用静态连接MFCHBITMAP GetBmpResourceFromDll()
{return LoadBitmap(AfxGetResourceHandle,MAKEINTRESOURCE(IDB_BACKGROUND));//或者使用以下这句//  m_pParts[i].m_hBitmap = //LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(1000+i));
}

处理窗口的WM_CTLCOLOR消息,如果已经加载皮肤文件,则从皮肤文件中加载窗口背景位图,作为窗口的背景位图

CWnd::OnCtlColor
afx_msg HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor );
//返回值:OnCtlColor必须返回一个刷子句柄,该刷子将被用于画出控件的背景。

三:动态库使用
在使用动态库方式加载皮肤文件时候,在主应用程序中如果需要用到DLL中的某个函数,则主应用程序应当存在一个与动态库中需要使用的函数同名的一个纯虚函数(注意主应用程序中是纯虚函数,DLL中的同名函数是虚函数),除此之外,主应用程序中的所有纯虚函数的排列顺序必须与DLL中的虚函数的顺序一致(目的是使虚函数表一致),如果虚函数表不一致,在主应用程序中调用DLL中的函数的时候就会调用到错误的函数甚至访问到不可访问的空间而使程序当掉,有一点还需要注意,虚析构函数一会存在与虚函数表中,也需要注意它的排列顺序,非虚函数和变量则无需考虑顺序,实例如下

//主应用程序里的类
class CSkinManage
{
protected:UINT m_PartCount;    //窗体由几部分组成/******************窗体各部分位图资源********************0,1,2           分别为标题栏的左\中\右3部分3,4,5           分别为左,下,右边框6,7,8,9,10,11   为标题栏普通按钮和热点按钮*********************************************************/CFormPart* m_pParts;public://加载位图资源 virtual HBITMAP GetBitmapRes(UINT Index) = 0;virtual Release() = 0;virtual CPoint GetButtonPos(UINT Index) = 0;virtual BOOL GetDrawRound() = 0;virtual COLORREF GetMenuBKColor() = 0;virtual COLORREF GetMenuSelColor() = 0;public:CSkinManage();virtual ~CSkinManage();
};//DLL中的对应类
class CSkin
{
protected:UINT m_PartCount;  //窗体由几部分组成/******************窗体各部分位图资源索引: *******************0,1,2:         分别为标题栏的左\中\右3部分3,4,5:         分别为左,下,右边框6,7,8,9,10,11: 为标题栏普通按钮和热点按钮12,13:         表示左下角和右下角位图14:            表示背景位图*************************************************************/CFormPart* m_pParts;COLORREF m_MenuBkColor;     //菜单背景颜色COLORREF m_MenuSelColor;    //菜单选中时的颜色BOOL DrawRound;             //是否绘制圆角public://获取位图资源virtual HBITMAP GetBitmapRes(UINT Index){return m_pParts[Index].m_hBitmap;}//释放对象virtual Release(){   delete this;}//获取按钮的位置virtual CPoint GetButtonPos(UINT Index){return  m_pParts[Index].m_Pos;}virtual BOOL GetDrawRound(){return DrawRound;}virtual COLORREF GetMenuBKColor(){return m_MenuBkColor;}virtual COLORREF GetMenuSelColor(){return m_MenuSelColor;}void LoadBitmapRes();       //加载位图资源void SetButtonPos() ;       //设置标题栏按钮的相对位置
public:CSkin();CSkin(UINT PartCount);~CSkin();};

如果把virtual ~CSkinManage();这一句移动到 virtual HBITMAP GetBitmapRes(UINT Index) = 0;这一句前面,整个程序就会当掉,因为你在调用GetBitmapRes(UINT Index)这个函数的时候其实调用的是~CSkinManage()这个函数,结果显然意见

四:菜单默认位置
当窗口Style属性为Resizing时,菜单的左边界肯定为4(在不人为改变菜单位置的情况下);
当窗口Style属性为Dialog Frame时,菜单的左边界肯定为3(在不人为改变菜单位置的情况下)

五:自绘响应函数
OnMeasureItem(..)函数用于设置自绘项的尺寸
OnDrawItem(…)函数用于根据前面得到的尺寸绘制需要自绘的项目

六:消息响应函数OnSysCommand(OnSysCommand(UINT nID, LPARAM lParam)

void CMynetsendDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);

解释:对话框的系统菜单命令,包括关闭对话框,最小化最大化,弹出关于对话框等等,实际上就是向这个对话框发送WM_SYSCOMMAND消息,对话框响应WM_SYSCOMMAND消息,然后根据不同的nID值判断到底是什么系统命令(关闭对话框,最大最小化还是其他什么),这个OnSysCommand
就是用来响应WM_SYSCOMMAND消息,进行相应处理的。
上面的if ((nID & 0xFFF0) == IDM_ABOUTBOX),就是说在需要弹出关于对话框的时候,就进行特别处理(因为在MFC自动生成的基于对话框的工程里面,这个关于对话框也是用户自己可以控制的),所以这时候就自己处理,弹出自己的关于对话框,对于其他的消息,默认不需要用户定制,就直接调用父类的处理就好

七:OnNcCalcSize()消息响应函数
功能:OnNcCalcSize改变标题栏等的高度
在创建窗口时,当收到 WM_NCCALCSIZE 消息时才指定客户区。不管什么时候,只要 Windows 想知道窗口客户区的大小,它便会发送这个消息。
NCCALCSIZE_PARAMS 结构保存三个矩形数组,第一个保存窗口的客户区。
如果改写主窗口的 WM_NCCALCSIZE/OnNcCalcSize,一定要确保调用基类的默认窗口处理例程,以便实现缺省处理。这样程序一运行便会有得到默认的客户区矩形,然后你可以调整其大小。同样,还应该在OnNcPaint/WM_NCPAINT 中调用基类默认的处理过程。否则 Windows 不会绘制边界,滚动栏或其它标准非客户区元素。如果你实现自己的窗口类,像定制工具栏或调色板,其中要计算客户区矩形并进行绘制处理,你可以不必调用基类默认的窗口过程。随便哪种方法,当窗口收到 WM_NCPAINT 消息时,你都得负责绘制整个非客户区。

八:消息响应函数CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
每当主框架窗口的客户区尺寸发生变化或控制条的位置发生变化,需要重新排列客户区时,调用该函数,根据视图客户区尺寸计算视图窗口的尺寸。
我们知道,排列主窗口客户区是由CFrameWnd::RecalcLayout()完成的。显然,视图的CalcWindowRect()函数也是由它触发调用的。主窗口的客户区尺寸减掉所有控制占用的部分,剩下的区域分给视图,这部分区域作为实参传入CalcWindowRect()。在CalcWindowRect()函数内,需要计算视图窗口的尺寸。代码如下:

void CView::CalcWindowRect(LPRECT lpClientRect, UNIT nAdjustType){// lpClientRect此时是整个视图客户区的尺寸// 需要为滚动条增加尺寸吗if (nAdjustType != 0){// 调用API,根据窗口风格计算窗口尺寸::AdjustWindowRectEx(lpClientRect, 0, FALSE, GetExStyle());DWORD dwStyle = GetStyle();if (dwStyle & WS_VSCROLL){// 为垂直滚动条增加尺寸int nAdjust = afxData.csVScroll;if (dwStyle & WS_BORDER)nAdjust -= CX_BORDER;lpClientRect->right += nAdjust;}if (dwStyle & WS_HSCROLL){// 为水平滚动条增加尺寸int nAdjust = afxData.cyHScroll;if (dwStyle & WS_BORDER)nAdjust -= CY_BORDER;lpClientRect->bottom += nAdjust;}return;}// 无需为滚动条增加尺寸,调用基类成员完成计算CWnd::CalcWindowRect(lpClientRect, nAdjustType);}

组件库实现界面换肤
一:OnCtrlColor(HWND hWnd)
如果在某个函数中使用了CWindowDC或者CClientdc这两种画图设备,则无需人工释放(xxx->DeleteDC()),这连个类的析构函数会自动释放创建的画图设备,如果人工释放,会因重复释放而使程序当掉

二:WM_CTRCOLOR
在组件库中需要自己修改窗口过程,然后在窗口过程中有些时候需要使用到WM_CtrlColor消息,笔者在使用的过程中发现单纯的使用WM_CtrlColor消息,则自定义窗口过程函数不会响应这个消息,需要使用WM_CtrlColorDlg或者WM_CtrlColorEdit或者WM_CtrlColorButton,因为笔者在组件库中分别为三种对象修改了窗口过程,单纯使用WM_CtrlColor不会被响应,需要加上类别

界面换肤软件学习笔记相关推荐

  1. 使用免费界面换肤软件 USkin

    使用免费界面换肤软件 USkin 作者:thirdwolf 下载源代码 一.介绍 我们都知道,Skin以前是一项比较难的技术.但至从WindowsXP推出以来,Skin或者说Theme变得很普遍.虽然 ...

  2. vc中使用免费界面换肤软件 USkin

    一.介绍 我们都知道,Skin以前是一项比较难的技术.但至从WindowsXP推出以来,Skin或者说Theme变得很普遍.虽然WindowsXP可以支持Theme,但当我们改变WindowsXP的风 ...

  3. 【QT学习】QSS样式表实现界面换肤(图文详解+源码)

    文章目录 前言 一.实现效果 二.QSS简介及用法 1.什么是QSS? 2.怎么使用QSS? 三.QSS用法一:单个控件调用setStyleSheet函数 四.QSS用法二:编写单个界面.qss文件的 ...

  4. 几种换肤软件使用问题

    几种换肤软件的使用和使用中的BUG                                                                                    ...

  5. Qt之界面换肤的两种方式

    概述 像现在市面上有很多软件都有换肤功能,例如:QQ.360.迅雷等.换肤其实很简单,并没有想象中那么难,下面介绍两种实现换肤的方式,仅供参考! 方式一 1. 实现原理 创建多个QSS文件 首先,根据 ...

  6. SkinLoad程序界面换肤工具

    SkinLoad程序界面换肤工具 作者:耿海增 下载本文示例工程 版本更新SkinLoad v0.3 本文在VC知识库链接 说明:SkinLoad是一个给程序换肤的工具,通过几个简单的函数调用就可以给 ...

  7. SkinMagic——MFC界面换肤美化

    SkinMagic--MFC界面换肤美化(完整步骤) 一. 下载并解压SkinMagic https://pan.baidu.com/share/link?shareid=1666255608& ...

  8. VC应用程序的界面换肤工具集合

    本人由于急着赶一个软件的说明文档,急需修改软件的界面,写代码显然是来不及的,所以在网上搜了好多换肤工具来试用,试用好几个,其中比较成功的有两个,其他的由于时间有限,没有仔细摸索,现不管三七二十一通通集 ...

  9. 很好的 .NET 换肤软件 IrisSkin

    当前.NET下提供换肤的控件有IrisSkin和DotNetSkin. 但是DotNetSkin提供的Demo版本,功能有限制,一时找不到可以破解的完全版. IrisSkin 的功能不比DotNetS ...

最新文章

  1. 一步步写自己SqlHelper类库(五):Command对象
  2. 一块只要4美元,超廉价版树莓派诞生,还用上了自研芯片
  3. 用numpy做图像处理
  4. R | 对亚马逊新总部可能位置进行可视化
  5. ASP.NET程序中常用代码汇总(四)
  6. 以表达式作为参数传入SQL的存储过程中去
  7. 数据结构与算法专题——第九题 鸡尾酒排序
  8. x3250m6系列服务器,IBM服务器X3250 M6 E3-1230v6 8GB 4x3.5 C110 300W 无驱
  9. PMT_Stream数据结构
  10. c++远征之多态篇——运行时类型识别(RTTI)
  11. 接口自动化测试(Python+Requests+Unittest)
  12. RX库中的IDisposable对象
  13. 国家开放大学专科计算机应用实训项目,国家开放大学电大专科《微机系统与维护》网络课实训1实训3作业及答案.docx...
  14. 什么是“光照度(Illuminance)”?
  15. 2毫秒c51汇编语言延时函数,单片机精确毫秒延时函数
  16. 9.C++例2-10 输入一系列整数,统计出正整数个数i和负整数个数j,读入0则结束。
  17. 2016年中国安防系统集成商发展状况如何?
  18. 2020年技术研发岗薪酬排名
  19. U盘文件全部变成只读模式的解决办法
  20. 菲涅尔区,前后比,VSWR

热门文章

  1. 湘阴一中2021高考成绩查询,湘阴一中2020级高一新生录取名单出炉!(附湘阴县高中录取情况)...
  2. MySQL-数据备份
  3. wps点击目录就跳到内容的方法教程
  4. ubuntu 20 禁用ipv6配置_纯固态电脑UEFI启动安装Ubuntu
  5. 小韩的剑圣之路(1)--简单易懂的javaweb体系图
  6. 【PS功能学习】05:高效修图法
  7. Oracle插入timestamp类型数据
  8. Vue高级篇--实现前后端完全分离
  9. 新建word文档默认作者如何修改
  10. 一些正则表达式(js代码验证)