DuiLib(二)——控件创建
2013-12-03 15:28
387 查看
上一篇讲了窗口及消息,了解了大体的程序框架。这一篇说的是控件的创建。
duilib支持XML配置文件,即根据XML创建窗口及控件,将界面与逻辑分开,便于修改及维护。上一篇的示例中可以看到在消息WM_CREATE中有控件创建的相关代码。
控件创建主要牵扯到类CDialogBuilder:
创建控件树,返回根控件:CDialogBuilder::Create
将控件树关联到CPaintManagerUI对象(由名字可猜出其功能与绘制控件有关):CPaintManagerUI::AttachDialog
添加消息通知:CPaintManagerUI::AddNotifier
创建控件树:
读取XML配置文件
解析Image(图片)、Font(字体)、Default(默认属性)、Windows(窗口相关)项(代码太长,省略了细节)
创建控件:CDialogBuilder::_Parse
可以通过include嵌套XML文件
创建控件(自定义控件调用回调函数实现)
添加子控件(解析子控件:递归调用_Parse、关联到父控件:CContainerUI::Add)
返回根控件
控件创建基本就这些,下一篇写控件消息。
duilib支持XML配置文件,即根据XML创建窗口及控件,将界面与逻辑分开,便于修改及维护。上一篇的示例中可以看到在消息WM_CREATE中有控件创建的相关代码。
if( uMsg == WM_CREATE ) { m_pm.Init(m_hWnd); //根据XML创建控件 CDialogBuilder builder; CControlUI* pRoot = builder.Create(_T("HelloWorld.xml"), (UINT)0, NULL, &m_pm); ASSERT(pRoot && "Failed to parse XML"); m_pm.AttachDialog(pRoot); m_pm.AddNotifier(this); return 0; }
控件创建主要牵扯到类CDialogBuilder:
创建控件树,返回根控件:CDialogBuilder::Create
将控件树关联到CPaintManagerUI对象(由名字可猜出其功能与绘制控件有关):CPaintManagerUI::AttachDialog
添加消息通知:CPaintManagerUI::AddNotifier
创建控件树:
读取XML配置文件
CControlUI* CDialogBuilder::Create(STRINGorID xml, LPCTSTR type, IDialogBuilderCallback* pCallback, CPaintManagerUI* pManager, CControlUI* pParent) { if( HIWORD(xml.m_lpstr) != NULL ) { if( *(xml.m_lpstr) == _T('<') ) { if( !m_xml.Load(xml.m_lpstr) ) return NULL; } else { if( !m_xml.LoadFromFile(xml.m_lpstr) ) return NULL; } } else { HRSRC hResource = ::FindResource(CPaintManagerUI::GetResourceDll(), xml.m_lpstr, type); if( hResource == NULL ) return NULL; HGLOBAL hGlobal = ::LoadResource(CPaintManagerUI::GetResourceDll(), hResource); if( hGlobal == NULL ) { FreeResource(hResource); return NULL; } m_pCallback = pCallback; if( !m_xml.LoadFromMem((BYTE*)::LockResource(hGlobal), ::SizeofResource(CPaintManagerUI::GetResourceDll(), hResource) )) return NULL; ::FreeResource(hResource); m_pstrtype = type; } return Create(pCallback, pManager); }
解析Image(图片)、Font(字体)、Default(默认属性)、Windows(窗口相关)项(代码太长,省略了细节)
CControlUI* CDialogBuilder::Create(IDialogBuilderCallback* pCallback, CPaintManagerUI* pManager, CControlUI* pParent) { m_pCallback = pCallback;//回调函数,用于创建自定义控件 CMarkupNode root = m_xml.GetRoot(); if( !root.IsValid() ) return NULL; if( pManager ) { LPCTSTR pstrClass = NULL; int nAttributes = 0; LPCTSTR pstrName = NULL; LPCTSTR pstrValue = NULL; LPTSTR pstr = NULL; for( CMarkupNode node = root.GetChild() ; node.IsValid(); node = node.GetSibling() ) { pstrClass = node.GetName(); if( _tcscmp(pstrClass, _T("Image")) == 0 ) {//Image } else if( _tcscmp(pstrClass, _T("Font")) == 0 ) {//Font } else if( _tcscmp(pstrClass, _T("Default")) == 0 ) {//Default } } pstrClass = root.GetName(); if( _tcscmp(pstrClass, _T("Window")) == 0 ) {//Window } } return _Parse(&root, NULL, pManager); }
创建控件:CDialogBuilder::_Parse
可以通过include嵌套XML文件
。。。。。。 if( _tcscmp(pstrClass, _T("Include")) == 0 ) {//Include if( !node.HasAttributes() ) continue; int count = 1; LPTSTR pstr = NULL; TCHAR szValue[500] = { 0 }; SIZE_T cchLen = lengthof(szValue) - 1; if ( node.GetAttributeValue(_T("count"), szValue, cchLen) ) count = _tcstol(szValue, &pstr, 10); cchLen = lengthof(szValue) - 1; if ( !node.GetAttributeValue(_T("source"), szValue, cchLen) ) continue; for ( int i = 0; i < count; i++ ) { CDialogBuilder builder; if( m_pstrtype != NULL ) { // 使用资源dll,从资源中读取 WORD id = (WORD)_tcstol(szValue, &pstr, 10); pControl = builder.Create((UINT)id, m_pstrtype, m_pCallback, pManager, pParent); } else { pControl = builder.Create((LPCTSTR)szValue, (UINT)0, m_pCallback, pManager, pParent); } } continue; } 。。。。。。
创建控件(自定义控件调用回调函数实现)
。。。。。。 else {//新建控件 SIZE_T cchLen = _tcslen(pstrClass); switch( cchLen ) { case 4: if( _tcscmp(pstrClass, _T("Edit")) == 0 ) pControl = new CEditUI; else if( _tcscmp(pstrClass, _T("List")) == 0 ) pControl = new CListUI; else if( _tcscmp(pstrClass, _T("Text")) == 0 ) pControl = new CTextUI; break; case 5: if( _tcscmp(pstrClass, _T("Combo")) == 0 ) pControl = new CComboUI; else if( _tcscmp(pstrClass, _T("Label")) == 0 ) pControl = new CLabelUI; break; case 6: if( _tcscmp(pstrClass, _T("Button")) == 0 ) pControl = new CButtonUI; else if( _tcscmp(pstrClass, _T("Option")) == 0 ) pControl = new COptionUI; else if( _tcscmp(pstrClass, _T("Slider")) == 0 ) pControl = new CSliderUI; break; case 7: if( _tcscmp(pstrClass, _T("Control")) == 0 ) pControl = new CControlUI; else if( _tcscmp(pstrClass, _T("ActiveX")) == 0 ) pControl = new CActiveXUI; break; case 8: if( _tcscmp(pstrClass, _T("Progress")) == 0 ) pControl = new CProgressUI; else if( _tcscmp(pstrClass, _T("RichEdit")) == 0 ) pControl = new CRichEditUI; break; case 9: if( _tcscmp(pstrClass, _T("Container")) == 0 ) pControl = new CContainerUI; else if( _tcscmp(pstrClass, _T("TabLayout")) == 0 ) pControl = new CTabLayoutUI; else if( _tcscmp(pstrClass, _T("ScrollBar")) == 0 ) pControl = new CScrollBarUI; break; case 10: if( _tcscmp(pstrClass, _T("ListHeader")) == 0 ) pControl = new CListHeaderUI; else if( _tcscmp(pstrClass, _T("TileLayout")) == 0 ) pControl = new CTileLayoutUI; break; case 12: if( _tcscmp(pstrClass, _T("DialogLayout")) == 0 ) pControl = new CDialogLayoutUI; break; case 14: if( _tcscmp(pstrClass, _T("VerticalLayout")) == 0 ) pControl = new CVerticalLayoutUI; else if( _tcscmp(pstrClass, _T("ListHeaderItem")) == 0 ) pControl = new CListHeaderItemUI; break; case 15: if( _tcscmp(pstrClass, _T("ListTextElement")) == 0 ) pControl = new CListTextElementUI; break; case 16: if( _tcscmp(pstrClass, _T("HorizontalLayout")) == 0 ) pControl = new CHorizontalLayoutUI; else if( _tcscmp(pstrClass, _T("ListLabelElement")) == 0 ) pControl = new CListLabelElementUI; break; case 20: if( _tcscmp(pstrClass, _T("ListContainerElement")) == 0 ) pControl = new CListContainerElementUI; break; } // User-supplied control factory if( pControl == NULL && m_pCallback != NULL ) { pControl = m_pCallback->CreateControl(pstrClass); } } 。。。。。。
添加子控件(解析子控件:递归调用_Parse、关联到父控件:CContainerUI::Add)
。。。。。。 // Add children if( node.HasChildren() ) { _Parse(&node, pControl, pManager); } // Attach to parent // 因为某些属性和父窗口相关,比如selected,必须先Add到父窗口 if( pParent != NULL ) { if( pContainer == NULL ) pContainer = static_cast<IContainerUI*>(pParent->GetInterface(_T("IContainer"))); ASSERT(pContainer); if( pContainer == NULL ) return NULL; if( !pContainer->Add(pControl) ) { delete pControl; continue; } } 。。。。。。
返回根控件
。。。。。。 // Return first item if( pReturn == NULL ) pReturn = pControl; 。。。。。。
控件创建基本就这些,下一篇写控件消息。
相关文章推荐
- UITableView总结
- Storyboard里面的几种Segue区别:push,modal,popover,replace和custom(转载)
- UIScrollView
- Quartus II TimeQuest Timing Analyzer 小结
- MSBUID相关(笔记)
- (iPhone/iPad开发)详解UIView的center属性
- minigui 3.0.12在ubuntu12.04下安装
- EFI useful document or link
- 双系统或三系统:Grub Rescue修复方法
- 双系统或三系统:Grub Rescue修复方法
- Android requestWindowFeature()的应用
- UIPopoverController
- DuiLib(一)——窗口及消息
- Confluence安装、汉化及jira整合
- 数位dp简单题目汇总
- Java: Queue 各种方法的细小区别
- IOS开发笔记UIView使用animateWithDuration控制页面效果
- UIScrollView用法
- UI Overview//用户界面概述
- 神奇的Fastcgi_Finish_Request