DirectUI的初步分析

最近由于项目的需要学习了一下DirectUI方面的东西,主要借鉴的是一个国外程序员写的代码(见引用一),看了后发现它更多的是探讨一种实现的可能性和思路,和实际应用还是有距离的,不过其实现还是很有意思的。在写此小结的时候又发现国内一个程序员将这个代码部分移植到WINCE下的代码(见引用二),因为平台的差异性要完全开发一个WINCE下的实际代码还是需要时间的。 
由于本人GUI开发做得少,工作中有关这方面的东西主要是提供思路和方法,学习DirectUI的主要目的是为了更新知识学习思路,文章中难免出现错误。

一、核心 
1、CWindowWnd: 窗口对象类(窗口实例对象父类) 
2、CDialogBuilder: 创建控件类,分析脚本并用递归方式(_Parse函数)创建所有控件实例 
3、CPaintManagerUI: 窗口消息及图形绘制管理器类 
4、CGUIRenderEngineUI: 图形渲染引擎类,在离屏DC中生成最终显示的图形,可根据需要扩展多种图形效果显示。 
5、INotifyUI: 事件通知抽象类 
6、IMessageFilterUI: 消息过滤抽象类

二、控件 
CControlUI: 控件管理抽象父类,父类INotifyUI 
1、button 
CButtonUI: 按钮控件 
COptionUI: 选择按钮控件

2、combox 
CSingleLinePickUI: 
CDropDownUI: 下拉控件,父类另有CContainerUI和IListOwnerUI

3、decoration 
CTitleShadowUI: 阴影效果 
CListHeaderShadowUI 
CSeparatorLineUI 
CFadedLineUI

4、edit 
CSingleLineEditUI: 单行编辑框控件 
CMultiLineEditUI: 多行编辑框控件

5、label 
CLabelPanelUI: 可设置背景色和文字色的静态标签控件 
CGreyTextHeaderUI

6、list 
第一种: 
CListUI: 列表控件,包含以下几个子控件 
(1)CListHeaderItemUI: 列表头 
(2)CListExpandElementUI: 列表项 
第二种:用法不明 
CListHeaderUI: 列表头 
CListElementUI: 列表项,父类另有IListItemUI 
CListLabelElementUI: 列表项,父类CListElementUI 
CListTextElementUI: 列表项 
CListFooterUI: 列表尾

7、panel 
CTextPanelUI: 父类CLabelPanelUI 
CTaskPanelUI: 
CNavigatorPanelUI: 导航面板,父类另有IListOwnerUI,包含CNavigatorButtonUI子控件 
CSearchTitlePanelUI: 
CImagePanelUI: 图片显示 
CWarningPanelUI: 警告提示,父类CTextPanelUI 
CPaddingPanelUI: 填充栏

8、tab 
CTabFolderUI: 父类另有CContainerUI和IListOwnerUI 
CTabPageUI: 父类另有CContainerUI

9、toolbar 
CToolbarUI: 工具栏,包含以下几个子控件 
(1)CToolButtonUI: 图形按钮 
(2)CToolSeparatorUI: 分隔符 
(3)CToolGripperUI:  gripper

10、title 
CToolbarTitlePanelUI:

11、statusbar 
CStatusbarUI: 状态栏,父类另有CContainerUI

12、anim 
CAnimJobUI: 动画显示类

13、ActiveX 
CActiveXUI:

三、容器: 
CContainerUI: 容器类,父类CControlUI和IContainerUI。可以认为容器是特殊的控件(见上面控件类关于父类的说明),其目的之一是具有容器特性的控件可以容纳其它控件,这样可以方便的实现控件的叠加;目的之二实际的窗口只有一个,对于叠加的控件必须要进行层次管理才能正确绘图和事件分发。另外可参见引用三 
1、画布: CCanvasUI(父类CContainerUI),可绘制背景色、画线、贴图 
CWindowCanvasUI: 父类CCanvasUI 
CControlCanvasUI: 父类CCanvasUI 
CWhiteCanvasUI: 父类CCanvasUI 
CDialogCanvasUI: 父类CCanvasUI 
CTabFolderCanvasUI: 父类CCanvasUI 
2、布局: 管理不同层次的控件 
CDialogLayoutUI: 父类CContainerUI 
CVerticalLayoutUI: 父类CContainerUI 
CHorizontalLayoutUI: 父类CContainerUI 
CTileLayoutUI: 父类CContainerUI

