DUiLib 源码分析 ——以UiLib 1.01版为分析目标

----------------------------------------------------------------------------------

分析约定:

private o------- 私有的成员变量或方法

protect x------- 受保护的成员变量或方法

public +------- 公开的成员变量或方法

----------------------------------------------------------------------------------



本篇分析一下源文件

UIManager.h/UIManager.cpp



CPaintManagerUI

成员变量



窗体句柄

o---m_hWndPaint 要CPaintManagerUI进行Direct绘图操作的窗体句柄

o---m_hwndTooltip 提示窗口句柄

o---m_hInstance 当前管理的Instance实例

o---m_hResourceInstance 当前管理的资源DLL Instance实例

o---m_pStrResourcePath 当前使用的资源路径

o---m_pStrResourceZip 当前使用的资源压缩包文件全称









------------------------------------------------------CPaintManagerUI使用的资源

绘图设备

o---m_hDcPaint 直接绘制到窗体的DC(为窗体的整个区域包括费客户区)

o---m_hDcOffscreen 内存缓冲区绘图DC

o---m_hDcBackground 背景绘制(支持AlphaBackground时使用)

位图

o---m_hbmpOffscreen m_hDcPaint的后台作图画布

o---m_hbmpBackground 背景图片bmp



------------------------------------------------------CPaintManagerUI用到的信息

o---m_ToolTip 提示消息

typedef struct tagTOOLINFOA {

UINT cbSize; //该结构体的大小 sizeof(TOOLINFO)

UINT uFlags; //附加标识类信息

HWND hwnd; //消息接受的窗体

UINT_PTR uId; //控件ID

RECT rect; //消息产生的区域位置

HINSTANCE hinst; //消息接收的实例

LPSTR lpszText; //提示消息

LPARAM lParam; //IE3.0以上的版本有该属性

void *lpReserved; //NT5.0以上的版本有该属性 附加信息

} TOOLINFO

标识类信息 

o---m_bShowUpdateRect 是否显示更新区域

o---m_bFirstLayout 是否是首个布局 

o---m_bUpdateNeeded 是否需要更新界面

o---m_bFocusNeeded 是否需要焦点

o---m_bOffscreenPaint 是否需要开双缓存绘图

o---m_bAlphaBackground 窗体背景是否需要支持Alpha通道(如png图片的半透明效果)

o---m_bMouseTracking 是否需要支持鼠标追踪

o---m_bMouseCapture 是否需要支持鼠标捕获



控件信息

o---m_pRoot xml根节点解析成的对象,通常为各种Window

o---m_pFocus 处于获得焦点状态的控件

o---m_pEventHover 处于鼠标悬停状态的控件

o---m_pEventClick 被鼠标点击的控件

o---m_pEventKey 接收键盘输入的控件



位置记录信息

o---m_pLastMousePos 鼠标最新的位置

o---m_szMinWindow 设置窗体可以调整到的最小大小

o---m_szMaxWindow 窗体可以调整到的最大大小

o---m_szInitWindowSize 窗体初始化是的大小

o---m_rcSizeBox 窗体外边框区域的大小

o---m_szRoundCorner 窗体四角的圆角弧度

o---m_rcCaption 窗体标题栏区域大小

o---m_uTimerID 当前定时器ID



集合类信息

o---m_aNotifiers 能够接收通知的对象集合

o---m_aTimers 定时器集合

o---m_aPreMessage 预处理消息集合

o---m_aPreMessageFilters 预处理消息过滤器集合

o---m_aMessageFilters 消息过滤器集合

o---m_aPostPaintControls 发送绘制请求的控件集合

o---m_aDelayedCleanup 延迟清理的对象集合

o---m_aAsyncNotify 异步通知消息集合

o---m_mNameHash 名称HashMap

o---m_mOptionGroup 选项组Map



xml对应资源

o---m_pParentResourcePM 上级(父类)资源的PaintManagerUI绘图管理器

o---m_dwDefaultDisabledColor 默认失效状态颜色

