duilib list控件扩展

对于简单的list控件已经有前辈分析了自带demo的ListRes全过程,duilib DirectUI库里面的一个简单的例子ListDemo

他分析了listdemo的来龙去脉,这里我只是将个人理解的list分析一下。

由于自带的listdemo不能满足要求,所以必须个人扩展list,通过尝试 发现

1. 列表头禁止拖动情况

这种情况很简单, 配置xml的时候将 表头宽度 和 元素宽度设置相同就行了,listheader布局如下:

[html]  view plain copy
  1. <List name="domainlist" bkcolor="#FFFFFFFF" inset="0,0,0,0" itemshowhtml="true" vscrollbar="true" hscrollbar="true" headerbkimage="file='list_header_bg.png'" itemalign="center" itembkcolor="#FFE2DDDF" itemaltbk="true" hscrollbar="false" menu="true">  
  2.     <ListHeader height="24" menu="true">  
  3.         <ListHeaderItem text="No" font="1" width="130" hotimage="file='list_header_hot.png'" pushedimage="file='list_header_pushed.png'" sepimage="file='list_header_sep.png'" sepwidth="1"/>  
  4.         <ListHeaderItem text="Domain" font="1" width="160" hotimage="file='list_header_hot.png'" pushedimage="file='list_header_pushed.png'" sepimage="file='list_header_sep.png'" sepwidth="1"/>  
  5.         <ListHeaderItem text="Description" font="1" width="140" hotimage="file='list_header_hot.png'" pushedimage="file='list_header_pushed.png'" sepimage="file='list_header_sep.png'" sepwidth="1"/>  
  6.     </ListHeader>  
  7. </List>  

上面是listdemo自带的xml,只是将listheaderitem宽度修改了

下面是listelement布局:

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  
  2. <Window>  
  3.     <HorizontalLayout width="266" height="60" bkcolor="#FFD2D2D2" >  
  4.         <HorizontalLayout width="130" height="60" bordersize="1" bordercolor="#FF00FF00">  
  5.             <HorizontalLayout />  
  6.             <VerticalLayout width="32">  
  7.                 <HorizontalLayout />  
  8.                 <Label name="listmem1" text="111" align="center" float="false" bkcolor="#FFFFFFFF" pos="22,0,0,0" width="32" height="18" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" />  
  9.                 <HorizontalLayout />  
  10.             </VerticalLayout>   
  11.             <HorizontalLayout />  
  12.         </HorizontalLayout>  
  13.         <VerticalLayout width="160" height="60" bordersize="1" bordercolor="#FF00FF00">  
  14.             <Label name="listmem2" text="222" align="center" float="true" bkcolor="#FFFFFFFF" pos="17,7,0,0" width="51" height="15" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" />  
  15.         </VerticalLayout>  
  16.         <VerticalLayout width="140" height="60" bordersize="1" bordercolor="#FF00FF00">  
  17.             <Edit name="listmem3" text="333" float="true" pos="10,7,0,0" width="61" height="15" bkcolor="#FFFFFFFF" textpadding="4,3,4,3" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" />  
  18.             <Button float="true" pos="18,29,0,0" width="72" height="24" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="file='offline_down.png' source='0,0,72,24'" hotimage="file='offline_down.png' source='0,24,72,48'" pushedimage="file='offline_down.png' source='0,48,76,72'" />  
  19.         </VerticalLayout>  
  20.     </HorizontalLayout>  
  21. </Window>  

使用的时候添加代码如下:

我是直接修改listdemo的,

屏蔽原有的OnSearch函数,添加下面代码即可:

[cpp]  view plain copy
  1. CDialogBuilder builder;  
  2. CVerticalLayoutUI *plist_element = static_cast<CVerticalLayoutUI*>( builder.Create( _T("listmem1.xml") , 0 , NULL , &m_pm , NULL ) );  
  3. CListUI *plist = static_cast< CListUI* >( m_pm.FindControl("domainlist") );  
  4. if ( !plist )  
  5. {  
  6.     return ;  
  7. }  
  8. plist->Add(plist_element);  

最后启动程序,得到下面的界面



2.列表头可拖动情况

如果直接使用CListContainerElementUI就会出现下面排版了。


可以看到位置完全打乱了,通过源码可以查到位置布局使用的函数是

[cpp]  view plain copy
  1. void SetPos(RECT rc);  

CListContainerElementUI里面并没有这个函数,那就是调用了CContainerUI的SetPos函数

CContainerUI的SetPos函数

