一点Duilib编程总结.docx_第1页
一点Duilib编程总结.docx_第2页
一点Duilib编程总结.docx_第3页
一点Duilib编程总结.docx_第4页
一点Duilib编程总结.docx_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

一点Duilib编程总结1.duilib简介duilib是一个开源的DirectUI界面库,简洁但是功能强大。而且还是BSD的license,所以即便是在商业上,大家也可以安心使用。现在大家可以从这个网站获取到他们所有的源码:/p/duilib/为了让我们能更简单的了解其机制,我们按照如下顺序一步一步的来对他进行观察:工具库:用于支撑整个项目的基础控件库:这是dui最关键的部分之一,相信也是大家最关注的部分之一,另外这里也来看看它是如何管理这些控件的消息流转:有了控件库,我们需要将Windows窗口的原生消息流转给这些控件,另外在这里也来看看Focus,Capture等等的实现资源组织和皮肤加载:有了上面所有的这些,我们再来看看它是如何自动创建皮肤的简单使用:最后,来看看到底要如何使用它以下是duilib工程带的一副总体设计图,在看代码之前看看这幅图,对看代码会很有帮助。duilib:2.工具库由于duilib没有对外部的任何库进行依赖,所以在其内部实现了很多用于支撑项目的基础类,这些类分布在Util文件夹中:UI相关:CPoint/CSize/CDuiRect简单容器:CStdPtrArray/CStdValArray/CStdString/CStdStringPtrMap上面这些类看名字就基本能够理解其具体的含义了,当然除了基本的基础库,还有一些和窗口使用相关的工具的封装:窗口工具:WindowImplBase,这个工具我们在这里不详述,后面会再次提到。3.控件库控件库在duilib的实现中被分为了两块:Core和Control:Core中包含的是所有控件公用的部分,里面主要是一些基类和绘制的封装。Control中包含的就是各个不同的控件的行为了。Core部分和控件相关的类图非常简单:duilib-core:3.1.控件基类:CControlUICControlUI在整个控件体系中非常重要,它是所有控件的基类,也是组成控件树的基本元素,控件树中所有的节点都是一个CControlUI。他基本包括了所有控件公共的属性,如:位置,大小,颜色,是否有焦点,是否被启用,等等等等。当然这个类中还提供了非常多的基础函数,用于重载来实现子控件,如获取控件名称和ClassName,是否显示,等等等等。另外为了方便从XML中直接解析出控件的各个属性,这个类中还在提供了一个SetAttribute的方法,传入字符串的属性名称和值对特定的属性进行设置,内部其实就是挨个比较字符串去完成的,所以平时使用的时候就还是不要使用的比较好了,因为每个属性实际上都有特定的方法来获取和设置。另外每个控件中还有几个事件管理的对象CEventSource,这些对象会在特定的时机被触发,如OnInit,调用其中保存的各个回调函数。3.1.1.控件类型转换这里我们就碰到一个问题,控件树中的每一个节点都是CControlUI,但是其实这些节点可能是文字,可能是图像,也有可能是列表,那么他怎么在这些控件指针之间进行转换呢?强制转型不是一个好的选择,duilib中使用的是CControlUI:GetInterface,传入一个字符串,传出指向控件的指针。类似于COM的QueryInterface。LPVOIDCControlUI:GetInterface(LPCTSTRpstrName)if(_tcscmp(pstrName,_T(Control)=0)returnthis;returnNULL;3.2.容器基类:CContainerUI有了基本的控件基类之后,我们就需要容器来将他管理起来,这个容器就是CContainerUI,其内部用一个数组来保存所有的CControlUI的对象,后续的所有工作,就都是基于这个对象来进行的了。这样在CContainerUI里面,主要实现了一下几个功能:子控件的查找:CContainerUI:FindControl子控件的生命周期管理:是否销毁(在Remove的时候自动销毁)/是否延迟销毁(交给CPaintMangerUI去一起销毁)。滚动条:所有的容器都支持滚动条,在其内部会对键盘和鼠标滚轮事件进行处理(CContainerUI:DoEvent),对其内部所有的元素调整位置,最后在绘制的时候实现滚动的效果绘制:由于容器中有很多元素,所以为了加快容器的绘制,绘制的时候会获取其真正需要绘制的区域,如果子控件不在此区域中,那么就不予绘制了3.3.控件实现有了普通的基类和容器的基类之后,我们就可以在其之上搭建控件了。其类图大致如下:duilib-control:3.3.1.基本控件duilib实现了非常多的基本控件,他们分布在Control文件夹下,每一个头文件就是一个控件,主要有:CLabelUI/CTextUI/CEditUI/CRichEditUICButtonUI/CCheckBoxUI/COptionUI(RadioButton)CScrollBarUI/CProgressUI/CSliderUICListUICDateTimeUI/CActiveXUI/CWebBrowserUI3.3.2.Layout除了基本控件之外,duilib为了辅助大家对界面元素进行布局,还在中间实现了专门用于Layout的元素:CChildLayoutUICHorizontalLayoutUI/CVerticalLayoutUI/CTileLayoutUI:纵向排列,横向排列格子排列CTabLayoutUI:Tab3.3.3.控件绘制绘制控件实际上有很多代码都是可以抽取出来的,比如:九宫格拉伸图片,平铺图片等等工作,我们实际上都不需要每次都去重写。所以这部分代码被抽取出来,形成了CRenderEngine,这个类在Core/UIRender下。在这个里面,我们可以看到很多的用于绘制方法。classUILIB_APICRenderEnginepublic:/.staticvoidDrawLine(HDChDC,constRECT&rc,intnSize,DWORDdwPenColor);staticvoidDrawRect(HDChDC,constRECT&rc,intnSize,DWORDdwPenColor);staticvoidDrawRoundRect(HDChDC,constRECT&rc,intwidth,intheight,intnSize,DWORDdwPenColor);staticvoidDrawText(HDChDC,CPaintManagerUI*pManager,RECT&rc,LPCTSTRpstrText,DWORDdwTextColor,intiFont,UINTuStyle);staticvoidDrawHtmlText(HDChDC,CPaintManagerUI*pManager,RECT&rc,LPCTSTRpstrText,DWORDdwTextColor,RECT*pLinks,CDuiString*sLinks,int&nLinkRects,UINTuStyle);/.;3.4.控件管理:CPaintManagerUI当所有这些基本的控件都准备好了之后,我们就只要将这些控件管理起来,这样一个基本的控件库就完成了,而这个管理就是CPaintManagerUI来负责的。在duilib中,一个Windows的原生窗口和一个CPaintManagerUI一一对应。其主要负责如下几个内容,后面会分开来细说,现在先了解一个概念就行:控件管理资源管理转化并分发Windows原生的窗口消息为了实现上面这些功能,其中有几个用于管理控件和资源的关键的数据结构:m_pRoot:保存根控件的节点m_mNameHash:保存控件名称Hash和控件对象指针的关系m_mOptionGroup:保存控件相关的Group,这个Group并不是TabOrder,他用于实现Option控件m_aCustomFonts:用来管理字体资源m_mImageHash:用来管理图片资源这些结构基本都可以看作是一堆列表和Map,这样可以用其来实现控件和资源的管理了。4.消息流转有了控件,现在我们的问题是,如何将原生的窗口消息分发给界面中所有的控件,使其行为和原生的一样呢?4.1.窗口基础类:CWindowWnd在duilib中,用来表示窗口的最基础的类是CWindowWnd,在这个类中实现了如下基本的内容:原生窗口的创建(CWindowWnd:Create)Subclass(CWindowWnd:Subclass)最基本的消息处理函数(CWindowWnd:_WndProc)和消息分发(CWindowWnd:HandleMessage)模态窗口(CWindowWnd:ShowModal)duilib通过这个类,将原生窗口的消息分发给其派生类,最后传给整个控件体系。另外在duilib中,需要进行消息处理的基本控件,都是从这个类继承出来的。4.2.消息分发一旦我们使用CWindowWnd类创建了窗口之后,消息就会通过CWindowWnd:HandleMessage进行分发,我们可以和WTL等其他的库一样,在此对原始的窗口消息进行处理。LRESULTCWindowWnd:HandleMessage(UINTuMsg,WPARAMwParam,LPARAMlParam)return02:CallWindowProc(m_OldWndProc,m_hWnd,uMsg,wParam,lParam);当然如果我们觉得这样麻烦,我们也可以使用CPaintManagerUI来对其进行默认处理。我们上面提到CPaintManagerUI还会对所有的控件进行管理,这样,消息就传递给了窗口内部特定的控件了。这些默认处理集中在CPaintManagerUI:MessageHandler()中,其内部会对很多窗口消息进行处理,并将其分发到对应的控件上去,比如对WM_LBUTTONDOWN的处理。caseWM_LBUTTONDOWN:/.POINTpt=GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam);m_ptLastMousePos=pt;CControlUI*pControl=FindControl(pt);/.TEventUIevent=0;event.Type=UIEVENT_BUTTONDOWN;/.pControl-Event(event);break;4.2.1.Focus&Capture通过上面这个最简单的例子,我们基本可以猜到duilib对Focus和Capture的处理方法了:用一个成员变量保存对应的控件,在消息到达时直接转发消息。在CPaintMainagerUI中,大家可以找到一个成员变量:m_pFocus,这个就是用来保存焦点控件的。在WM_KEYDOWN等键盘消息发生时,duilib就会模拟Windows行为,将消息直接转给当前Focus的控件。caseWM_KEYDOWN:if(m_pFocus=NULL)break;TEventUIevent=0;event.Type=UIEVENT_KEYDOWN;/.m_pFocus-Event(event);/.break;但是很奇怪的是,duilib里面并没有对Capture做处理,分发鼠标消息到对应的子控件上,可能是还没有完善的原因。4.2.2.其他消息分发方式除了Event以外,CPaintManagerUI还提供了其他几种用于处理消息的方法:Notifier:在窗口上处理一些控件的逻辑,可以将其看成和WM_NOTIFY差不多的功能PreMessageFilter:消息预处理,这个大家肯定不陌生了。PostPaint:绘制后的回调TranslateAccelerator:快捷键的处理这里需要注意的是:PreMessageFilter和TranslateAccelerator是通过全局数组来实现的,这并不符合多线程的窗口编程要求,所以duilib对多线程的支持并不是很好!4.3.WindowImplBase为了简化duilib的使用,库中提供了一个非常方便的工具:WindowImplBase。这个类将常用的功能封装在其内部,比如Notifier和PreMessageFilter,并在其中提供了各种默认的虚回调函数,供派生类重载。通过这个类,我们可以非常方便的来实现一个简单的界面。classUILIB_APIWindowImplBase:publicCWindowWnd,publicCNotifyPump,publicINotifyUI,publicIMessageFilterUI,publicIDialogBuilderCallback/.virtualUINTGetClassStyle()const;/.virtualLRESULTOnClose(UINT/*uMsg*/,WPARAM/*wParam*/,LPARAM/*lParam*/,BOOL&bHandled);virtualLRESULTOnDestroy(UINT/*uMsg*/,WPARAM/*wParam*/,LPARAM/*lParam*/,BOOL&bHandled);/.5.资源组织和皮肤加载好了,现在我们已经有了控件管理和控件库,现在我们需要让UI框架来帮忙组织这些资源,并且自动的来帮我们创建皮肤,减少我们的开发量。duilib中的皮肤文件主要有几个部分组成:xml描述文件:描述窗口中控件的布局和样式各种资源如图片我们把这些资源放在一个文件夹中,这样就形成了基础的皮肤包。当然我们还可以将其组合成一个zip包,从而加快IO访问,但是修改起来就会相对麻烦。所以我们可以在debug中使用前者,而在release中使用后者。我们可以在binskin下面找到duilib中自带demo的所有的皮肤包。皮肤中,最关键的部分就是这个xml描述文件了,一个xml描述文件对应着一个窗口的信息,如:控件的类型和样式等等。为了有一个直观的印象,我截取了duilib中ListDemo的xml描述文件的一部分放在这里:.为了通过配置文件自动创建皮肤,duilib提供了一个类:CDialogBuilder(DuiLibCoreUIDlgBuilder.h)。这个类提供了从皮肤包(文件夹和zip格式)中的xml中创建皮肤的方法:CDialogBuilder:Create。内部实际上就是一个xml的解析,依次创建各式控件。除了创建控件,这个类还将一些可以复用的资源提取出来放入CPaintManagerUI中统一管理,如字体和图片等等。6.简单使用由于项目里面实在是带了太多太多的demo,而且在duilib的工程中,还有一个doc的目录,里面也非常详细的描述了要如何使用duilib来创建一个简单的工程。所以关于duilib的简单使用,这里就不再详述了,这里就只列出GameDemo的main

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论