o---m_dwDefaultFontColor 默认字体颜色

o---m_dwDefaultLinkFontColor 默认超链接字体颜色

o---m_dwDefaultLinkHoverFontColor默认超链接鼠标悬停状态的字体颜色

o---m_dwDefaultSelectedBkColor 默认选中状态背景色

o---m_DefaultFontInfo 默认字体信息

TFontInfo{

hFont 该字体的句柄

sFontName 字体名称

iSize 字号

bBold 是否粗体

bUnderline 是否有下划线

bItalic 是否为斜体

TEXTMETRIC tm 该字体的TEXTMETRIC信息

}

o---m_aCustonFonts 自定义字体资源集合

o---m_mImageHash 图片资源HashMap

o---m_DefaultAttrHash DefaultAttr资源HashMap



私有方法

将所有的控件添加到m_mNameHash哈希表中

o---static CControlUI* CALLBACK __FindControlFromNameHash(CControlUI* pThis, LPVOID pData);

计算控件数量

o---static CControlUI* CALLBACK __FindControlFromCount(CControlUI* pThis, LPVOID pData);

根据点是否在区域中,查询控件

o---static CControlUI* CALLBACK __FindControlFromPoint(CControlUI* pThis, LPVOID pData);

通过Tab信息查询控件

o---static CControlUI* CALLBACK __FindControlFromTab(CControlUI* pThis, LPVOID pData);

从快照中查询控件

o---static CControlUI* CALLBACK __FindControlFromShortcut(CControlUI* pThis, LPVOID pData);

查找需要更新的控件

o---static CControlUI* CALLBACK __FindControlFromUpdate(CControlUI* pThis, LPVOID pData);

通过名称比较查询控件

o---static CControlUI* CALLBACK __FindControlFromName(CControlUI* pThis, LPVOID pData);



公开方法

绘图管理器的初始化(m_hWndPaint,m_hDcPaint赋值,在预处理消息中加入管理器)

+---void Init(HWND hWnd);

当前需要更新界面

+---void NeedUpdate();

指定区域失效

+---void Invalidate(RECT& rcItem);

获取绘图设备DC

+---HDC GetPaintDC() const;

获取绘图的窗口句柄

+---HWND GetPaintWindow() const;

获取提示窗体句柄

+---HWND GetTooltipWindow() const;

获取当前鼠标的位置

+---POINT GetMousePos() const;

获取客户区大小

+---SIZE GetClientSize() const;

获取窗体初始化时的大小

+---SIZE GetInitSize();

设置窗体初始化大小

+---void SetInitSize(int cx, int cy);

获取窗体的边框区域大小

+---RECT& GetSizeBox();

设置窗体的边框区域大小

+---void SetSizeBox(RECT& rcSizeBox);

获取标题区域位置

+---RECT& GetCaptionRect();

设置标题区域位置

+---void SetCaptionRect(RECT& rcCaption);

获取窗体四角的圆角弧度

+---SIZE GetRoundCorner() const;

设置窗体四角的圆角弧度

+---void SetRoundCorner(int cx, int cy);

获取窗体可以调整到的最小大小

+---SIZE GetMinInfo() const;

设置窗体可以调整到的最小大小

+---void SetMinInfo(int cx, int cy);

获取窗体可以调整到的最大大小

+---SIZE GetMaxInfo() const;

设置窗体可以调整到的最大大小

+---void SetMaxInfo(int cx, int cy);

窗体的不透明度(0完全透明-255完全不透明)

+---void SetTransparent(int nOpacity);

设置绘图是否支持透明处理

+---void SetBackgroundTransparent(bool bTrans);

是否显示更新区域

+---bool IsShowUpdateRect() const;

设置是否显示更新

+---void SetShowUpdateRect(bool show);

获取当前管理的实例句柄

+---static HINSTANCE GetInstance();

获得当前运行的实例的路径

+---static CStdString GetInstancePath();

获得当前的工作路径

+---static CStdString GetCurrentPath();

获取资源DLL的实例句柄

+---static HINSTANCE GetResourceDll();

