博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
DirectUI的优点及其自定义控件的开发
阅读量:6277 次
发布时间:2019-06-22

本文共 9108 字,大约阅读时间需要 30 分钟。

   DirectUI是一款占用资源小、绘图性能高、依赖性小的纯Win32 SDK开发的Windows下普遍适用的可视化界面库。与标准控件换肤类界面库不同的是,DirectUI本身具备了标准控件换肤的功能,但其更强调用户自定义界面的开发,提供可扩展的多种布局控件、几十套可扩展的功能强大的界面控件。它可以构建任何一种类型的2D界面框架。DirectUI吸取了游戏绘图引擎的精髓,并在其基础上创造了脏区域局部更新机制,多核CPU多线程渲染,充分提高了界面库的运行效率,与常见的游戏引擎相比,占用极低的CPU时间。目前支持GDI、DirectX、OpenGL等绘图引擎。

  其身影无处不在,MSN、QQ、迅雷、360、网游等等应用案例均是。其具有以下优点:

  1、高速绘图引擎,具有较好的性能、极小的内存开销,而且无句柄、无“消息”(事件)

  2、无第三方的最小依赖,界面与逻辑彻底分离,且逻辑支持javascript/lua

  4、主流界面换肤方式,且皮肤方案可以放在压缩包中

  5、不同分辨率、窗口大小下的自适布局(控件)的支持

  注1:传统win32/mfc并没有好的布局工具及相应的属性,创建控件实例时必须一旦其位置、大小(CreateWindow/CreateWindowEx),而一旦窗口大小,分辨率改变之后,无法自适,得自己处理。

  注2:DirecitUI采用XML描述布局,较传统win32/mfc代码方式更为现代化和便利,用“贴图”点缀应用也因此更加容易。

  注3:用过.net/java,会感觉到DirectUI有事件的味道,而c++的消息似乎被包起来了。

  DirectUI源于微软的MSN应用,因优秀而很快风靡起来,其商业项目非常成熟但不免费,而开源版的也有不补的,需要根据自身需求进行完善和补充。网上搜索了一下如何其为创建自定义控件,但没有找到,好在自己解决了,方法如下:

  UICommonControls.cpp(.h)中包含了八个公共控件类:  

class UILIB_API CLabelUIclass UILIB_API CButtonUI class UILIB_API COptionUI class UILIB_API CTextUI class UILIB_API CProgressUI class UILIB_API CSliderUI class UILIB_API CEditUI class UILIB_API CScrollBarUI class UILIB_API CCustomerUI
  第一步,照着任何一个类创建一个类似的控件类即可,类名不可重复,上面名为CCustomerUI的控件类是我们创建的,直接继承于DirectUI控件的基类CControlUI。
  第二步,打开UIDlgBuilder.cpp,关注下面代码“case 8”中的代码:
