DUI总结-程序员宅基地

  DUI好处在于可以很方便的构建高效,绚丽的,非常易于扩展的界面。从而很好的将界面和逻辑分离,同时易于实现各种超炫的界面效果如换色,换肤,透明等。DUI使用的是GDI+核心.DirectUI可以理解为一个轻量级的WPF,可以让C++做出C#般绚丽的界面。

DUI核心的大体结构图如下:

/

分为几个大部分:

1.    控件

2.    容器

3.    UI构建解析器(XML解析)

4.    窗体管理器

5.    渲染引擎

一、构建

1、CDialogBuilder的创建

         在DUI中加载xml界面配置文件的工作由CMarkUp类完成,CMarkUp类对xml内容进行分析构建出结点树。CDialogBuilder利用CMarkUp构建的结点树New出控件,并利用xml结点树的属性,构建出控件的属性。

下面由一张图来描述如何进行界面的模块划分。

/

2、控件与容器的构建

  这里我们先讲下,控件类和布局类的区别,在这里我们在构建几个类,先看下继承图

/

 (1)、一个控件基类(CControlUI)和一个按钮控件类(CButtonUI)

控件基类,包含有控件绘制的最基本的几个函数,当然都是虚函数,比如:SetAttribute(设置控件属性),GetInterface(获取控件的this指针),DoPaint(绘图)

(2)、一个容器基类,故名思义,容器是用来盛控件的,所以它必须具有的几个函数:

Add(将控件添加到此容器的子队列中),Remove(删除某个子控件)、RemoveAll(清空子控件队列)、GetItem(获取某个子控件)、GetCount(获取子控件的个数).所以这几个函数也是容器最基类IContainerUI的函数,

(3)、CContainerUI,这个才是稍微有意义点的布局类,它用于在窗体上划分出不同的区域,然后在区域中布局控件.这里最值得注意的地方是派生出它的基类,它是两个基类的派生类(IContainerUI和CControlUI),所以容器也是控件,这一点在后面绘图代码中特点重要,在绘图时,我们将所有的容器和控件全部都定义为CControlUI,所以如果当前的如果是CDialogUI的指针的话,它就会根据继承关系,先到CDialogUI中执行相关函数,这点尤其注意!!!!(这里暂时搞不明白也没关系,后面遇到的时候,我会重新讲)

(4)、CDialogUI,这是窗体的构建类,里面包含所在构建窗体的大小、背景图案等属性。

在控件基类中保存了窗口的句柄,因为我们只有一个窗体,也就是CreateWindowEx函数创建后,返回的那个HWND,我们这里保存的就是这个HWND,那我们要它有什么用呢,这是因为我们这里的控件全部都是模拟的控件的行为而已,是并没有句柄的,所以也不可能像MFC那样根据控件的句柄单独刷新       了,所以我们要刷新控件的话,就得刷新整个窗体(当然,我们会利用缓存技术局部绘制来提高效率),我们要刷新窗体就得利用SendMessage(hwnd,msg,wparam,lparam),所以要在控件基类中保存窗口的句柄。

 

3、窗体创建

创建窗体的一个基本思想,使用户不必做更多的工作,在创建窗口的基类CWindowWnd中完成窗口类注册、创建窗口、消息响应等功能,用户只需要从基类派生,并且简单调用Create()函数就可以了。

 

二、消息机制

1、添加EVENT机制

以通知某个按钮LBUTTONDOWN为例,我们首先在HandMessage()中,截获WM_LBUTTONDOWN消息,然后根据点击位置,由FindControlFromPoint找到控件,然后发送EVENT消息通知它,EVENT消息包括消息类型、发送消息控件、如果点击消息发送鼠标位置等。在这个控件收到EVNET通知后,然    后根据事件类型,重新绘图。就是根据当前不同的控件状态,给按钮绘制不同的颜色。当点击时,是红色,放开时,是绿色。

