java directui_DirectUI的优点及其自定义控件的开发

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 CLabelUI

class UILIB_API CButtonUI

class UILIB_API COptionUIclass UILIB_API CTextUIclass UILIB_API CProgressUIclass UILIB_API CSliderUIclass UILIB_API CEditUIclass UILIB_API CScrollBarUIclass 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分离开,但开源版的暂不知是否可以。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值