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

智能推荐

Qt安装完成后在开始菜单中找不到QT for Desktop解决方法_qt for desktop在哪_xiaoyuVS的博客-程序员宅基地

Qt安装完成后在开始菜单中找不到QT for Desktop安装Qt后在开始菜单中未找到QT for Desktop安装完QT后,开始菜单内容下解决方法在“用户启动文件夹”下查找发现在启动文件夹下有QT for Desktop,如下:..._qt for desktop在哪

Code For Better 谷歌开发者之声——Vue+echarts 前后端结合实现大屏数据可视化_大屏后端生成-程序员宅基地

一、首先介绍一下数据可视化Echarts数据可视化, 说白了, 就是把数据以更加直观的方式进行呈现. 那什么方式是更加直观的方式呢? 就是图表.常言道, 文不如表, 表不如图, 人们大脑对图的敏感程度要比苍白无力的文字好很多...._大屏后端生成

JavaWeb(ajax实现无刷新分页)_java不用刷新网页-程序员宅基地

目录1.准备阶段需要2.需要那些技术来实现无刷新分页3.主要代码部分4.实现后的界面截图1.准备阶段需求1.1首先需要开发工具eclipse1.2需要jar包两个:JSON的jar包:fastjson-1.2.47.jar ojdbc14.jar放入lib中,以及jQuery的类库:jquery-3.3.1.js放到js文件夹内2.需要那些技术来实现无刷新分页 2.1、Java,Oracle数据库,AJAX,jQuery 2.2、需要在项目..._java不用刷新网页

史上最直白的LDA教程之一-程序员宅基地

前言LDA线性鉴别分析,又叫线性鉴别矢量,它是Ronald Fisher发明的,所以有时候又叫Fisher鉴别矢量,它的核化版本叫KFDA(Kernel Fisher Discriminant Analysis)。机器学习的分类问题 ,是一种有监督学习。所谓有监督,就是知道训练样本的类别。顾名思义,无监督学习就是没有样本的类别信息,比如PCA就是无监督学习,如我们前面推导过的PCA,不需要

GOSMatch: Graph-of-Semantics Matching for Detecting Loop Closures in 3D LiDAR data_木得感情的_coder的博客-程序员宅基地

GOSMatch: Graph-of-Semantics Matching for Detecting Loop Closures in 3D LiDAR data利用激光雷达的点云信息检测闭环是一件很不容易的事情,因为激光雷达的数据是不稳定的.本文提出了一种叫做GOSMatch的方法依靠语义级别的信息做场景重识别,本文的方法利用语义物体之间的空间关系产生新颖的描述符. 本文还设计了一种由粗到细的测量来有效的找到闭环.此外, 一旦确定找到了闭环帧,系统就会给出准确的六自由度的位姿估计结果,本文在kitti

随便推点

iOS中UITextView遇到的问题总结-程序员宅基地

前言由于iOS中的UITextField不支持文本换行,所以在有换行需求时,我们只好用UITextView。以下是在使用UITextView时很容易遇到的一些问题。问题一:UITextView显示边框UITextView默认是没有边框颜色的,没有直接的属性来设置边框颜色。可以使用layer属性来解决,代码如下: //设置边框宽度 self.

Simulink中使用了to workspace或者Scope为什么在工作空间什么都没有显示_to workspace 之后找不到-程序员宅基地

记录一下,自己使用to workspace 模块时候工作空间却没有显示,原因是在设置Configuration parameters 中的Simscape 中Data logging——log simulation data 需要把None 改成ALL,并且Data history 里的limitdata的对勾取消掉拿走不谢!..._to workspace 之后找不到

Tensorflow tf.GradientTape()自动求导的记录器_tf.matmul(x, w) tape.gradient(y, [w, b])_qianchedu的博客-程序员宅基地

计算函数在时分别对的偏导数。其中代码import tensorflow as tfX = tf.constant([[1.,2.],[3.,4.]])y = tf.constant([[1.],[2.]])w = tf.Variable(initial_value = [[1.],[2.]])b = tf.Variable(initial_value=1.)with tf.GradientTape() as tape: L = 0.5*tf.reduce_sum(..._tf.matmul(x, w) tape.gradient(y, [w, b])

接入高德开放平台实现地址转换为经纬度坐标_像是一个傻子的博客-程序员宅基地

高德地图API1 地址转为经纬度后台人员填写完房源详情地址后,由此地址转为,电子地图中的经纬度。从而方便日后前台在电子地 图中的标识显示。 高德地图开放平台:https://lbs.amap.com/注:需要注册成为开发者,注册成功后就可以使用此开放平台注册成功后,登录开发放平台,进入后台需要创建一个新的应用创建应用成功后,需要添加一个key添加key得到请求的key注:此key是日后请求api所用的key一定要保存好api地址:https://lbs.amap.com/a_高德开放平台

Java接入微信告警实现代码(Cat点评)_cat 微信使用-程序员宅基地

企业微信下载请参考依赖添加&amp;amp;amp;amp;lt;dependency&amp;amp;amp;amp;gt; &amp;amp;amp;amp;lt;groupId&amp;amp;amp;amp;gt;org.apache.httpcomponents&amp;amp;amp;amp;lt;/groupId&amp;amp;amp;amp;gt; &amp;amp;amp;amp;lt;artifactId&a_cat 微信使用

Android进阶_htpps://molde-video.com/-程序员宅基地

Activity生命周期典型情况下的生命周期对于一个特定Activity,第一次启动,回调:onCreate->onStart->onResume打开新的Activity或切换到桌面:onPause->onStop新打开Activity时,原Activity的onPause先执行,新的Activity的onResume再执行回到原来Activity:onRestar..._htpps://molde-video.com/

推荐文章

热门文章

相关标签