|
Posted on 2010-08-07 19:04 S.l.e!ep.¢% 阅读(7898) 评论(1) 编辑 收藏 引用 所属分类: 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: 在布局窗口(对应脚本中DialogLayout)画所有控件(控件实例对象保存在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: 在布局窗口上查找相应控件对象 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
handless UI (direct UI) http:
//
www.viksoe.dk/code/windowless1.htm
viksoe的代码很好,这个可以被运用到商业上。 个人觉得这个框架比mfc甚至wtl的在构架、思想上高N倍。 首先 viksoe采用layout机制动态计算各子窗口的坐标位置,自适应屏幕大小的变化。而MFC要求子窗口的坐标位置硬编码,结果要适应不同分辨率的屏幕 非常困难。GTK
+
在窗口布局时分为两个阶段,第一个阶段父窗口先询问子窗口的最佳大小,第二个阶段父窗口根据自己的大小计算子窗口的实际大小,子窗口根 据实际大小进行调整。
其次viksoe采用容器机制来合理分离控件的职责,MFC没有容器这个概念,很难实现递归组合。viksoe中差 不多所有控件都是容器,都可以容纳其它任何控件,而MFC只有顶层窗口才是容器,可以容纳其它子控件。容器这个概念对代码重用的影响非常之大,这里举两个 例子:其一是带图片的按钮(BitmapButton),在viksoe中它就是CCanvasUI类和CButtonUI的组合,而在MFC中,图片和 文字都要自己绘制。前者的CCanvasUI类和CButtonUI可以在很多地方重用,而后都的绘制代码和事件处理代码只有自己才能使用。在MFC中, 即使只是实现一个不同外观的列表框,你都要采用自绘的方式,代码重用非常困难,向列表框中加入其它控件就更麻烦了,要使用一些非同寻常的手段不可。
另 外说句在驱动里画gui,这个和普通gui有所不同,上面说的directUI还是用到了Windows的消息,而驱动里只能自己hook key 、mouse 中断。然后实现各种消息的派发。但这样对兼容usb接口的键盘很成问题。这实际相当于自己实现了win32k里面的内容。而驱动里面画图其实不过是自己写 显存。但又有很多兼容问题要解决,别的不说,每种显卡的显存位置就要自己实现,所以softICE直接做不下去了,syser在部分机器上也得靠 directX来获取显存。 我的blog hi.baidu.com
/
weolar
HTMLayoutSDK 有时间看下这个,比较好用,用spy
++
去抓,也抓不到任何窗口,而且简单.htm文件描述,做界面那叫一个方便,效果也很不错,关键是免费,现在我都转这个做界面了.
我现在正在研究viksoe的这个DirectUI库,把它改写成wchar_t的了,并把类库中使用的CWindowWnd换成了atl
/
wtl的 CWindowImpl, 我准备好好的在这个DirectUI库的基础上把这个库进行进一步的开发,做一个好用的强大的DirectUI库,有兴趣一块开发的可以联系我,放到 Google code上,大家一块做
!
davidxifeng@gmail.com csdn上留言也行.不过不会经常查看
关注Game内嵌Web浏览器内核(HTML Rendering Engine)
2008
-
10
-
13
21
:
51
网络游戏在游戏内部经常会有一些Web方面的显示需求,利用HTML来实现UI这个早已不是新鲜的玩意,云风就曾经提到大话西游1中采用内嵌IE来实现客户端的UI,尽管当时这种技术方案没有成功,但是对于利用HTML Rendering这样的解析渲染引擎来表现客户端GUI的技术探索还在不断的深入。 HTML Rendering Engine一般由DOM构建,HTML
/
CSS解析,Layout Engine,屏幕渲染等几大模块构成。 其中LayoutEngine负责获取页面的内容(HTML、XML、CSS、图片),并按照W3c的标准规则计算网页显示方式,并最终输出到屏幕。由于布局引擎负责了最重要的功能,因此可以被看作是浏览器的内核。 目前比较有名的内核如下: Gecko,以此为内核的浏览器最出名的莫过于Firefox了。 Webkit则由于google的Chrome而更加出名。Webkit是一个开源的HTML 渲染引擎,由苹果公司基于 KDE 的 KHTML 项目开发而成。 当然由于Window的一统天下,IE的内核Trident也被很多应用所采用,GoogleTalk就是采用Trident来渲染对话界面的。 从这个Wiki上还能看到主流浏览器内核的比较情况:http:
//
en.wikipedia.org/wiki/Comparison_of_layout_engines
对于OnlineGame的简单Web应用需求,其实可以找一些轻量级的内核。HTMLayout就是这样一款针对WebUI的桌面应用和方便嵌入而设计的。但是HTMLayout并非完整特性的Web浏览器,对于一些非标准的HTML标记的渲染还有些问题,不过对于一个轻量级的嵌入引擎来说已经足够完美了。 官网如下:http:
//
www.terrainformatica.com/htmlayout/
其附带的SDK中包含了一个利用DX来渲染表现的例子,原理很简单就是利用RenderingEngine将HTML解析输出到位图上,并转由DX的材质输出。官网下载的例子采用DX8来写的,需要做一些简单改动就可以了。MSN的桌面宠物多猫就利用HTMLayout来实现GUI的。 第二人生中内嵌的浏览器库llMozLib,就是通过内嵌Gecko来进行HTML的渲染显示的,可以在http:
//
ubrowser.com/找到详细的介绍,也可以从第二人生的官网上找到源代码。这个功能就强大多了,值得下功夫研究一下。
Feedback
# DirectUI是目前windows平台上最流行的一种无窗口界面技术 回复 更多评论
2011-02-15 18:39 by
DirectUI是目前windows平台上最流行的一种无窗口界面技术,所有控件都是虚拟控件没有实际窗口,因此效率更高,更安全。目前国内流行的QQ/MSN/迅雷等都采用此种技术 我们的DirectUI具有以下特点:
1.互联网知名公司使用,质量有保证 2.性能优越,可与qq/msn等无窗口界面媲美 3.全部控件都是虚拟控件,更安全,改快速 4.而且内存占用更少 5.支持界面配置化(xml) 6.文档详尽 7.良好的编程风格 8.经过严格测试,无任何GDI和内存泄漏 9.支持换肤 10.可实现透明/渐变等效果 11.支持自定义控件扩展 12.支持可视化编辑,无需编写代码即可生成界面
联系方式:QQ:1276489675 邮箱:1276489675@qq.com
|