上文介绍了网易duilib是如何通过CMarkup
支持标准xml语法的,本文主要介绍duilib特化
xml的作用
在duilib中,xml主要有两种类型:
- 全局资源描述
- 窗口样式设计
全局资源描述
在程序目录下themes\default\global.xml文件里,定义了全局统一的资源类型。其根节点必须为<Global>
标签,如
1 |
|
这些资源可以通过名字在任何地方被使用
全局资源在静态成员函数GlobalManager::LoadGlobalResource
中被加载
1 | void GlobalManager::LoadGlobalResource() |
窗口样式设计
窗口xml文件的根节点必须为<Window>
标签,文件可以放在任何地方
1 |
|
窗口类必须继承自ui::WindowImplBase
,并且重写其GetSkinFolder
以及GetSkinFile
方法设置xml文件
窗口在初始化的时候,会加载xml文件
1 | LRESULT WindowImplBase::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) |
我们可以看到,两者本质上都是通过WindowBuilder
完成解析操作
WindowBuilder
WindowBuilder
在CMarkup
的基础上,完成duilib特化的工作
1 | class Box; |
CreateControlCallback
是自定义控件的回调函数,根据标签值返回对应控件类
Create
函数主要生成布局
_Parse
函数主要生成控件
Global标签、Window标签解析
这两个最外层的标签在Create
函数被处理
Create
函数先处理两者的属性
1 | if (strClass == _T("Global")) |
<Global>
标签支持的属性有
disabledfontcolor
defaultfontcolor
linkfontcolor
linkhoverfontcolor
selectedcolor
Window
标签支持的属性有
size
窗口大小heightpercent
sizebox
caption
允许拖动的recttextid
窗口标题文字roundcorner
圆角mininfo
maxinfo
shadowattached
阴影是否算点击shadowimage
阴影图shadowcorner
阴影圆角alphafixcorner
Create
函数再处理两者的子标签
1 | if (strClass == _T("Global")) |
<Global>
标签支持的子标签有
FontResource
Font
字体,它支持的属性有name
size
bold
underline
italic
Class
样式类TextColor
Window
标签在这层只支持
Class
样式类
完成了<Global>
标签与<Window>
标签的解析后,Create
对xml子节点递归进行其他解析
1 | for( CMarkupNode node = root.GetChild() ; node.IsValid(); node = node.GetSibling() ) { |
Include标签、控件标签、事件标签解析
主要通过_Parse
进行其他解析
1 | Control* WindowBuilder::_Parse(CMarkupNode* pRoot, Control* pParent, Window* pManager) |
- Include
Include
标签实际上是将目标文件拷贝到此处,所以在这里做递归处理 - duilib标准控件
交给CreateControlByClass
处理1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66Control* WindowBuilder::CreateControlByClass(const std::wstring& strControlClass)
{
Control* pControl = nullptr;
SIZE_T cchLen = strControlClass.length();
switch( cchLen ) {
case 3:
if( strControlClass == DUI_CTR_BOX ) pControl = new Box;
break;
case 4:
if( strControlClass == DUI_CTR_HBOX ) pControl = new HBox;
else if( strControlClass == DUI_CTR_VBOX ) pControl = new VBox;
break;
case 5:
if( strControlClass == DUI_CTR_COMBO ) pControl = new Combo;
else if( strControlClass == DUI_CTR_LABEL ) pControl = new Label;
break;
case 6:
if( strControlClass == DUI_CTR_BUTTON ) pControl = new Button;
else if( strControlClass == DUI_CTR_OPTION ) pControl = new Option;
else if( strControlClass == DUI_CTR_SLIDER ) pControl = new Slider;
else if( strControlClass == DUI_CTR_TABBOX ) pControl = new TabBox;
break;
case 7:
if( strControlClass == DUI_CTR_CONTROL ) pControl = new Control;
else if( strControlClass == DUI_CTR_TILEBOX ) pControl = new TileBox;
else if (strControlClass == DUI_CTR_LISTBOX) pControl = new ListBox(new Layout);
//else if( pstrClass == DUI_CTR_ACTIVEX ) pControl = new ActiveX;
break;
case 8:
if( strControlClass == DUI_CTR_PROGRESS ) pControl = new Progress;
else if( strControlClass == DUI_CTR_RICHEDIT ) pControl = new RichEdit;
else if( strControlClass == DUI_CTR_CHECKBOX ) pControl = new CheckBox;
//else if( pstrClass == DUI_CTR_DATETIME ) pControl = new DateTime;
else if( strControlClass == DUI_CTR_TREEVIEW ) pControl = new TreeView;
else if( strControlClass == DUI_CTR_TREENODE ) pControl = new TreeNode;
else if( strControlClass == DUI_CTR_HLISTBOX ) pControl = new ListBox(new HLayout);
else if( strControlClass == DUI_CTR_VLISTBOX ) pControl = new ListBox(new VLayout);
else if ( strControlClass == DUI_CTR_CHILDBOX ) pControl = new ChildBox;
else if( strControlClass == DUI_CTR_LABELBOX ) pControl = new LabelBox;
break;
case 9:
if( strControlClass == DUI_CTR_SCROLLBAR ) pControl = new ScrollBar;
else if( strControlClass == DUI_CTR_BUTTONBOX ) pControl = new ButtonBox;
else if( strControlClass == DUI_CTR_OPTIONBOX ) pControl = new OptionBox;
break;
case 10:
//if( pstrClass == DUI_CTR_WEBBROWSER ) pControl = new WebBrowser;
break;
case 11:
if( strControlClass == DUI_CTR_TILELISTBOX ) pControl = new ListBox(new TileLayout);
else if( strControlClass == DUI_CTR_CHECKBOXBOX ) pControl = new CheckBoxBox;
break;
case 14:
if (strControlClass == DUI_CTR_VIRTUALLISTBOX) pControl = new VirtualListBox;
break;
case 15:
break;
case 16:
break;
case 20:
if( strControlClass == DUI_CTR_LISTCONTAINERELEMENT ) pControl = new ListContainerElement;
break;
}
return pControl;
} - 自定义控件
由Create
传入的CreateControlCallback
回调决定 - XML事件
包括两个标签<Event>
与<BubbleEvent>