获取资源的路径(以"\"结尾)

+---static const CStdString& GetResourcePath();

获得Zip资源的路径

+---static const CStdString& GetResourceZip();

设置实例句柄

+---static void SetInstance(HINSTANCE hInst);

设置当前的工作路径

+---static void SetCurrentPath(LPCTSTR pStrPath);

设置当前的DLL资源的实例句柄

+---static void SetResourceDll(HINSTANCE hInst);

设置资源所在文件夹路径

+---static void SetResourcePath(LPCTSTR pStrPath);

设置Zip资源的路径(包括Zip文件名)

+---static void SetResourceZip(LPCTSTR pStrZip);

设置使用上级资源的绘图管理器

+---bool UseParentResource(CPaintManagerUI* pm);

获得上级资源绘图管理器

+---CPaintManagerUI* GetParentResource() const;

获取禁用状态的默认颜色

+---DWORD GetDefaultDisabledColor() const;

设置禁用状态的默认颜色

+---void SetDefaultDisabledColor(DWORD dwColor);

获取字体默认颜色

+---DWORD GetDefaultFontColor() const;

设置字体默认颜色

+---void SetDefaultFontColor(DWORD dwColor);

设置链接文字的默认字体颜色 

+---DWORD GetDefaultLinkFontColor() const;

获取链接文字的默认颜色

+---void SetDefaultLinkFontColor(DWORD dwColor);

获取鼠标悬停与超链上的默认字体颜色

+---DWORD GetDefaultLinkHoverFontColor() const;

获取鼠标悬停与超链上的默认字体颜色

+---void SetDefaultLinkHoverFontColor(DWORD dwColor);

获取选中状体的默认背景颜色

+---DWORD GetDefaultSelectedBkColor() const;

设置选中状态的默认背景颜色

+---void SetDefaultSelectedBkColor(DWORD dwColor);

获取默认使用的字体信息

+---TFontInfo* GetDefaultFontInfo();

设置默认使用的字体信息

+---void SetDefaultFont(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);

获取用户自定义字体的数量(一般对应xml中Font的数量)

+---DWORD GetCustomFontCount() const;

向字体数组列表追加字体资源

+---HFONT AddFont(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);

向字体数组列表中插入字体资源

+---HFONT AddFontAt(int index, LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);

获取数组中指定下标的字体对象句柄

+---HFONT GetFont(int index);

从字体数组中获取指定配置的字体对象句柄

+---HFONT GetFont(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);

字体数组集合中是否存在字体对象

+---bool FindFont(HFONT hFont);

字体数组集合中是否存在指定配置的字体对象

+---bool FindFont(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);

获得字体对象的

+---int GetFontIndex(HFONT hFont);

根据指定的配置信息查询字体索引

+---int GetFontIndex(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);

从字体数组列表中移除字体对象

+---bool RemoveFont(HFONT hFont);

从字体数组列表中移除指定位置的字体信息

+---bool RemoveFontAt(int index);

清空字体数组列表

+---void RemoveAllFonts();

通过字体数组索引查找字体信息

+---TFontInfo* GetFontInfo(int index);

通过字体对象句柄获取字体信息

+---TFontInfo* GetFontInfo(HFONT hFont);

根据图像路径查找图像信息

+---const TImageInfo* GetImage(LPCTSTR bitmap);

根据名称,类型,遮罩色 查询 图像信息

+---const TImageInfo* GetImageEx(LPCTSTR bitmap, LPCTSTR type = NULL, DWORD mask = 0);

添加图像

+---const TImageInfo* AddImage(LPCTSTR bitmap, LPCTSTR type = NULL, DWORD mask = 0);

添加图像

+---const TImageInfo* AddImage(LPCTSTR bitmap, HBITMAP hBitmap, int iWidth, int iHeight, bool bAlpha);

根据图像名称移除图像

+---bool RemoveImage(LPCTSTR bitmap);

移除全部图像

+---void RemoveAllImages();

添加控件的默认配置信息(如button)

+---void AddDefaultAttributeList(LPCTSTR pStrControlName, LPCTSTR pStrControlAttrList);

根据控件名称查询该类控件的默认配置

+---LPCTSTR GetDefaultAttributeList(LPCTSTR pStrControlName) const;

移除指定控件类型名称的默认配置

+---bool RemoveDefaultAttributeList(LPCTSTR pStrControlName);

获取默认配置信息列表

+---const CStdStringPtrMap& GetDefaultAttribultes() const;

清空默认配置信息列表

+---void RemoveAllDefaultAttributeList();

将对话框控件附加到当前的管理器中

+---bool AttachDialog(CControlUI* pControl);

控件初始化

+---bool InitControls(CControlUI* pControl, CControlUI* pParent = NULL);

控件回收

+---void ReapObjects(CControlUI* pControl);



添加控件到指定的选项组

+---bool AddOptionGroup(LPCTSTR pStrGroupName, CControlUI* pControl);

查询指定选项组名称中的全部选项

+---CStdPtrArray* GetOptionGroup(LPCTSTR pStrGroupName);

从指定控件中移除指定选项组名称的选项组

+---void RemoveOptionGroup(LPCTSTR pStrGroupName, CControlUI* pControl);

清空全部选项组列表

+---void RemoveAllOptionGroups();



获取焦点状态的控件

+---CControlUI* GetFocus() const;

设置控件为获得焦点状态

+---void SetFocus(CControlUI* pControl);

设置控件为需要绘制焦点

+---void SetFocusNeeded(CControlUI* pControl);



设置下一个获得Tab键会获得焦点的控件,Tab是否继续往下走

+---bool SetNextTabControl(bool bForward = true);



为指定控件以及其子控件设置定时器

+---bool SetTimer(CControlUI* pControl, UINT nTimerID, UINT uElapse);

移除指定控件上的指定编号的定时器

+---bool KillTimer(CControlUI* pControl, UINT nTimerID);

清空所有的定时器

+---void RemoveAllTimers();



设置窗体接受鼠标事件

+---void SetCapture();

释放窗体捕获鼠标事件

+---void ReleaseCapture();

判断窗体是否接受鼠标事件

+---bool IsCaptured();



添加控件到通知集合中

+---bool AddNotifier(INotifyUI* pControl);

将控件从通知集合中移除

+---bool RemoveNotifier(INotifyUI* pControl); 

发送同步/异步通知

+---void SendNotify(TNotifyUI& Msg, bool bAsync = false);

构建同步或异步通知并发送

+---void SendNotify(CControlUI* pControl, LPCTSTR pstrMessage, WPARAM wParam = 0, LPARAM lParam = 0, bool bAsync = false);





向预处理消息过滤器链中添加消息过滤器

+---bool AddPreMessageFilter(IMessageFilterUI* pFilter);

从预处理消息过滤器链合中移除指定的消息过滤器

+---bool RemovePreMessageFilter(IMessageFilterUI* pFilter);



向消息过滤器链中添加消息过滤器

+---bool AddMessageFilter(IMessageFilterUI* pFilter);

从消息过滤器链中移除消息过滤器

+---bool RemoveMessageFilter(IMessageFilterUI* pFilter);

获取发送需要绘制的控件的数量

+---int GetPostPaintCount() const;

向绘制请求集合中添加要绘制的控件

+---bool AddPostPaint(CControlUI* pControl);

从绘制请求集合中移除指定的控件

+---bool RemovePostPaint(CControlUI* pControl);

将绘制请求控件插入到绘制请求集合的指定位置

+---bool SetPostPaintIndex(CControlUI* pControl, int iIndex);

向延迟清理集合中添加需要延迟清理的对象

+---void AddDelayedCleanup(CControlUI* pControl);

获取根节点控件

+---CControlUI* GetRoot() const;

从根节点开始查找指定点所在的控件

+---CControlUI* FindControl(POINT pt) const;

从指定节点开始查找指定点所在的控件

+---CControlUI* FindControl(CControlUI* pParent, POINT pt) const;

从根节点开始,查找指定名称的控件

+---CControlUI* FindControl(LPCTSTR pstrName);

从指定节点开始查找指定名称的控件

+---CControlUI* FindControl(CControlUI* pParent, LPCTSTR pstrName);



消息循环,非游戏框架消息泵,无法利用无消息的空闲时间 

+---static void MessageLoop();

消息翻译,在Win32原有的消息转换基础上,将需要自己处理的消息转发给消息预处理器

+---static bool TranslateMessage(const LPMSG pMsg);

消息预处理器

1.消息预处理过滤(消息预处理过滤器集合对消息进行过滤处理)

2.检查是否按下Tab键,设置下一个获得焦点的控件

3.处理Alt+Shortcut Key按下后的控件获得焦点和激活的设置

4.检查是否有系统键消息,有则发送获得焦点的控件的事件

+---bool PreMessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes);





