您好,欢迎访问三七文档
当前位置:首页 > 建筑/环境 > 工程监理 > chrome UI排版-绘制-消息分发机制剖析
ChromeUI框架分析一、总体结构1、概述代码结构UI部分的通用代码放在src/chrome/views目录下。其中:control目录中为各种控件,如Label、Textfield等,这个目录最为庞大。widget目录中为系统相关的UI底层细节,特别是UI消息机制。window目录中为UIFrame相关的细节,例如窗口的标题栏、系统按钮以及、Frame、Dialog等的代理接口。focus目录下为焦点管理、快捷键相关代码。animation中为与动画相关的代码。主要特点1、采用DUI技术,大部分窗口和控件都是DUI的。2、虚窗口的基类是View,每个View可以包含子View,他们组织成一棵树结构。3、真窗口的基类是Widget,它处理与操作系统相关的最原始的消息,在windows上,它处理所有窗口消息。Window是顶层窗口的基类,包括气泡、漂浮窗口、对话框、主窗口等。4、View树的根节点是RootView,这个View的主要用途就是从Widget中接收UI消息,进行分发,包括排版与绘制,它是整个窗口树的根。5、NonClientView表示整个实际的窗口树的根,是RootView唯一的子节点。RootView向上和OS层打交道,而NonClientView则专注于下层的控件View。NonClientView表示整个非客户区的View,包括标题栏、窗口图标、关闭按钮、最大化与最小化按钮、边框等,它负责非客户区的排版与绘制,这类可以被派生,以实现各种不同的客户区。ClientView是客户区的根,负责客户区的排版与绘制。6、排版由专门的LayoutManager负责。7、界面绘制上,绘制引擎(Canvas)与窗框系统分开。可以根据实际情况使用不同的图形引擎(Skia与D2D)。一般情况下,绘图采用Skia,字体用windows的GDI,Skia保证可以跨平台。绘制引擎提供了裁剪、平移变换等机制,使得View可以只重绘一部分,而且支持紧急与非紧急绘制。8、控件消息的响应采用Listener模式。9、绘制通过任务机制实现,从Task派生出一个PaintTask,其Run函数中实现绘制,该任务被放到MessagePumpForUI的任务队列中,每次消息循环的时候取出来执行。10、广泛采用设计模式,顶层窗口的实现大类运用了代理模式,复杂的界面元素采用MVC模式实现界面(排版、绘制、界面消息响应)与逻辑的分离。UI核心类与模块的关系如下图所示:UI的基础代码可以分为消息循环(MessagePumpForUI与MessageLoopForUI)、真窗口(Widget以及派生类)、虚窗口(View以及派生类)、窗口树的根(RootView以及派生类,它实际上是View的派生类)、消息分发与响应、排版(LayoutManager)、绘制(Canvas、CanvasPaint等)、焦点与快捷键管理(FocusManager)组成。这些是UI最底层、最核心的模块,控件建立在这些模块的基础之上。类的继承关系图View是所有控件、子窗口(虚窗口)的基类。View类的派生关系图:这其中有一个庞大的分支为各种控件,具体有:按钮Button菜单Menu滚动条ScrollBar表格TableView树控件TreeView组合框ComboBox列表框ListBox编辑框TextField静态控件Label超链接控件Link其中,树控件、编辑框采用windows自己的原生控件,其他控件均为DUI的。但是有些控件,如按钮等,chrome还包装了windows的原生控件。Widget是所有真窗口的基类,它负责窗口的消息映射、子窗口的管理,每个Widget有一个RootView,作为窗口树的根,管理其子窗口。Widget类的派生关系图:WidgetWin有两类派生类,分别是气泡与漂浮窗口(地址栏自动提示窗口、标签拖出去形成的新窗口、信息气泡、菜单);有标题栏与边框的窗口(对话框、主窗口)。WindowWin是所有有标题栏与边框的窗口的基类(对话框、主窗口)。WindowWin中有客户区(client_view_)与非客户区(frame_view_),WindowWin通过配置不同的客户区,可以形成不同的窗口。WindowImpl是对窗口创建、风格与扩展风格、窗口过程管理的封装。窗口的结构窗口中最大的子窗口是RootView,它是窗口树的根,它有唯一的一个孩子NonClientView。NonClientView是逻辑上的根,它有两个孩子NonClientFrameView和ClientView,前者是窗口的非客户区,负责非客户区的绘制、消息响应;后者是窗口的客户区,负责客户区的绘制、消息响应。这种结构如下图所示:各个类之间的关系如下图所示(虚线为包含,实线为继承):WidgetWin中有成员变量root_view_(RootView),为其窗口树的根,而窗口在初始化时RootView通过SetContentsView设置其孩子节点NonClientView。NonClientView有两个节点frame_view_(NonClientFrameView)与client_view_(ClientView),分别是窗口的客户区与非客户区,各自处理客户区与非客户区的消息、绘制、排版等。WindowWin继承自WidgetWin,是有边框的窗口,其中有成员变量non_client_view_。而WidgetWin并没有该成员,这是因为对于气泡等漂浮窗口,没必要划分客户区与非客户区。非客户区与客户区View的派生关系如下图所示(虚线为包含,实线为继承):ClientView有两个派生类,分别是DialogClientView与BrowserView,前者是对话框的客户区,后者是浏览器主窗口的客户区。NonClientFrameView有4个派生类,其中GlassBrowserFrameView为毛玻璃效果的窗口,OpaqueBrowserFrameView为非透明的窗口。窗口的风格窗口的风格、扩展风格的计算由WindowWin类的的两个函数CalculateWindowStyle、CalculateWindowExStyle统一完成,最基本的风格是WS_CLIPCHILDREN(裁剪孩子)、WS_CLIPSIBLINGS(裁剪兄弟)。主窗口是WS_OVERLAPPED/WS_OVERLAPPEDWINDOW;对话框是WS_POPUP、DS_MODALFRAME;可缩放的窗口是WS_OVERLAPPED、WS_THICKFRAME;控件等原生窗口为WS_CHILD。2、ViewView是View层次结构中的一个矩形区域,是所有View的基类。View是其他View的容器。View有一些基本属性,用于缩放、排版、绘制、事件分发等。View采用简单的盒式排版管理器,类似于XUL的SprocketLayout系统。基类只提供了抽象的接口,很由子类负责实现绘制、与子类相关的属性、函数。View的的继承关系classView:publicAcceleratorTargetAcceleratorTarget是一个虚基类,它有唯一一个成员函数AcceleratorPressed,用于处理快捷键消息。因此,所有View都可以处理快捷键View的主要数据成员是否Eanable:boolenabled_;是否能够获得焦点:boolfocusable_;View所占的区域:gfx::Rectbounds_;注意,该区域是相对于其父窗口的坐标系。是否需要排版:boolneeds_layout_;父节点:View*parent_;子节点数组:ViewListchild_views_;排版管理器,永于对子窗口的排版:scoped_ptrLayoutManagerlayout_manager_;是否可见:boolis_visible_;背景:scoped_ptrBackgroundbackground_;边框:scoped_ptrBorderborder_;是否被父亲拥有:boolis_parent_owned_;当可视区域改变时需要通知的后代View的列表:scoped_ptrViewListdescendants_to_notify_;该View的名字:std::wstringaccessible_name_;按Tab键时下一个获得焦点的View:View*next_focusable_view_;按Shift-Tab键时下一个获得焦点的View:View*previous_focusable_view_;焦点管理器:FocusManager*accelerator_focus_manager_;快捷键列表:scoped_ptrstd::vectorAcceleratoraccelerators_;size_tregistered_accelerator_count_;右键菜单管理器:ContextMenuController*context_menu_controller_;拖拽管理器,负责为View写拖拽数据,同时提供拖拽支持:DragController*drag_controller_;窗口树的组织(黄色为父节点指针,蓝色为子节点指针):ContextMenuController右键菜单管理器为一个抽象接口,View中有这个成员,这使得所有View及其子类都具有显示、响应右键菜单的能力:classContextMenuController{public:virtualvoidShowContextMenu(View*source,constgfx::Point&p,boolis_mouse_gesture)=0;protected:virtual~ContextMenuController(){}};其中唯一一个成员函数是ShowContextMenu,用于为View显示右键菜单,其中source是要显示菜单的View的指针,p是菜单显示的位置,为屏幕坐标系。DragController也是一个抽象的接口,负责为View的拖拽写数据,View中有这个成员,这使得所有View都支持拖拽。classDragController{public://Writesthedataforthedrag.virtualvoidWriteDragData(View*sender,constgfx::Point&press_pt,OSExchangeData*data)=0;//Returnsthesupporteddragoperations(seeDragDropTypesforpossible//values).Adragisonlystartedifthisreturnsanon-zerovalue.virtualintGetDragOperations(View*sender,constgfx::Point&p)=0;//Returnstrueifadragoperationcanbestarted.//|press_pt|representsthecoordinateswherethemousewasinitially//presseddown.|p|isthecurrentmousecoordinates.virtualboolCanStartDrag(View*sender,constgfx::Point&press_pt,constgfx::Point&p)=0;protected:virtual~DragController(){}};AcceleratorTarget为快捷键接收者,所有View都从其中派生,这使得所有View及其子类都具有处理快捷键的能力。AcceleratorTarget的唯一一个成员函数为AcceleratorPressed,用于处理具体的快捷键,各个View可以重写此函数,用于处理自己的快捷键。charView::kVie
本文标题:chrome UI排版-绘制-消息分发机制剖析
链接地址:https://www.777doc.com/doc-5593315 .html