2、添加NOTIFY机制

  试想一下,上面的EVENT机制能够通知我们的控件,当前控件应该处于哪种状态,并完成哪种绘制。但是,当用户想点击控件的时候托动窗体,或者在点击控件的时候弹出另一个窗体该怎么办呢这,就是NOTIFY通知机制,比如当前控件处理BUTTON-DWON的状态时,我们就向用户发送“click”通知消息,又比如,当我们的控件处于"BUTTON-DOWN"同时又具有"MOUSE-MOVE"状态时,我们就向用户发送“drag”(拖动)通知消息。

    与EVENT相似,要发送通知消息,总是以结构体为单位的,这样能包含的信息多一些,而这里的消息通知的结构体定义围绕着我们感兴趣的几个变量,如消息发送者(控件)、消息类型、时间戳、鼠标信息等。

    在DUI中NOTIOFY机制是作为一个功能独立的模块,所以把它单独抽象为一个类INotifyUI,这个类只包含一个纯虚函数,Notify(),参数为一个TNotifyUI的结构体。在创建窗口时,我们将窗口类CMyWnd派生自INotifyUI,在窗口类中实现Notify()函数。

用下述步骤来描述Notify的工作流程

  STEP01. 消息第一次会由CPaintManagerUI类的TranslateMessage消息接收到.
  STEP02. 2. 调用CWindowWnd::Create创建窗口. 完成以下操作:

  1) 如果要子类下Window的控件(就是系统的控件, 而不是duilib的模拟控件), 就设置ControlProc函数为消息回调函数.

  2)不子类化, 就注册窗口类. 此时设置WndProc为窗口消息处理回调函数. 

  3)用CreateWindowExAPI函数创建窗口.

  这里先不看子类化相关的, 我要先看明白标准的窗口创建过程. 这也操作后消息就会分发到WndProc了。消息第二次就由WndProc接收到.

  STEP03. 之后要传到CPaintManagerUI类对象的MessageHandler函数. 未处理的消息就要返回给CWindowWnd类的默认消息处理函数来处理了. 

  STEP04.在 MessageHandler中利用多态性来调用不同控件的事件方法:pControl -> Event: pControl为控件对象实例之一。

  STEP5. CPaintManagerUI::SendNotify: 注意以下实现是完成控制和业务分离的关键

  m_CPaintManagerUI::AddNotifier 保存监听对象到m_aNotifiers中,利用重载特性调用注册的监听对象(窗口)的消息处理函数Notify

for (  int  i  =   0 ; i  <  m_aNotifiers.GetSize();  ++ i )

{    

static_cast < INotifyUI *> (m_aNotifiers[i]) -> Notify(Msg); 

}

转载于:https://www.cnblogs.com/ccueyt/p/5359221.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30650039/article/details/95523624

智能推荐

将eclipse文本编码格式修改为UTF-8-程序员宅基地

如果要使插件开发应用能有更好的国际化支持,能够最大程度的支持中文输出,则最好使 Java文件使用UTF-8编码。然而,Eclipse工作空间(workspace)的缺省字符编码是操作系统缺省的编码,简体中文操作系统 (Windows XP、Windows 2000简体中文)的缺省编码是GB18030,在此工作空间中建立的工程编码是GB18030,工程中建立的java文件也是GB18030。如果要使

转:Tomcat部署时war和war exploded区别以及平时踩得坑_core: war 和 core:war expoloded-程序员宅基地

目录war和war exploded的区别使用war模式开发的时候遇到的坑war和war exploded的区别在使用IDEA开发项目的时候,部署Tomcat的时候通常会出现下边的情况:是选择war还是war exploded 这里首先看一下他们两个的区别:1.war模式:将WEB工程以包的形式上传到服务器 ;2.war exploded模式:将WEB工程以当前文件夹的位置关系上传到..._core: war 和 core:war expoloded

使用pako.js 解压缩ws消息_pako blob-程序员宅基地

下载pako 插件。Github下载 https://github.com/nodeca/pako 或 npm install pako引入pako:import pako from 'pako'创建好ws后,设置 ws.binaryType = "arraybuffer"//默认的data类型是"blob",所以这里要改掉 。处理数据if (typeof(evt.data) ..._pako blob

RS485_Modbus通讯笔记_485功能码_c1278943913的博客-程序员宅基地

