Duilib总体框架
从GoogleCode上下载的duilib工程中附带的一副总体设计图(如下所示),可以先整体了解一下,有个初步的认识,对后续进一步深入了解学习会很有帮助。
通过设计图有了一个初步认识后,接下来开始进一步深入学习了解,主要从以下几个方面进行了解学习:
库的组成;框架基本流程;元素创建机制;消息处理机制。
1. 库的基本组成
1.1 工具库
由于duilib没有对外部的任何库进行依赖,所以在其内部实现了很多用于支撑项目的基础类(如下图所示)。这些类分布在Util文件夹中:
- UI相关:CPoint / CSize / CDuiRect
- 简单容器:CStdPtrArray / CStdValArray / CStdString / CStdStringPtrMap
上面这些类看名字就基本能够理解其具体的含义了,当然除了基本的基础库,还有一些和窗口使用相关的工具的封装,如窗口工具:WindowImplBase,这个工具我们在这里不详述,后面使用中会经常用到。
1.2 控件库
控件库在duilib的实现中被分为了两块:Core和Control:
- Core中包含的是所有控件公用的部分,里面主要是一些基类和绘制的封装。
- Control中包含的就是各个不同的控件的行为了。
这当中尤其要注意控件基类CControlUI和容器基类CContainerUI,这是duilib核心类(如下图所示)中是很重要的两部分:

1.2.1. 控件基类:CControlUI
CControlUI在整个控件体系中非常重要,它是所有控件的基类,也是组成控件树的基本元素,控件树中所有的节点都是一个CControlUI。
它基本包括了所有控件公共的属性,如:位置,大小,颜色,是否有焦点,是否被启用等等。当然这个类中还提供了非常多的基础函数,用于重载来实现子控件,如获取控件名称和ClassName,是否显示等等。
另外为了方便从XML中直接解析出控件的各个属性,这个类中还在提供了一个SetAttribute的方法,传入字符串的属性名称和值对特定的属性进行设置,内部其实就是挨个比较字符串去完成的,所以平时使用的时候就还是不要使用的比较好了,因为每个属性实际上都有特定的方法来获取和设置。
另外每个控件中还有几个事件管理的对象——CEventSource,这些对象会在特定的时机被触发,如OnInit,调用其中保存的各个回调函数。
1.2.2. 容器基类:CContainerUI
有了基本的控件基类之后,我们就需要容器来将他管理起来,这个容器就是CContainerUI,其内部用一个数组来保存所有的CControlUI的对象,后续的所有工作,就都是基于这个对象来进行的了。
这样在CContainerUI里面,主要实现了一下几个功能:
- 子控件的查找:CContainerUI::FindControl
- 子控件的生命周期管理:是否销毁(在Remove的时候自动销毁) / 是否延迟销毁(交给CPaintMangerUI去一起销毁)。
- 滚动条:所有的容器都支持滚动条,在其内部会对键盘和鼠标滚轮事件进行处理(CContainerUI::DoEvent),对其内部所有的元素调整位置,最后在绘制的时候实现滚动的效果
- 绘制:由于容器中有很多元素,所以为了加快容器的绘制,绘制的时候会获取其真正需要绘制的区域,如果子控件不在此区域中,那么就不予绘制了
而对于这些控件的绘制实现以及相关使用,在后续具体进一步学习中再深入详解。
2. 框架基本流程
框架的基本流程实际上类似Win32创建窗口流程,如果对于Win32比较熟悉,这部分可以很快掌握。
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
CPaintManagerUI::SetInstance(hInstance); // 第一步: 实例句柄与渲染类关联
CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + _T("skin"));
HRESULT Hr = ::CoInitialize(NULL); // 第二步:初始化COM库, 为加载COM库提供支持
if( FAILED(Hr) )
return 0;
CMainFrameWnd* pFrame = new CMainFrameWnd(); // 第三步:创建窗口类
if( pFrame == NULL )
return 0;
pFrame->Create(NULL, _T("主程序"), UI_WNDSTYLE_FRAME, 0L, 0, 0, 800, 600); // 第四步:注册窗口类与创建窗口
// 实际上这里调用Create操作和Win32创建窗体一样,内部实际上做了以下操作:
// -> RegisterSuperclass (注册一个超类 即已有一个窗口类的基上再注册一个窗口类)
// -> RegisterWindowClass (注册窗口类)
// -> ::CreateWindowEx (创建窗口,此时触发 WM_CREATE 消息)
// -> HandleMessage ( WM_CREATE消息处理OnCreate)
pFrame->CenterWindow(); // 第五步:窗口居中显示
::ShowWindow(*pFrame, SW_SHOW);
CPaintManagerUI::MessageLoop(); // 第六步:处理消息循环
::CoUninitialize(); // 第七部:退出程序并释放COM库
return 0;
}