四、通用 
1、script 
CMarkup 
CMarkupNode

2、language 
CUIUtility

3、multi-thread 
CriticalSection 
AutoCriticalSection 
CMutex 
CAutoMutex 
CEvent 
CAutoEvent 
CManualEvent

五、主要数据成员 
1、CPaintManagerUI 
CControlUI* m_pRoot: 如果控件是叠加的则存放最下层的控件对象,否则存放第一个创建的控件对象 
CControlUI* m_pFocus: 存放获得焦点的控件对象指针 
CControlUI* m_pEventHover: 存放当前有鼠标移进移出事件的控件对象指针 
CControlUI* m_pEventClick: 存放当前有点击事件的控件对象指针 
CControlUI* m_pEventKey: 存放当前有按键事件的控件对象指针 
CStdPtrArray m_aNotifiers: 记录所有需要事件通知的窗口,根据窗口名称调用相应的消息处理函数 
CStdPtrArray m_aNameHash: 保存控件对象指针hash表(用控件名称生成hash值) 
CStdPtrArray m_aPostPaint: panel的fade效果 
CStdPtrArray m_aMessageFilters: 保存需要进行消息过滤的控件或功能(如动画类) 
CStdPtrArray m_aDelayedCleanup: 
CStdPtrArray m_aPreMessages: 预处理消息 
HWND m_hWndPaint: 控件布局窗口句柄 
HDC m_hDcPaint: 控件布局窗口设备DC 
HDC m_hDcOffscreen: 离屏内存DC 
HBITMAP m_hbmpOffscreen: 离屏内存DC相关联HBITMAP

2、CControlUI 
CPaintManagerUI* m_pManager: 窗口消息或绘图管理器 
CControlUI* m_pParent: 逻辑上的父窗口(控件)对象指针 
CStdString m_sName: 控件标识 
CStdString m_sText: 控件显示标题或显示脚本字符串 
CStdString m_sToolTip: 控件的Tip信息

3、CContainerUI 
CStdPtrArray m_items: 同一层的控件对象或控件对象的子对象,例如canvas上放置的按钮、combox由edit和list两个子对象组成,其它还有tab等。具体见CDropDownUI、CTabFolderUI、CNavigatorPanelUI三个类定义

4、CDialogLayoutUI 
CStdValArray m_aModes: 用于存放在Layout上绝对坐标转成相对坐标(CDialogLayoutUI::RecalcArea)的控件对象(指针、大小、模式),目的是否为了让布局上的控件随布局变化而变化,能够正确绘图???

六、控件属性 
待完成

七、脚本例子 
<Dialog> 
  <WindowCanvas pos=/"0,0,600,800/"> 
  <DialogLayout pos=/"0,0,600,800/"> 
    <Button pos=/"390, 30, 490, 58/" text=/"OK/" name=/"ok/"/> 
  </DialogLayout> 
  </WindowCanvas> 
</Dialog>