前言 RS-485总线标准规定了总线接口的电气特性标准即对于2个逻辑状态的定义:正电平在+2V~+6V之间,表示一个逻辑"1";负电平在-2V~-6V之间,则表示逻辑"0";数字信号采用差分传输方式,能够有效减少噪声信号的干扰。特点1.接口信号电平低,不易损坏接口电路的芯片,且该电平与TTL电平兼容,可方便与TTL 电路连接。2.数据传输速度快:最高传输速率为10Mbps3.可远程传输数据:RS-485接口的最大传输距离标准值为4000英尺,实际上可达 300..._485功能码

RGB 和 YUV 的转换公式-程序员宅基地

转载于:https://www.cnblogs.com/zoneofmine/p/10835711.html_rgb与yuv转换公式

C语言_求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字。-程序员宅基地

例如2+22+222+2222+22222(此时共有5个数相加),几个数相加有键盘控制。1.程序分析:关键是计算出每一项的值。后面的每一项是在前面一项的基础上加了a*10n,之前想要用纯数学的方法计算总和很麻烦,没什么简便算法。还是让循环结构来完成这种重复计算吧。main() {  int a,n,count=1;  long int sn=0,tn=0;  p..._c语言求s=a+aa+aaa+aaaa+aa...a的值

随便推点

antd vue中的switch自定义传参问题解决_antv switch-程序员宅基地

<a-select @change="checked=> handleChange(checked, record)"> </a-select>以上代码即可解决传递自定义参数问题_antv switch

如何快速学习一门新的编程语言?零基础开始学编程,就可以这样!_从零开始学编程如何快速入门-程序员宅基地

上学的时候,一位老师在与新手开发人员分享经验的时候曾说:最难学的编程语言是第二门语言。 不要为此感到难过,这句话的意思其实是说,在你第一次学习编程时,就已经对编程有了一些先入为主的想法。你会在语法上做很多的联想和假设。因此,在学习第二门语言时,你必须首先忘掉这些假设。在你学习第二门甚至是第三门语言时,一定要牢记这一点。剖析编程现有的编程语言已经超过了5,000种,但是TIOBE指数只列出了..._从零开始学编程如何快速入门

python按键精灵是哪个库_Python键鼠操作自动化库PyAutoGUI简介-程序员宅基地

PyAutoGUI是一个Python语言的键鼠自动化库,简单来说和按键精灵的功能一样。但是因为是Python的类库,所以可以使用Python代码配合一些其他类库完成更加强大的功能。下面让我为大家介绍一下吧。安装从pip安装即可。pip install pyautogui稍等一下安装就完毕了。从pip安装类库使用介绍简单介绍一下PyAutoGUI的函数以及使用方法。鼠标操作函数操作鼠标点击的函数。函..._pyautogui和按键精灵对比

Java计算两个经纬度之间的距离_java 经纬度换算成距离_云上上云的博客-程序员宅基地

计算结果是米public class MapUtils { private static double EARTH_RADIUS = 6371.393; private static double rad(double d) { return d * Math.PI / 180.0; } /** * 计算两个经纬度之间的距离 * * @param lat1 * @param lng1 * @param l_java 经纬度换算成距离

I3C——代码相关(杂记)_i3c驱动代码-程序员宅基地

8150代码中当前能够使用的还只是sensor。我们来看下其中的定义以及对应的使用方法。如果支持I3C,那么SSC_TARGET_NO_I3C_SUPPORT该宏将不会被定义。 AMSS/slpi_proc/ssc/build/ssc.scons#'SSC_TARGET_NO_I3C_SUPPORT' to be removed after core team gives ..._i3c驱动代码

开始玩hadoop 11 --Hbase 入门 shell基础命令-程序员宅基地

查看HBASE 状态是60010 端口集群启动后,运行./hbase shell 命令查看状态 :status 查看版本:version创建表:create ‘member’,‘member_id’,‘address’,‘info’(后面三个叫列族,后面会包含多列,多列的集合)查看表信息:list查看表结构(列族):describe xxx删除列族:alter ‘mem

推荐文章

热门文章

相关标签