CControlUI* CDialogBuilder::_Parse(CMarkupNode* pRoot, CControlUI* pParent, CPaintManagerUI* pManager){    CDialogLayoutUI* pDialogLayout = NULL;    IContainerUI* pContainer = NULL;    CControlUI* pReturn = NULL;    for( CMarkupNode node = pRoot->GetChild() ; node.IsValid(); node = node.GetSibling() ) {        LPCTSTR pstrClass = node.GetName();        if( _tcscmp(pstrClass, _T("Image")) == 0 || _tcscmp(pstrClass, _T("Font")) == 0 \            || _tcscmp(pstrClass, _T("Default")) == 0 ) continue;        CControlUI* pControl = NULL;        if( _tcscmp(pstrClass, _T("Include")) == 0 ) {            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;				else if( _tcscmp(pstrClass, _T("Customer")) == 0 ) pControl = new CCustomerUI;                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);            }        }        ASSERT(pControl);        if( pControl == NULL ) continue;        // Add children        if( node.HasChildren() ) {            _Parse(&node, pControl, pManager);        }        // Attach to parent        // 因为某些属性和父窗口相关,比如selected,必须先Add到父窗口        if( pParent != NULL ) {            if( pContainer == NULL ) pContainer = static_cast
(pParent->GetInterface(_T("IContainer"))); ASSERT(pContainer); if( pContainer == NULL ) return NULL; if( !pContainer->Add(pControl) ) { delete pControl; continue; } } // Init default attributes if( pManager ) { pControl->SetManager(pManager, NULL, false); LPCTSTR pDefaultAttributes = pManager->GetDefaultAttributeList(pstrClass); if( pDefaultAttributes ) { pControl->ApplyAttributeList(pDefaultAttributes); } } // Process attributes 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 < nAttributes; i++ ) { pControl->SetAttribute(node.GetAttributeName(i), node.GetAttributeValue(i)); } // Very custom attributes if ( node.GetAttributeValue(_T("stretch"), szValue, cchLen) ) { if( pParent == NULL ) continue; if( pDialogLayout == NULL ) pDialogLayout = static_cast
(pParent->GetInterface(_T("DialogLayout"))); ASSERT(pDialogLayout); if( pDialogLayout == NULL ) continue; UINT uMode = 0; if( _tcsstr(szValue, _T("move_x")) != NULL ) uMode |= UISTRETCH_MOVE_X; if( _tcsstr(szValue, _T("move_y")) != NULL ) uMode |= UISTRETCH_MOVE_Y; if( _tcsstr(szValue, _T("move_xy")) != NULL ) uMode |= UISTRETCH_MOVE_X | UISTRETCH_MOVE_Y; if( _tcsstr(szValue, _T("size_x")) != NULL ) uMode |= UISTRETCH_SIZE_X; if( _tcsstr(szValue, _T("size_y")) != NULL ) uMode |= UISTRETCH_SIZE_Y; if( _tcsstr(szValue, _T("size_xy")) != NULL ) uMode |= UISTRETCH_SIZE_X | UISTRETCH_SIZE_Y; if( _tcsstr(szValue, _T("group")) != NULL ) uMode |= UISTRETCH_NEWGROUP; if( _tcsstr(szValue, _T("line")) != NULL ) uMode |= UISTRETCH_NEWLINE; pDialogLayout->SetStretchMode(pControl, uMode); } } if( pManager ) { pControl->SetManager(NULL, NULL, false); } // Return first item if( pReturn == NULL ) pReturn = pControl; } return pReturn;}

  Customer的长度为8,所以上面case 后面的号是8,关键地方为if( _tcscmp(pstrClass, _T("Customer")) == 0 ) pControl = new CCustomerUI;

  自定义控件具体的内容,根据实际需求去写即可。此外,据我所知,商业版的DirectUI的自定义控件是可以做成插件的,即与DirectUI SDK分离开,但开源版的暂不知是否可以。

 

转载地址:http://zkfva.baihongyu.com/

你可能感兴趣的文章
JAVA IO BIO NIO AIO
查看>>
input checkbox 复选框大小修改
查看>>
网吧维护工具
查看>>
BOOT.INI文件参数
查看>>
vmstat详解
查看>>
新年第一镖
查看>>
unbtu使用笔记
查看>>
OEA 中 WPF 树型表格虚拟化设计方案
查看>>
Android程序开发初级教程(一) 开始 Hello Android
查看>>
使用Gradle打RPM包
查看>>
“我意识到”的意义
查看>>
淘宝天猫上新辅助工具-新品填表
查看>>
再学 GDI+[43]: 文本输出 - 获取已安装的字体列表
查看>>
nginx反向代理
查看>>
操作系统真实的虚拟内存是什么样的(一)
查看>>
hadoop、hbase、zookeeper集群搭建
查看>>
python中一切皆对象------类的基础(五)
查看>>
modprobe
查看>>
android中用ExpandableListView实现三级扩展列表
查看>>
%Error opening tftp://255.255.255.255/cisconet.cfg
查看>>