[cpp]  view plain copy
  1. void CContainerUI::SetPos(RECT rc)  
  2. {  
  3.     CControlUI::SetPos(rc);  
  4.     if( m_items.IsEmpty() ) return;  
  5.     rc.left += m_rcInset.left;  
  6.     rc.top += m_rcInset.top;  
  7.     rc.right -= m_rcInset.right;  
  8.     rc.bottom -= m_rcInset.bottom;  
  9.   
  10.     forint it = 0; it < m_items.GetSize(); it++ ) {  
  11.         CControlUI* pControl = static_cast<CControlUI*>(m_items[it]);  
  12.         if( !pControl->IsVisible() ) continue;  
  13.         if( pControl->IsFloat() ) {  
  14.             SetFloatPos(it);  
  15.         }  
  16.         else {  
  17.             pControl->SetPos(rc); // 所有非float子控件放大到整个客户区  
  18.         }  
  19.     }  
  20. }  

直接将得到的rc设置给子控件了,也就是说,ListContainerElement每一列的宽度都是一样的,第二列 被 第三列 覆盖了 ,第一列一直居中。

这里说明一下,duilib 控件位置布局是由父控件设置的,父控件只管自己的子控件。如下图所示


Root只管理下一层的Root1和Root2,其余的和他不相干。

Root1管理Root3和Root4,Root2管理Root5和Root6.

这里的父节点都是IContainerUI控件或者继承于IContainerUI控件的类,叶子节点一般都是CControlUI类或者继承于CControlUI的类。


所以我们需要在ListContainerElement添加SetPos函数

[cpp]  view plain copy
  1. void CListContainerElementUI::SetPos(RECT rc)  
  2. {  
  3.     CControlUI::SetPos(rc);  
  4.     rc = m_rcItem;  
  5.   
  6.     // Adjust for inset  
  7.     rc.left += m_rcInset.left;  
  8.     rc.top += m_rcInset.top;  
  9.     rc.right -= m_rcInset.right;  
  10.     rc.bottom -= m_rcInset.bottom;  
  11.   
  12.     TListInfoUI *plistinfo = GetOwner()->GetListInfo();  
  13.   
  14.     // Determine the width of elements that are sizeable  
  15.     SIZE szAvailable = { rc.right - rc.left, rc.bottom - rc.top };  
  16.   
  17.     forint it2 = 0; it2 < m_items.GetSize(); it2++ )  
  18.     {  
  19.         CControlUI* pControl = static_cast<CControlUI*>(m_items[it2]);  
  20.         if( !pControl->IsVisible() )   
  21.             continue;  
  22.         if( pControl->IsFloat() )   
  23.         {  
  24.             SetFloatPos(it2);  
  25.             continue;  
  26.         }  
  27.         RECT rcPadding = pControl->GetPadding();  
  28.         SIZE sz = pControl->EstimateSize(szAvailable);  
  29.         if( sz.cx == 0 )   
  30.         {  
  31.             if( sz.cx < pControl->GetMinWidth() )   
  32.                 sz.cx = pControl->GetMinWidth();  
  33.             if( sz.cx > pControl->GetMaxWidth() )   
  34.                 sz.cx = pControl->GetMaxWidth();  
  35.         }  
  36.         else   
  37.         {  
  38.             if( sz.cx < pControl->GetMinWidth() )   
  39.                 sz.cx = pControl->GetMinWidth();  
  40.             if( sz.cx > pControl->GetMaxWidth() )  
  41.                 sz.cx = pControl->GetMaxWidth();  
  42.         }  
  43.   
  44.         sz.cy = pControl->GetFixedHeight();  
  45.         if( sz.cy == 0 )   
  46.             sz.cy = rc.bottom - rc.top - rcPadding.top - rcPadding.bottom;  
  47.         if( sz.cy < 0 )   
  48.             sz.cy = 0;  
  49.         if( sz.cy < pControl->GetMinHeight() )   
  50.             sz.cy = pControl->GetMinHeight();  
  51.         if( sz.cy > pControl->GetMaxHeight() )   
  52.             sz.cy = pControl->GetMaxHeight();  
  53.   
  54.   
  55.         RECT rcCtrl = { plistinfo->rcColumn[it2].left + rcPadding.left,  
  56.             rc.top + rcPadding.top,  
  57.             plistinfo->rcColumn[it2].right + rcPadding.left,   
  58.             rc.top + sz.cy + rcPadding.top + rcPadding.bottom };  
  59.         pControl->SetPos(rcCtrl);  
  60.     }  
  61. }  


这里面代码主要来自于CHorizontalLayoutUI,删除了个人认为不需要的代码,当然本人接触这东西才一个月,也有可能多删除了一些东西。

重新写OnSearch函数

[cpp]  view plain copy
  1. CDialogBuilder builder;  
  2. CListContainerElementUI *plist_element = static_cast<CListContainerElementUI*>( builder.Create( _T("listmem.xml") , 0 , NULL , &m_pm , NULL ) );  
  3. if ( !plist_element )  
  4. {  
  5.     return ;  
  6. }  
  7.   
  8. if ( !plist )  
  9. {  
  10.     return ;  
  11. }  
  12. plist->Add(plist_element);  

现在可以看到拖动效果了

直接上图吧,原始图



拖动图




转载自http://blog.csdn.net/midle110/article/details/39118201
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值