您当前的位置: 首页 >  ar

插件开发

暂无认证

  • 5浏览

    0关注

    492博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

第一章 第六小节Duilib的WindowImplBase基类OnCreate函数中CDialogBuilder对象_Parse函数--xml文件到子控件树

插件开发 发布时间:2022-03-26 09:25:48 ,浏览量:5

文章目录
    • 1.CDialogBuilder对象中Parse函数
    • 2.作者答疑

1.CDialogBuilder对象中Parse函数

  接着上一部分讲解,已经获取了文件中窗体及默认部分的绘制信息,接着构建子控件树,源代码如下:

CControlUI* CDialogBuilder::_Parse(CMarkupNode* pRoot, CControlUI* pParent, CPaintManagerUI* pManager)
    {
        IContainerUI* pContainer = NULL;
        CControlUI* pReturn = NULL;
        for( CMarkupNode node = pRoot->GetChild() ; node.IsValid(); node = node.GetSibling() ) {
            LPCTSTR pstrClass = node.GetName();
            if( _tcsicmp(pstrClass, _T("Image")) == 0 || _tcsicmp(pstrClass, _T("Font")) == 0 \
                || _tcsicmp(pstrClass, _T("Default")) == 0 || _tcsicmp(pstrClass, _T("Style")) == 0 ) continue;//这部分已经在上一级函数里初始化过

            CControlUI* pControl = NULL;
            if (_tcsicmp(pstrClass, _T("Import")) == 0) continue;
            if( _tcsicmp(pstrClass, _T("Include")) == 0 ) {//包含其它文件,内存的xml代码,生成控件
                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 CreateControl(strClass));

                // 检查插件
                if( pControl == NULL ) {
                    CStdPtrArray* pPlugins = CPaintManagerUI::GetPlugins();
                    LPCREATECONTROL lpCreateControl = NULL;
                    for( int i = 0; i GetSize(); ++i ) {
                        lpCreateControl = (LPCREATECONTROL)pPlugins->GetAt(i);
                        if( lpCreateControl != NULL ) {
                            pControl = lpCreateControl(pstrClass);
                            if( pControl != NULL ) break;
                        }
                    }
                }
                // 回掉创建
                if( pControl == NULL && m_pCallback != NULL ) {
                    pControl = m_pCallback->CreateControl(pstrClass);
                }
            }

            if( pControl == NULL ) {
#ifdef _DEBUG
                DUITRACE(_T("未知控件:%s"), pstrClass);
#else
                continue;
#endif
            }

            // Add children
            if( node.HasChildren() ) {
                _Parse(&node, pControl, pManager);
            }
            // Attach to parent
            // 因为某些属性和父窗口相关,比如selected,必须先Add到父窗口
            CTreeViewUI* pTreeView = NULL;
            if( pParent != NULL && pControl != NULL ) {
                CTreeNodeUI* pParentTreeNode = static_cast(pParent->GetInterface(_T("TreeNode")));
                CTreeNodeUI* pTreeNode = static_cast(pControl->GetInterface(_T("TreeNode")));
                pTreeView = static_cast(pParent->GetInterface(_T("TreeView")));
                // TreeNode子节点
                if(pTreeNode != NULL) {
                    if(pParentTreeNode) {
                        pTreeView = pParentTreeNode->GetTreeView();
                        if(!pParentTreeNode->Add(pTreeNode)) {
                            delete pTreeNode;
                            pTreeNode = NULL;
                            continue;
                        }
                    }
                    else {
                        if(pTreeView != NULL) {
                            if(!pTreeView->Add(pTreeNode)) {
                                delete pTreeNode;
                                pTreeNode = NULL;
                                continue;
                            }
                        }
                    }
                }
                // TreeNode子控件
                else if(pParentTreeNode != NULL) {
                    pParentTreeNode->GetTreeNodeHoriznotal()->Add(pControl);
                }
                // 普通控件
                else {
                    if( pContainer == NULL ) pContainer = static_cast(pParent->GetInterface(_T("IContainer")));
                    ASSERT(pContainer);
                    if( pContainer == NULL ) return NULL;
                    //将控件注册到容器内,并将控件与CPaintManagerUI关联起来
                    //并按名字注册到CPaintManagerUI成员m_mNameHash内。
                    if( !pContainer->Add(pControl) ) {
                        delete pControl;
                        continue;
                    }
                }
            }
            if( pControl == NULL ) continue;

            // 初始化默认属性
            if( pManager ) {
                if(pTreeView != NULL) {
                    pControl->SetManager(pManager, pTreeView, true);
                }
                else {
                    pControl->SetManager(pManager, NULL, false);
                }
                LPCTSTR pDefaultAttributes = pManager->GetDefaultAttributeList(pstrClass);
                if( pDefaultAttributes ) {
                    pControl->ApplyAttributeList(pDefaultAttributes);
                }
            }
            // 加载其它属性
            if( node.HasAttributes() ) {
                TCHAR szValue[500] = { 0 };
                SIZE_T cchLen = lengthof(szValue) - 1;
                // Set ordinary attributes
                int nAttributes = node.GetAttributeCount();
                for( int i = 0; i SetAttribute(node.GetAttributeName(i), node.GetAttributeValue(i));
                }
            }
            if( pManager ) {
                if(pTreeView == NULL) {
                    pControl->SetManager(NULL, NULL, false);
                }
            }
            // 返回第一个控件作为根控件
            if( pReturn == NULL ) pReturn = pControl;
        }
        return pReturn;
    }

  _Parse函数的主要作用是根据xml文件构建ui界面控件树形结构,普通控件直接构建。   【注意】函数返回根控件的指针,再根据根指针往下索引,所以在xml文件Window 标签下第一个容器一定要包含其它子控件和子容器,否则查找函数根据根指针查找会找不到对应的子控件。   另外一方面,其中子控件的构建的方法值得分析下,源码如下:

                CDuiString strClass;
                strClass.Format(_T("C%sUI"), pstrClass);
                pControl = dynamic_cast(CControlFactory::GetInstance()->CreateControl(strClass));

  首先通过静态函数::GetInstance()获取一个构建工厂CControlFactory的实例指针,源代码如下所示:

    CControlFactory* CControlFactory::GetInstance()  
    {
        static CControlFactory* pInstance = new CControlFactory;
        return pInstance;
    }
   	//自定义函数
    CControlFactory::CControlFactory()
    {
        INNER_REGISTER_DUICONTROL(CControlUI);
        INNER_REGISTER_DUICONTROL(CContainerUI);
        INNER_REGISTER_DUICONTROL(CButtonUI);
        INNER_REGISTER_DUICONTROL(CComboUI);
        INNER_REGISTER_DUICONTROL(CComboBoxUI);
        INNER_REGISTER_DUICONTROL(CDateTimeUI);
        INNER_REGISTER_DUICONTROL(CEditUI);
        INNER_REGISTER_DUICONTROL(CActiveXUI);
        INNER_REGISTER_DUICONTROL(CFlashUI);
        INNER_REGISTER_DUICONTROL(CGifAnimUI);
#ifdef USE_XIMAGE_EFFECT
        INNER_REGISTER_DUICONTROL(CGifAnimExUI);
#endif
        INNER_REGISTER_DUICONTROL(CGroupBoxUI);
        INNER_REGISTER_DUICONTROL(CIPAddressUI);
        INNER_REGISTER_DUICONTROL(CIPAddressExUI);
        INNER_REGISTER_DUICONTROL(CLabelUI);
        INNER_REGISTER_DUICONTROL(CListUI);
        INNER_REGISTER_DUICONTROL(CListHeaderUI);
        INNER_REGISTER_DUICONTROL(CListHeaderItemUI);
        INNER_REGISTER_DUICONTROL(CListLabelElementUI);
        INNER_REGISTER_DUICONTROL(CListTextElementUI);
        INNER_REGISTER_DUICONTROL(CListContainerElementUI);
        INNER_REGISTER_DUICONTROL(CMenuUI);
        INNER_REGISTER_DUICONTROL(CMenuElementUI);
        INNER_REGISTER_DUICONTROL(COptionUI);
        INNER_REGISTER_DUICONTROL(CCheckBoxUI);
        INNER_REGISTER_DUICONTROL(CProgressUI);
        INNER_REGISTER_DUICONTROL(CRichEditUI);
        INNER_REGISTER_DUICONTROL(CScrollBarUI);
        INNER_REGISTER_DUICONTROL(CSliderUI);
        INNER_REGISTER_DUICONTROL(CTextUI);
        INNER_REGISTER_DUICONTROL(CTreeNodeUI);
        INNER_REGISTER_DUICONTROL(CTreeViewUI);
        INNER_REGISTER_DUICONTROL(CWebBrowserUI);
        INNER_REGISTER_DUICONTROL(CAnimationTabLayoutUI);
        INNER_REGISTER_DUICONTROL(CChildLayoutUI);
        INNER_REGISTER_DUICONTROL(CHorizontalLayoutUI);
        INNER_REGISTER_DUICONTROL(CTabLayoutUI);
        INNER_REGISTER_DUICONTROL(CTileLayoutUI);
        INNER_REGISTER_DUICONTROL(CVerticalLayoutUI);
        INNER_REGISTER_DUICONTROL(CRollTextUI);
        INNER_REGISTER_DUICONTROL(CColorPaletteUI);
        INNER_REGISTER_DUICONTROL(CListExUI);
        INNER_REGISTER_DUICONTROL(CListContainerHeaderItemUI);
        INNER_REGISTER_DUICONTROL(CListTextExtElementUI);
        INNER_REGISTER_DUICONTROL(CHotKeyUI);
        INNER_REGISTER_DUICONTROL(CFadeButtonUI);
        INNER_REGISTER_DUICONTROL(CRingUI);
    }
    