八、绘图及事件处理 
1、绘图 
STEP01. CWindowWnd::__WndProc: 主窗口程序 
STEP02. pThis->HandleMessage: pThis是布局窗口对象指针,并与布局窗口绑定(SetWindowLongPtr) 
STEP03. m_pm.MessageHandler: m_pm为CPaintManagerUI唯一实例对象 
STEP04. CPaintManagerUI::MessageHandler: 处理WM_PAINT 
STEP05. m_pRoot->DoPaint: m_pRoot为最下层的控件对象(在本例中为CWindowCanvasUI控件,对应脚本中的WindowCanvas) 
STEP06. CCanvasUI::DoPaint: 往画布上绘制背景色、边角弧形、水印等。 
STEP07. CContainerUI::DoPaint: 在最下层具有容器特性的控件(CWindowCanvasUI控件)上画容器内所有控件(控件实例对象保存在m_items中) 
STEP08. pControl->DoPaint: pControl为控件对象实例之一,利用多态性来调用不同控件的绘图方法 
STEP09. CButtonUI::DoPaint: 按钮(对应脚本中Button)绘图方法,有下面两种方法 
i)文字方法: CGUIRenderEngineUI::DPaintButton 
ii)图片方法: CGUIRenderEngineUI::DoPaintBitmap 
STEP10. 新一轮消息循环

2、事件 
STEP01. CWindowWnd::__WndProc: 
STEP02. pThis->HandleMessage: 
STEP03. m_pm.MessageHandler: 
STEP04. CPaintManagerUI::MessageHandler: 处理WM_LBUTTONDOWN 
STEP05. CPaintManagerUI::FindControl: 根据鼠标坐标查找相应控件对象 
STEP06. m_pRoot->FindControl: 
STEP07. CContainerUI::FindControl: 在最下层具有容器特性的控件(CWindowCanvasUI控件)容器内查找相应控件对象 
STEP08. CControlUI::FindControl: 在m_items中查找相对应的控件对象 
STEP09. pControl->Event: pControl为控件对象实例之一,利用多态性来调用不同控件的事件方法 
STEP10. CPaintManagerUI::MessageHandler: 处理WM_LBUTTONUP 
STEP11. m_pEventClick->Event: 利用多态性来调用不同控件的事件方法(m_pEventClick说明见"主要数据成员") 
STEP12. CButtonUI::Event: 按钮(对应脚本中Button)事件方法 
STEP13. CButtonUI::Activate: 
STEP14. m_pManager->SendNotify: 传递控件对象指针和触发事件(文本方式) 
STEP15. CPaintManagerUI::SendNotify: 注意以下两点实现是完成控制和业务分离的关键 
i)利用重载特性调用注册的监听对象(窗口)的消息处理函数Notify(监听对象保存在m_aNotifiers中) 
for( int i = 0; i < m_aNotifiers.GetSize(); ++i ) 

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

ii)布局窗口CStartPageWnd的消息处理,宏定义展开后实际就是重载的Notify函数
DIRECT_BEGIN_NOTIFYMAP(CStartPageWnd) 
    PROCESS_BUTTON_CLICK(_T("ok"),OnOk) 
    。。。 
DIRECT_END_NOTIFYMAP(CStandardPageWnd) 
STEP16. CStartPageWnd::OnOk: 控件消息处理函数,此处可以加入具体的事务逻辑处理 
STEP17. 新一轮消息循环

3、消息定义(文本) 
"click"、"changed"、"link"、"browse"、"itemclick"、"itemselect"、"dropdown"、"itemactivate"、"headerdragging"、"headerclick"、"headerdragged"、"itemexpand"、"itemcollapse"、"windowinit"、"killfocus"、"setfocus"、"timer"

九、疑问 
1、Edit、Combox的下拉列表部分、ScrollBar、Tooltip控件是创建的实际窗口,这个与DirectUI思路还是有差别的 
2、实例中有创建一个不进行消息处理的窗口(CFrameWindowWnd),然后又创建了一个窗口(CStandardPageWnd)用于具体的控件布局。但是我用一个窗口也能实现,原作者为什么这样还不清楚 
3、控件是用文本形式来做标识的,消息类型是文本形式,是否改成数值型比较好

十、引用 
引用一: http://www.viksoe.dk/code/windowless1.htm 
引用二: http://directui.googlecode.com/ 
引用三:http://www.cnblogs.com/cutepig/archive/2010/06/14/1758204.html

转自:http://liyunde.org/?p=1255


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值