----------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------

消息处理器(核心处理器)

1.消息过滤

2.检查Custom消息并处理

3.检查是否有WM_CLOSE消息并处理

4.处理WM_ERASEBKGND(不允许进行背景擦除,防止闪烁)

5.绘制处理(核心)

5.1做延迟绘图判断,当前是否有 窗体大小调整的操作,或者是否需要初始化窗体

5.2设置焦点控件

5.3如果开启双缓存绘图,采用双缓存方式绘图,否则采用标准绘图方式绘图

5.4 

6.处理客户区的绘制WM_PRINTCLIENT

7.接到WM_GETMINMAXINFO消息后向系统提交该窗体可调整大小的最小和最大限制

8.窗体大小改变时,向焦点控件发送改变大小消息并设置窗体需要更新

9.处理定时器消息,向定时器集合中广播定时消息

10.处理鼠标悬停

10.1向鼠标悬停的控件发送鼠标悬停消息

10.2如果当前控件有提示消息,创建消息提示窗体

11.处理鼠标离开事件,关闭消息提示框,发送鼠标离开消息,取消鼠标的追踪

12.鼠标移动时,开始追踪鼠标

12.1处理鼠标移动时,鼠标在控件上进入,移动,悬停和离开的消息

13.处理鼠标左键按下的消息设定活动的焦点的控件