//在常用控件中加上一个在内存中的静态构建函数
#define DECLARE_DUICONTROL(class_name)\
public:\
    static CControlUI* CreateControl();

#define IMPLEMENT_DUICONTROL(class_name)\
    CControlUI* class_name::CreateControl()\
    { return new class_name; }

#define REGIST_DUICONTROL(class_name)\
    CControlFactory::GetInstance()->RegistControl(_T(#class_name), (CreateClass)class_name::CreateControl);

#define INNER_REGISTER_DUICONTROL(class_name)\
    RegistControl(_T(#class_name), (CreateClass)class_name::CreateControl);

	//注册函数
    void CControlFactory::RegistControl(CDuiString strClassName, CreateClass pFunc)
    {
        strClassName.MakeLower();
        m_mapControl.insert(MAP_DUI_CTRATECLASS::value_type(strClassName, pFunc));
    }

  在每一个子控件中,都添加了如此的构建函数,组成这样一个构建工厂,当外部提供类名动态构建时,调用对应的静态构建函数,动态创建对应的子控件对象,代码如下所示:

 typedef CControlUI* (*CreateClass)();
 typedef std::map MAP_DUI_CTRATECLASS;
 
 CControlUI* CControlFactory::CreateControl(CDuiString strClassName)
    {
        strClassName.MakeLower();
        MAP_DUI_CTRATECLASS::iterator iter = m_mapControl.find(strClassName);
        if ( iter == m_mapControl.end()) {
            return NULL;
        }
        else {
            return (CControlUI*) (iter->second());//val作为函数调用。
        }
    }

  到此,根据xml文件创建子控件树,并返回根节点指针介绍完毕!下一小节回到窗口初始化函数部分。

2.作者答疑

  如有疑问,请留言。

关注
打赏
1665481431
查看更多评论
立即登录/注册

微信扫码登录

0.0558s