3. 元素创建机制
第一步:响应WM_CREATE消息;
第二步:主窗口类与窗口句柄关联;
m_pm.Init(m_hWnd)
第三步:加载XML并动态创建界面无素,与布局界面元素
CDialogBuilder builder;</span>
CDialogBuilderCallbackEx cb;</span>
CControlUI* pRoot =builder.Create(_T("skin.xml"), (UINT)0, &cb, &m_pm);
第四步:附加控件到HASH表
PaintManagerUI::AttachDialog
InitControls
FindControl
__FindControlFromNameHash
pManager->m_mNameHash.Insert

第五步:添加通知处理
CPaintManagerUI::AddNotifier
第六步:窗口的绘制(以上是窗口的创建过程,通过xml,所有控件都被加载到CPaintManagerUI)
CPaintManagerUI响应WM_PAINT消息,开始双缓存绘图
m_pRoot->DoPaint绘背景图
CControlUI::DoPaint
CRenderEngine 真正的绘图类
pPostPaintControl->DoPostPaint 在背景图上绘制控件
::BitBlt 把离屏视图画到主屏上

4.消息处理机制
第一步:注册消息处理函数
在CWindowWnd注册窗口(RegisterWindowClass())里,注册消息回调函数(__WndProc);
第二步:消息分发
消息回调函数(处理所有系统发送的消息),然后回调函数通过子类的CMainFrameWnd::HandleMessage对消息进行分发。
非窗口消息通过CMainFrameWnd::HandleMessage调用CPaintManagerUI::MessageHandler进行分发。
第三步:消息循环
在CPaintManagerUI类的MessageLoop处理消息循环;
接收到消息以后,进入消息回调函数(__WndProc);
(注:以下内容以鼠标单机Button事件为例)
第四步:处理控件消息
鼠标按下时(WM_LBUTTONDOWN),查找鼠标点击的控件。
处理控件的鼠标按下消息:通过调用基类CControlUI:: DoEvent,引起子类如CButtonUI::DoEvent事件。
子类的DoEvent对不同类型的事件进行处理。通过CPaintManagerUI:: SendNotify回调控件注册的事件。
Duilib总体框架的更多相关文章
- Java 集合系列 01 总体框架
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- WisDom.Net 框架设计(一) 总体框架
WisDom.Net总体框架 1.目标 WisDom.Net 做为以后快速开发相关的软件的基础框架,实现用户,权限,角色,菜单,和工作流的管理功能.相关功能可以独立使用,快速用于其他程序的开发.预计 ...
- Cocos2d-x学习笔记(两)Cocos2d-x总体框架
原创文章.转载请注明出处:http://blog.csdn.net/sfh366958228/article/details/38680123 前言 上一节我们简单分析了HelloWorldproje ...
- Android系统--输入系统(十二)Dispatch线程_总体框架
Android系统--输入系统(十二)Dispatch线程_总体框架 1. Dispatch线程框架 我们知道Dispatch线程是分发之意,那么便可以引入两个问题:1. 发什么;2. 发给谁.这两个 ...
- 【Java集合系列】---总体框架
个的组合,这些数据项可能共享某些特征,需要以某种操作方式一起进行操作,一般来说,这些数据项的类型都是相同的,或者基类相同(若使用的语言支持继承),列表或数组通常不认为是集合,因为其大小固定,但是事实上 ...
- java.io包的总体框架图(转)
原文链接:java.io包的总体框架图, 便于记忆!
- Duilib学习笔记《01》— duilib整体框架认识
从GoogleCode上下载的duilib工程中附带的一副总体设计图(如下所示),可以先整体了解一下,有个初步的认识,对后续进一步深入了解学习会很有帮助. 通过设计图有了一个初步认识后,接下来开始进一 ...
- duilib基本框架
最近我一个同学在项目中使用到了duilib框架,但是之前并没有接触过,他与我讨论这方面的内容,看着官方给出的精美的例子,我对这个库有了很大的兴趣,我自己也是初学这个东东,我在网上花了不少时间来找相关的 ...
- ROS探索总结(二)——ROS总体框架
个人分类: ROS 所属专栏: ROS探索总结 一. 总体结构 根据ROS系统代码的维护者和分布来标示,主要有两大部分: (1)main:核心部分,主要由Willow G ...
随机推荐
- javascript总结39: 元素获取的常见问题
1 定义id属性的元素,不获取直接使用 由于id名具有唯一性,部分浏览器支持直接使用id名访问元素,但不是标准方式,生产环境下不推荐使用. 2 元素是对象 获取到的元素是DOM对象 ,DOM对象也有数 ...
- 暂停、恢复CALayer 动画
CALayer都是实现了CAMediaTiming协议(或者叫做接口).所以layer的动画有一个很有意思的属性speed.如果一个layer的动画速度变成0.0的时候,很显然这个动画就不再动了.设置 ...
- (转)jQuery插件编写学习+实例——无限滚动
原文地址:http://www.cnblogs.com/nuller/p/3411627.html 最近自己在搞一个网站,需要用到无限滚动分页,想想工作两年有余了,竟然都没有写过插件,实在惭愧,于是简 ...
- 编写高质量代码改善C#程序的157个建议——建议75:警惕线程不会立即启动
建议75:警惕线程不会立即启动 现代的大多数操作系统都不是一个实时的操作系统,Windows系统也是如此.所以,不能奢望我们的线程能够立即启动.Windows内部会实现特殊的算法以进行线程之间的调度, ...
- Python之安装第三方扩展库
PyPI 地址:https://pypi.python.org/pypi 如果你知道你要找的库的名字,那么只需要在右上角搜索栏查找即可. 1.pip安装扩展库 (1)安装最新版本的扩展库: cmd&g ...
- html中怎么样让div并排显示
html中的div默认是流式显示,每个div会占用一整行 <html> <head> <meta http-equiv="Content-Type" ...
- Linux常用命令,学的时候自己记的常用的保存下来方便以后使用 o(∩_∩)o 哈哈
service httpd restart 重启Apache service mysqld restart 重启mysql [-][rwx][r-x][r--] 1 234 567 890 421 4 ...
- Ray tracing performance benchmark
accel. avg size 3.14accel. avg depth 16.15accel. max size 8accel. max depth 20accel. GPIT 3.00 MB tr ...
- 安全测试---AWVS简单安装介绍
使用AWVS对域名进行全局分析,深入探索: 首先,介绍一下AWVS这个工具. Acunetix Web Vulnerability Scanner(简称AWVS)是一款知名的网络漏洞扫描工具,它通过网 ...
- [agc016b]Colorful Hats 分类讨论
Description 有n个人,每个人都戴着一顶帽子.当然,帽子有不同的颜色. 现在,每个人都告诉你,他看到的所有其他人的帽子共有多少种颜色,请问你有没有符合所有人的描述的情况. Input ...