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::AttachDialogInitControlsFindControl__FindControlFromNameHashpManager->m_mNameHash.Insert
第五步:添加通知处理
CPaintManagerUI::AddNotifier
第六步:窗口的绘制(以上是窗口的创建过程,通过xml,所有控件都被加载到CPaintManagerUI)
CPaintManagerUI响应WM_PAINT消息,开始双缓存绘图m_pRoot->DoPaint绘背景图 CControlUI::DoPaintCRenderEngine 真正的绘图类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回调控件注册的事件。
本文转载自:https://www.cnblogs.com/MrYuan/p/4971842.html
duilib整体框架认识相关推荐
- 基于360SafeDemo对duilib整体框架的概述
我们以一个具体窗口(360Safe Window)的创建为入口,建立起程序的整个框架.然后逐步深入,对其中的细节以及duilib中各个类在任务的执行过程中负责的任务进行分析.分析以问题作为导向,随着层 ...
- 【推荐系统】推荐系统整体框架概览
感谢博文作者 Kevin_Duan 原文链接:https://blog.csdn.net/chunyun0716/article/details/83152037 推荐系统整体架构 先说点题外话,最近 ...
- 通俗易懂SpringMVC整体框架理解
最近又重新温习了一下前台SpringMVC框架,能够从整体上对SpringMVC有一个全局的认识.在这里也总结一下,为那些即将学习SpringMVC的亲们,做一个很好的开端吧! 1. SpringMV ...
- V4L2 driver(一). 整体框架
1.1 从字符设备说起 熟悉v4l2用户空间编程的都知道, v4l2编程主要是调用一系列的ioctl函数去对v4l2设备进行打开, 关闭, 查询, 设置等操作. v4l2设备是一个字符设备, 而且其驱 ...
- 推荐系统整体框架概览
推荐系统整体框架概览 推荐系统整体架构 推荐系统的核心组成部分 离线 核心节点 服务 UI 总结 推荐系统整体架构 先说点题外话,最近在看的书中讲到了怎么进行自学的方法,分了十个层级.第一个便是要了解 ...
- 浅谈opencl之整体框架
结合四大模型,以CPU和GPU平台为例子,opencl整体框架如下: CPU为host端, GPU为device端, host和device端的交互是以context为主.context贯穿到整个op ...
- jQuery源码分析 整体框架部分及部分常用方法
最近尝试看看jQuery的源码. 版本 version = "1.11.1" 相对于看一本jQuery如何使用的书,看jQuery源码对它可以有更深层次的理解.jQuery中大量使 ...
- 第一次总结:整体框架
第一次总结:整体框架 tcp部份: 1.初始化WiFi连接路由器 wifi.begin();bool b = wifi.Initialize(STA, SSID, PASSWORD);连接局域网if( ...
- zeptojs库解读1之整体框架
首先看的是整体框架, // zepto骨骼,这个函数的作用使得Zepto(slector, context)使用很多$.fn里面的方法 var Zepto = (function(){// zepto ...
- 项目背景一般写什么_项目申报整体框架规划思路,提高你的书写逻辑!
看到网友留言,希望我能分享下项目申报整体框架规划的思路,我们今天就这个内容深度讨论. 当我们拿到企业的所有材料的时候,第一件事情就是要看材料是否满足必须的申报条件,缺一不可,满足了这些条件,如果缺少一 ...
最新文章
- MyBatis映射文件(一)
- php 获取下拉框选中的文本,jQuery如何获取select选择的文本与值?(代码示例)...
- JavaWeb学习中的小问题
- thymleaf中枚举 判断对象值内容
- Android中Adapter适配器的介绍以及用法的总结
- linux python2.7安装教程_Linux RedHat下安装Python2.7开发环境
- linux桌面隐藏鼠标,如何隐藏鼠标光标
- VC++用异或(XOR)方式实现拖放画动态直线
- Spring包名代码提示
- 失焦事件触发_JavaScript event 事件详解
- Atitit 字符串转换数组main参数解析 args splitByWholeSeparator 	 		String string= -host 101.1 8*124 -db 1
- 从幼苗长成大树 中美两国GIS软件技术已并驾齐驱
- java.lang.IllegalStateException: No instances available for user
- python海龟画图函数汇总
- 浙江大学副教授杨洋——《Time2Graph:从图视角出发的时间序列建模》
- surface book 3 结束休眠之后风扇狂转
- 未明学院:国际政治专业出身,如何pk掉港大、美籍商科生,拿下亚马逊市场部德勤offer!
- excel之高级筛选与VLOOKUP函数
- 金融工程学(一):概述
- m.555lu.co/vlist.php_新浪微博V2接口演示程序-Powered by Sina App Engine
热门文章
- mysql5.7.13编译安装_编译安装MySQL-5.7.13
- python关于csv的查询系统_使用Python对csv文件操作
- sql 语句 查询结果赋值变量_RationalDMIS 7.1 变量赋值 ASSIGN语句
- mysql 命令 kill_当MySQL事务中发生了网络异常
- latex数学符号加粗_latex的安装与数学公式的书写
- In file included from /usr/include/stdio.h:27:0, from btest.c:16: /usr/include/feat出错的解决办法
- oracle通信通道的文件结尾_oracle里执行full join 报通信通道的文件结尾问题
- php中js中文传值乱码,php解析JSON中文乱码问题的解决方法
- A. Death Note
- 如何系统嗯学习计算机知识,老师,非科班出身的人该怎么系统的学习计算机知识呢?...