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. Thread启动方式一(Thread.start):源码分析

    package day11; class TestDemo extends Thread{ int count = 0; /*public void add(){ while(count<100 ...

  2. openstack 本地化

    研究了一下 openstack中的本地化:主要使用gettext模块: 其中本地化包括对一般字符串的本地化和log的本地化:   (1) _localedir = os.environ.get('es ...

  3. 在.net中实现在textbox中按ctrl+enter进行数据的提交

    textbox.Attributes.Add("onKeydown", "if(event.ctrlKey&&event.keyCode == 13){d ...

  4. Asp.Net请求管道中的19个事件

    请求管道中的19个事件.(1)BeginRequest: 开始处理请求(2)AuthenticateRequest授权验证请求,获取用户授权信息(3):PostAuthenticateRequest获 ...

  5. Cash Machine_多重背包

    Description A Bank plans to install a machine for cash withdrawal. The machine is able to deliver ap ...

  6. 2、SQL基础整理(聚合函数)

    聚合函数 --求平均 select  AVG(age) as 年龄 from xuesheng select AVG(chinese) as 语文 from xuesheng where class ...

  7. 为什么有的代码要用 base64 进行编码

    一.1.传输信道只支持ASCII字符,不方便传输二进制流的场合. 2.含有非ASCII字符,容易出现编码问题的场合. 3.简易的掩人耳目.至少非开发人一眼看不出来是啥. 二.Base64主要用于将不可 ...

  8. HDU 5828(线段树)

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

  9. translate居中

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

  10. 简单的JS运动封装实例---侧栏分享到

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...