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 。。。。。。

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

  • 相关阅读:
    超级管理员登录后如果连续XX分钟没有操作再次操作需要重新登录
    linux下连接本地的navicate
    linux 日常中会用到的命令(持续更新)
    关于PHP的 PHP-FPM进程CPU 100%的一些原因分析和解决方案
    VMware Workstation 14 激活码
    破解phpstorm
    redis五种数据类型的使用场景
    关于Nginx负载均衡的6种策略
    PHP和PHP-FPM 配置文件优化
    redis配置文件详解
  • 原文地址:https://www.cnblogs.com/dahai/p/3455865.html
Copyright © 2011-2022 走看看