14.鼠标双击事件处理,向需要接收鼠标双击事件的控件发送双击事件

15.鼠标左键抬起时,向上次接收到点击消息的控件发送鼠标左键抬起的消息

16.鼠标右键按下时,向需要接收鼠标右键按下的控件发送右键按下消息

17.鼠标右键快捷菜单消息,将该消息通知给上次点击过的按钮

18.滚轮消息时,象鼠标所在的控件发送滚轮消息

19.WM_CHAR 消息时,向获得焦点的控件发送该消息

20.键盘按下时,向焦点控件发送该键盘消息,并设定焦点控件为键盘消息控件

21.键盘按键抬起时,向事键盘消息控件发送该事件

22.设定鼠标光标消息时,获得光标所在控件接收该消息

23.通知消息到来时,加OCM_BASE后发送通知消息

24.命令消息到来,加OCM_BASE后发送消息

25.WM_CTLCOLOREDIT,STATIC消息到来后,加OCM_BASE后发送消息

+---bool MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes);

转自:http://www.cnblogs.com/wuqi924/articles/2127062.html

DuiLib——第一篇UIManager的更多相关文章

  1. duilib库分析2.第一篇UIManager

    DUiLib 源码分析 ——以UiLib 1.01版为分析目标--------------------------------------------------------------------- ...

  2. Swing:LookAndFeel 教程第一篇——手把手教你写出自己的 LookAndFeel

    本文是 LookAndFeel 系列教程的第一篇. 是我在对 Swing 学习摸索中的一些微薄经验. 我相信,细致看全然系列之后.你就能写出自己的 LookAndFeel. 你会发现 Swing 原来 ...

  3. 从0开始搭建SQL Server AlwaysOn 第一篇(配置域控)

    从0开始搭建SQL Server AlwaysOn 第一篇(配置域控) 第一篇http://www.cnblogs.com/lyhabc/p/4678330.html第二篇http://www.cnb ...

  4. Python爬虫小白入门(四)PhatomJS+Selenium第一篇

    一.前言 在上一篇博文中,我们的爬虫面临着一个问题,在爬取Unsplash网站的时候,由于网站是下拉刷新,并没有分页.所以不能够通过页码获取页面的url来分别发送网络请求.我也尝试了其他方式,比如下拉 ...

  5. Three.js 第一篇:绘制一个静态的3D球体

    第一篇就画一个球体吧 首先我们知道Three.js其实是一个3D的JS引擎,其中的强大之处就在于这个JS框架并不是依托于JQUERY来写的.那么,我们在写这一篇绘制3D球体的文章的时候,应该注意哪些地 ...

  6. 深入学习jQuery选择器系列第一篇——基础选择器和层级选择器

    × 目录 [1]id选择器 [2]元素选择器 [3]类选择器[4]通配选择器[5]群组选择器[6]后代选择器[7]兄弟选择器 前面的话 选择器是jQuery的根基,在jQuery中,对事件处理.遍历D ...

  7. 【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  8. Android基础学习第一篇—Project目录结构

    写在前面的话: 1. 最近在自学Android,也是边看书边写一些Demo,由于知识点越来越多,脑子越来越记不清楚,所以打算写成读书笔记,供以后查看,也算是把自己学到所理解的东西写出来,献丑,如有不对 ...

  9. 深入理解ajax系列第一篇——XHR对象

    × 目录 [1]创建对象 [2]发送请求 [3]接收响应[4]异步处理[5]实例演示 前面的话 ajax是asynchronous javascript and XML的简写,中文翻译是异步的java ...

