zoukankan      html  css  js  c++  java
  • DuiLib(二)——控件创建

    上一篇讲了窗口及消息,了解了大体的程序框架。这一篇说的是控件的创建。

    duilib支持XML配置文件,即根据XML创建窗口及控件,将界面与逻辑分开,便于修改及维护。上一篇的示例中可以看到在消息WM_CREATE中有控件创建的相关代码。

     1 if( uMsg == WM_CREATE ) {
     2             m_pm.Init(m_hWnd);
     3             //根据XML创建控件
     4             CDialogBuilder builder;
     5             CControlUI* pRoot = builder.Create(_T("HelloWorld.xml"), (UINT)0, NULL, &m_pm);
     6             ASSERT(pRoot && "Failed to parse XML");
     7             m_pm.AttachDialog(pRoot);
     8             m_pm.AddNotifier(this);
     9             return 0;
    10         }

    控件创建主要牵扯到类CDialogBuilder:

    • 创建控件树,返回根控件:CDialogBuilder::Create
    • 将控件树关联到CPaintManagerUI对象(由名字可猜出其功能与绘制控件有关):CPaintManagerUI::AttachDialog
    • 添加消息通知:CPaintManagerUI::AddNotifier

    创建控件树:

    • 读取XML配置文件
       1 CControlUI* CDialogBuilder::Create(STRINGorID xml, LPCTSTR type, IDialogBuilderCallback* pCallback, 
       2                                    CPaintManagerUI* pManager, CControlUI* pParent)
       3 {
       4     if( HIWORD(xml.m_lpstr) != NULL ) {
       5         if( *(xml.m_lpstr) == _T('<') ) {
       6             if( !m_xml.Load(xml.m_lpstr) ) return NULL;
       7         }
       8         else {
       9             if( !m_xml.LoadFromFile(xml.m_lpstr) ) return NULL;
      10         }
      11     }
      12     else {
      13         HRSRC hResource = ::FindResource(CPaintManagerUI::GetResourceDll(), xml.m_lpstr, type);
      14         if( hResource == NULL ) return NULL;
      15         HGLOBAL hGlobal = ::LoadResource(CPaintManagerUI::GetResourceDll(), hResource);
      16         if( hGlobal == NULL ) {
      17             FreeResource(hResource);
      18             return NULL;
      19         }
      20 
      21         m_pCallback = pCallback;
      22         if( !m_xml.LoadFromMem((BYTE*)::LockResource(hGlobal), ::SizeofResource(CPaintManagerUI::GetResourceDll(), hResource) )) return NULL;
      23         ::FreeResource(hResource);
      24         m_pstrtype = type;
      25     }
      26 
      27     return Create(pCallback, pManager);
      28 }
    • 解析Image(图片)、Font(字体)、Default(默认属性)、Windows(窗口相关)项(代码太长,省略了细节)
       1 CControlUI* CDialogBuilder::Create(IDialogBuilderCallback* pCallback, CPaintManagerUI* pManager, CControlUI* pParent)
       2 {
       3     m_pCallback = pCallback;//回调函数,用于创建自定义控件
       4     CMarkupNode root = m_xml.GetRoot();
       5     if( !root.IsValid() ) return NULL;
       6 
       7     if( pManager ) {
       8         LPCTSTR pstrClass = NULL;
       9         int nAttributes = 0;
      10         LPCTSTR pstrName = NULL;
      11         LPCTSTR pstrValue = NULL;
      12         LPTSTR pstr = NULL;
      13         for( CMarkupNode node = root.GetChild() ; node.IsValid(); node = node.GetSibling() ) {
      14             pstrClass = node.GetName();
      15             if( _tcscmp(pstrClass, _T("Image")) == 0 ) {//Image
      16             }
      17             else if( _tcscmp(pstrClass, _T("Font")) == 0 ) {//Font
      18             }
      19             else if( _tcscmp(pstrClass, _T("Default")) == 0 ) {//Default
      20             }
      21         }
      22 
      23         pstrClass = root.GetName();
      24         if( _tcscmp(pstrClass, _T("Window")) == 0 ) {//Window
      25         }
      26     }
      27     return _Parse(&root, NULL, pManager);
      28 }
    • 创建控件:CDialogBuilder::_Parse
      • 可以通过include嵌套XML文件
         1 。。。。。。
         2 if( _tcscmp(pstrClass, _T("Include")) == 0 ) {//Include
         3             if( !node.HasAttributes() ) continue;
         4             int count = 1;
         5             LPTSTR pstr = NULL;
         6             TCHAR szValue[500] = { 0 };
         7             SIZE_T cchLen = lengthof(szValue) - 1;
         8             if ( node.GetAttributeValue(_T("count"), szValue, cchLen) )
         9                 count = _tcstol(szValue, &pstr, 10);
        10             cchLen = lengthof(szValue) - 1;
        11             if ( !node.GetAttributeValue(_T("source"), szValue, cchLen) ) continue;
        12             for ( int i = 0; i < count; i++ ) {
        13                 CDialogBuilder builder;
        14                 if( m_pstrtype != NULL ) { // 使用资源dll,从资源中读取
        15                     WORD id = (WORD)_tcstol(szValue, &pstr, 10); 
        16                     pControl = builder.Create((UINT)id, m_pstrtype, m_pCallback, pManager, pParent);
        17                 }
        18                 else {
        19                     pControl = builder.Create((LPCTSTR)szValue, (UINT)0, m_pCallback, pManager, pParent);
        20                 }
        21             }
        22             continue;
        23         }
        24 。。。。。。
      • 创建控件(自定义控件调用回调函数实现)
        。。。。。。
        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)
         1 。。。。。。
         2 // Add children
         3         if( node.HasChildren() ) {
         4             _Parse(&node, pControl, pManager);
         5         }
         6         // Attach to parent
         7         // 因为某些属性和父窗口相关,比如selected,必须先Add到父窗口
         8         if( pParent != NULL ) {
         9             if( pContainer == NULL ) pContainer = static_cast<IContainerUI*>(pParent->GetInterface(_T("IContainer")));
        10             ASSERT(pContainer);
        11             if( pContainer == NULL ) return NULL;
        12             if( !pContainer->Add(pControl) ) {
        13                 delete pControl;
        14                 continue;
        15             }
        16         }
        17 。。。。。。
      • 返回根控件
      • 1 。。。。。。
        2 // Return first item
        3         if( pReturn == NULL ) pReturn = pControl;
        4 。。。。。。

     控件创建基本就这些,下一篇写控件消息。

  • 相关阅读:
    赫尔维茨公式
    从解析几何的角度分析二次型
    Struts 1 Struts 2
    记一次服务器被入侵的调查取证
    契约式设计 契约式编程 Design by contract
    lsblk df
    Linux Find Out Last System Reboot Time and Date Command 登录安全 开关机 记录 帐号审计 历史记录命令条数
    Infrastructure for container projects.
    更新文档 版本控制 多版本并发控制
    Building Microservices: Using an API Gateway
  • 原文地址:https://www.cnblogs.com/dahai/p/3455865.html
Copyright © 2011-2022 走看看