码迷,mamicode.com
首页 > 其他好文 > 详细

Duilib 学习源码系列1-创建控件

时间:2014-08-01 04:40:51      阅读:347      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   使用   for   ar   代码   div   

    好了,昨天研究出了为什么加载xml结束以后我在自己新建一个控件位置不能调整,原来要先add才能调属性。

    本来这个是昨天的任务,虽然这块内容是前天就看完的,权当边写边复习吧。

    上一篇提到

    <VerticalLayout name="window" bkcolor="#FFFFFFFF" bkcolor2="#FFAAAAA0" bkcolor3="#00000000"> 代表了一个控件字符串;

    上次忘记说了 及时经过那个parser函数处理以后 变成了:

    0VerticalLayout0name0"window"0bkcolor0"#FFFFFFFF"0bkcolor20"#FFAAAAA0"0bkcolor30"#00000000"0

    0代表了原先这个位置的ascii码已经变成了0,也就是字符串结尾标记。

    这样做有啥好处?

    比如你知道这个控件字符串的起始位置,那么假设这个控件字符串是一个LPCTSTR类型的指针LpStr

    那么 CString ControlName = LpStr;此时,ControlName的值就为VerticalLayout;

    那么之后就可以获得属性的偏移量,为LpStr + ControlName.Getlenth()*sizeof(WCHAR);

    之后我们就可以依照类似的方法建立一张属性的表,只需要记录下属性名称的偏移量以及属性值的偏移量.之后就可以获得你要获得属性值了。

    (PS:duilib 内部不会像我这么sb的来操作,不过基本道理差不多。);

    每一个控件都存在一个叫做CMarkupNode的类中来维护的。

    好了下面说说创建控件了。。

    CControlUI* CDialogBuilder::Create(IDialogBuilderCallback* pCallback, CPaintManagerUI* pManager, CControlUI* pParent)先是调用这个函数来把windows窗口的设置弄好(大小啊,字体啊之类的);