随机推荐

  1. sql 之CONCAT用法

    这是java交流群里一个网友面试的时候发过来的笔试题,我觉得题目的假定条件应该是某个字母对应的最小数字只有一个. 思路第一步是查出一个子表s1: select name,min(number) fro ...

  2. 数组prototype添加函数呢,采用回调判定函数内容

    1.解决方案 Array.prototype.all = function (p) { return this.filter(p).length == this.length; }; Array.pr ...

  3. mysql 批量创建表,利用存储过程

    最近根据需求,需要提前创建一批日志表,以日期结尾,每天创建一张,例如XXX20160530,请参考如下: BEGIN    DECLARE `sName` VARCHAR(128);   DECLAR ...

  4. IOS之Core Foundation框架和Cocoa Foundation框架的区别

    Core Foundation框架 (CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能.下面列举该框架支持进行管理的数据以及可提供的 ...

  5. 算法----序列和的 top N

    Description: 两个长度为 n 的数组 A 和 B, 各从中选出一个元素相加 A[i] + B[j], 求 top n 小的那些和. 思路 1:这样的和总共有 n^2 个, 排序,然后取前 ...

  6. Angularjs相关理论

    1.AngularJS的工作流程: (1)浏览器载入HTML,然后把它解析成DOM (2)浏览器载入angularjs脚本 (3)AngularJS等到DOMContentLoaded事件触发 (4) ...

  7. Android Manifest.xml详解

    一.关于AndroidManifest.xml AndroidManifest.xml 是每个android程序中必须的文件.它位于整个项目的根目录,描述了package中暴露的组件(activiti ...

  8. NSArray,NSSet,NSDictionary的遍历,基本使用集锦

    NSArray *array = [NSArray arrayWithObjects:@"zhangsan",@"lisi",@"wangwu&quo ...

  9. HDU 5828(线段树)

    Problem Rikka with Sequence 题目大意 维护一个序列,支持三种操作. 操作1:区间加. 操作二:区间开根号(向下取整). 操作3:区间求和. 解题分析 可以发现经过若干次操作 ...

  10. Sticky Footer (让页脚永远停靠在页面底部,而不是根据绝对位置)

    <!doctype html><html> <head> <meta charset="UTF-8"> <meta name= ...