之后就是调用CControlUI* CDialogBuilder::_Parse(CMarkupNode* pRoot, CControlUI* pParent, CPaintManagerUI* pManager)来创建(贴代码!)

  1 CControlUI* CDialogBuilder::_Parse(CMarkupNode* pRoot, CControlUI* pParent, CPaintManagerUI* pManager)
  2 
  3 {
  4 
  5     IContainerUI* pContainer = NULL;
  6 
  7     CControlUI* pReturn = NULL;
  8 
  9     for( CMarkupNode node = pRoot->GetChild() ; node.IsValid(); node = node.GetSibling() ) {//检索子控件队列(第一次进入该函数 proot指向的节点必然是<windows XXXXXXX >这个节点.因为控件队列的最顶端且最前面的就是他)
 10 
 11         LPCTSTR pstrClass = node.GetName();
 12 
 13         if( _tcscmp(pstrClass, _T("Image")) == 0 || _tcscmp(pstrClass, _T("Font")) == 0  14 
 15             || _tcscmp(pstrClass, _T("Default")) == 0 ) continue;
 16 
 17  
 18 
 19         CControlUI* pControl = NULL;
 20 
 21         if( _tcscmp(pstrClass, _T("Include")) == 0 ) {
 22 
 23             if( !node.HasAttributes() ) continue;
 24 
 25             int count = 1;
 26 
 27             LPTSTR pstr = NULL;
 28 
 29             TCHAR szValue[500] = { 0 };
 30 
 31             SIZE_T cchLen = lengthof(szValue) - 1;
 32 
 33             if ( node.GetAttributeValue(_T("count"), szValue, cchLen) )
 34 
 35                 count = _tcstol(szValue, &pstr, 10);
 36 
 37             cchLen = lengthof(szValue) - 1;
 38 
 39             if ( !node.GetAttributeValue(_T("source"), szValue, cchLen) ) continue;
 40 
 41             for ( int i = 0; i < count; i++ ) {
 42 
 43                 CDialogBuilder builder;
 44 
 45                 if( m_pstrtype != NULL ) { // 使用资源dll,从资源中读取
 46 
 47                     WORD id = (WORD)_tcstol(szValue, &pstr, 10); 
 48 
 49                     pControl = builder.Create((UINT)id, m_pstrtype, m_pCallback, pManager, pParent);
 50 
 51                 }
 52 
 53                 else {
 54 
 55                     pControl = builder.Create((LPCTSTR)szValue, (UINT)0, m_pCallback, pManager, pParent);
 56 
 57                 }
 58 
 59             }
 60 
 61             continue;
 62 
 63         }
 64 
 65         //树控件XML解析
 66 
 67         else if( _tcscmp(pstrClass, _T("TreeNode")) == 0 ) {
 68 
 69             CTreeNodeUI* pParentNode    = static_cast<CTreeNodeUI*>(pParent->GetInterface(_T("TreeNode")));
 70 
 71             CTreeNodeUI* pNode            = new CTreeNodeUI();
 72 
 73             if(pParentNode){
 74 
 75                 if(!pParentNode->Add(pNode)){
 76 
 77                     delete pNode;
 78 
 79                     continue;
 80 
 81                 }
 82 
 83             }
 84 
 85  
 86 
 87             // 若有控件默认配置先初始化默认属性
 88 
 89             if( pManager ) {
 90 
 91                 pNode->SetManager(pManager, NULL, false);
 92 
 93                 LPCTSTR pDefaultAttributes = pManager->GetDefaultAttributeList(pstrClass);
 94 
 95                 if( pDefaultAttributes ) {
 96 
 97                     pNode->ApplyAttributeList(pDefaultAttributes);
 98 
 99                 }
100 
101             }
102 
103  
104 
105             // 解析所有属性并覆盖默认属性
106 
107             if( node.HasAttributes() ) {
108 
109                 TCHAR szValue[500] = { 0 };
110 
111                 SIZE_T cchLen = lengthof(szValue) - 1;
112 
113                 // Set ordinary attributes
114 
115                 int nAttributes = node.GetAttributeCount();
116 
117                 for( int i = 0; i < nAttributes; i++ ) {
118 
119                     pNode->SetAttribute(node.GetAttributeName(i), node.GetAttributeValue(i));
120 
121                 }
122 
123             }
124 
125  
126 
127             //检索子节点及附加控件
128 
129             if(node.HasChildren()){
130 
131                 CControlUI* pSubControl = _Parse(&node,pNode,pManager);
132 
133                 if(pSubControl && _tcscmp(pSubControl->GetClass(),_T("TreeNodeUI")) != 0)
134 
135                 {
136 
137                     //                     pSubControl->SetFixedWidth(30);
138 
139                     //                     CHorizontalLayoutUI* pHorz = pNode->GetTreeNodeHoriznotal();
140 
141                     //                     pHorz->Add(new CEditUI());
142 
143                     //                     continue;
144 
145                 }
146 
147             }
148 
149  
150 
151             if(!pParentNode){
152 
153                 CTreeViewUI* pTreeView = static_cast<CTreeViewUI*>(pParent->GetInterface(_T("TreeView")));
154 
155                 ASSERT(pTreeView);
156 
157                 if( pTreeView == NULL ) return NULL;
158 
159                 if( !pTreeView->Add(pNode) ) {
160 
161                     delete pNode;
162 
163                     continue;
164 
165                 }
166 
167             }
168 
169             continue;
170 
171         }
172 
173 //这里开始的上面那部分我没怎么看懂- - 毕竟还没有写过duilib的程序有些属性完全不了解- - 我感觉好像就是对一些依赖的东西做些初始化
174 
175         else {
176 
177             SIZE_T cchLen = _tcslen(pstrClass);
178 
179             switch( cchLen ) {//new 相应的控件
180 
181                …(此处篇幅太大,以删除,总而言之就是根据控件类型来new对应的类)
182 
183             }
184 
185             // User-supplied control factory
186 
187             if( pControl == NULL ) {
188 
189                 CStdPtrArray* pPlugins = CPaintManagerUI::GetPlugins();
190 
191                 LPCREATECONTROL lpCreateControl = NULL;
192 
193                 for( int i = 0; i < pPlugins->GetSize(); ++i ) {
194 
195                     lpCreateControl = (LPCREATECONTROL)pPlugins->GetAt(i);
196 
197                     if( lpCreateControl != NULL ) {
198 
199                         pControl = lpCreateControl(pstrClass);
200 
201                         if( pControl != NULL ) break;
202 
203                     }
204 
205                 }
206 
207             }
208 
209             if( pControl == NULL && m_pCallback != NULL ) {
210 
211                 pControl = m_pCallback->CreateControl(pstrClass);
212 
213             }
214 
215         }
216 
217  
218 
219 #ifndef _DEBUG
220 
221         ASSERT(pControl);
222 
223 #endif // _DEBUG
224 
225             if( pControl == NULL )
226 
227             {
228 
229 #ifdef _DEBUG
230 
231                 DUITRACE(_T("未知控件:%s"),pstrClass);
232 
233 #else
234 
235                 continue;
236 
237 #endif
238 
239             }
240 
241  
242 
243         // Add children
244 
245         if( node.HasChildren() ) {//是否有子节点,突然想到第一篇的控件数组中,有标记记录是否有子节点的.
246 
247             _Parse(&node, pControl, pManager);//遍历子节点控件
248 
249         }
250 
251         // Attach to parent
252 
253         // 因为某些属性和父窗口相关,比如selected,必须先Add到父窗口
254 
255         if( pParent != NULL ) {//加入父控件队列中
256 
257             CTreeNodeUI* pContainerNode = static_cast<CTreeNodeUI*>(pParent->GetInterface(_T("TreeNode")));
258 
259             if(pContainerNode)
260 
261                 pContainerNode->GetTreeNodeHoriznotal()->Add(pControl);
262 
263             else
264 
265             {
266 
267                 if( pContainer == NULL ) pContainer = static_cast<IContainerUI*>(pParent->GetInterface(_T("IContainer")));
268 
269                 ASSERT(pContainer);
270 
271                 if( pContainer == NULL ) return NULL;
272 
273                 if( !pContainer->Add(pControl) ) {//父节点将子节点加入父节点的子控件队列中.
274 
275                     delete pControl;
276 
277                     continue;
278 
279                 }
280 
281             }
282 
283         }
284 
285         // Init default attributes
286 
287         if( pManager ) {
288 
289             pControl->SetManager(pManager, NULL, false);
290 
291             LPCTSTR pDefaultAttributes = pManager->GetDefaultAttributeList(pstrClass);
292 
293             if( pDefaultAttributes ) {
294 
295                 pControl->ApplyAttributeList(pDefaultAttributes);
296 
297             }
298 
299         }
300 
301         // Process attributes
302 
303         if( node.HasAttributes() ) {//添加控件属性
304 
305             TCHAR szValue[500] = { 0 };
306 
307             SIZE_T cchLen = lengthof(szValue) - 1;
308 
309             // Set ordinary attributes
310 
311             int nAttributes = node.GetAttributeCount();
312 
313             for( int i = 0; i < nAttributes; i++ ) {
314 
315                 pControl->SetAttribute(node.GetAttributeName(i), node.GetAttributeValue(i));
316 
317         // GetAttributeXXXX这个函数就是前面所说的属性建表了,根据序号取出对应的值以及属性名称,其实内部不止根据序号,还有属性名称来取对应的值等等操作
318 
319             }
320 
321         }
322 
323         if( pManager ) {
324 
325             pControl->SetManager(NULL, NULL, false);//清空信息(虽然我也不知道为什么要这么做)不过看了下后面的代码会重新赋值的.不过子节点设置父节点为空,但是父节点依旧可以找到子节点…
326 
327         }
328 
329         // Return first item
330 
331         if( pReturn == NULL ) pReturn = pControl;//返回子控件队列中的第一个元素.所有<window XXXX>的节点下只能有一个子控件,多余的就被无视了
332 
333     }
334 
335     return pReturn;
336 
337 }

 

好快~ 控件的创建就讲完了 有事有啥不妥的欢迎指正 谢谢了

Duilib 学习源码系列1-创建控件,布布扣,bubuko.com

Duilib 学习源码系列1-创建控件

标签:style   blog   color   使用   for   ar   代码   div   

原文地址:http://www.cnblogs.com/verpas/p/3883846.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!