duilib list控制元件擴充套件
阿新 • • 發佈:2019-01-22
他分析了listdemo的來龍去脈,這裡我只是將個人理解的list分析一下。
由於自帶的listdemo不能滿足要求,所以必須個人擴充套件list,通過嘗試 發現
1. 列表頭禁止拖動情況
這種情況很簡單, 配置xml的時候將 表頭寬度 和 元素寬度設定相同就行了,listheader佈局如下:
<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"> <ListHeader height="24" menu="true"> <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"/> <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"/> <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"/> </ListHeader> </List>
上面是listdemo自帶的xml,只是將listheaderitem寬度修改了
下面是listelement佈局:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <Window> <HorizontalLayout width="266" height="60" bkcolor="#FFD2D2D2" > <HorizontalLayout width="130" height="60" bordersize="1" bordercolor="#FF00FF00"> <HorizontalLayout /> <VerticalLayout width="32"> <HorizontalLayout /> <Label name="listmem1" text="111" align="center" float="false" bkcolor="#FFFFFFFF" pos="22,0,0,0" width="32" height="18" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" /> <HorizontalLayout /> </VerticalLayout> <HorizontalLayout /> </HorizontalLayout> <VerticalLayout width="160" height="60" bordersize="1" bordercolor="#FF00FF00"> <Label name="listmem2" text="222" align="center" float="true" bkcolor="#FFFFFFFF" pos="17,7,0,0" width="51" height="15" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" /> </VerticalLayout> <VerticalLayout width="140" height="60" bordersize="1" bordercolor="#FF00FF00"> <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" /> <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'" /> </VerticalLayout> </HorizontalLayout> </Window>
使用的時候新增程式碼如下:
我是直接修改listdemo的,
遮蔽原有的OnSearch函式,新增下面程式碼即可:
CDialogBuilder builder; CVerticalLayoutUI *plist_element = static_cast<CVerticalLayoutUI*>( builder.Create( _T("listmem1.xml") , 0 , NULL , &m_pm , NULL ) ); CListUI *plist = static_cast< CListUI* >( m_pm.FindControl("domainlist") ); if ( !plist ) { return ; } plist->Add(plist_element);
最後啟動程式,得到下面的介面
2.列表頭可拖動情況
如果直接使用CListContainerElementUI就會出現下面排版了。
可以看到位置完全打亂了,通過原始碼可以查到位置佈局使用的函式是
void SetPos(RECT rc);
CListContainerElementUI裡面並沒有這個函式,那就是呼叫了CContainerUI的SetPos函式
CContainerUI的SetPos函式
void CContainerUI::SetPos(RECT rc)
{
CControlUI::SetPos(rc);
if( m_items.IsEmpty() ) return;
rc.left += m_rcInset.left;
rc.top += m_rcInset.top;
rc.right -= m_rcInset.right;
rc.bottom -= m_rcInset.bottom;
for( int it = 0; it < m_items.GetSize(); it++ ) {
CControlUI* pControl = static_cast<CControlUI*>(m_items[it]);
if( !pControl->IsVisible() ) continue;
if( pControl->IsFloat() ) {
SetFloatPos(it);
}
else {
pControl->SetPos(rc); // 所有非float子控制元件放大到整個客戶區
}
}
}
直接將得到的rc設定給子控制元件了,也就是說,ListContainerElement每一列的寬度都是一樣的,第二列 被 第三列 覆蓋了 ,第一列一直居中。
這裡說明一下,duilib 控制元件位置佈局是由父控制元件設定的,父控制元件只管自己的子控制元件。如下圖所示
Root只管理下一層的Root1和Root2,其餘的和他不相干。
Root1管理Root3和Root4,Root2管理Root5和Root6.
這裡的父節點都是IContainerUI控制元件或者繼承於IContainerUI控制元件的類,葉子節點一般都是CControlUI類或者繼承於CControlUI的類。
所以我們需要在ListContainerElement新增SetPos函式
void CListContainerElementUI::SetPos(RECT rc)
{
CControlUI::SetPos(rc);
rc = m_rcItem;
// Adjust for inset
rc.left += m_rcInset.left;
rc.top += m_rcInset.top;
rc.right -= m_rcInset.right;
rc.bottom -= m_rcInset.bottom;
TListInfoUI *plistinfo = GetOwner()->GetListInfo();
// Determine the width of elements that are sizeable
SIZE szAvailable = { rc.right - rc.left, rc.bottom - rc.top };
for( int it2 = 0; it2 < m_items.GetSize(); it2++ )
{
CControlUI* pControl = static_cast<CControlUI*>(m_items[it2]);
if( !pControl->IsVisible() )
continue;
if( pControl->IsFloat() )
{
SetFloatPos(it2);
continue;
}
RECT rcPadding = pControl->GetPadding();
SIZE sz = pControl->EstimateSize(szAvailable);
if( sz.cx == 0 )
{
if( sz.cx < pControl->GetMinWidth() )
sz.cx = pControl->GetMinWidth();
if( sz.cx > pControl->GetMaxWidth() )
sz.cx = pControl->GetMaxWidth();
}
else
{
if( sz.cx < pControl->GetMinWidth() )
sz.cx = pControl->GetMinWidth();
if( sz.cx > pControl->GetMaxWidth() )
sz.cx = pControl->GetMaxWidth();
}
sz.cy = pControl->GetFixedHeight();
if( sz.cy == 0 )
sz.cy = rc.bottom - rc.top - rcPadding.top - rcPadding.bottom;
if( sz.cy < 0 )
sz.cy = 0;
if( sz.cy < pControl->GetMinHeight() )
sz.cy = pControl->GetMinHeight();
if( sz.cy > pControl->GetMaxHeight() )
sz.cy = pControl->GetMaxHeight();
RECT rcCtrl = { plistinfo->rcColumn[it2].left + rcPadding.left,
rc.top + rcPadding.top,
plistinfo->rcColumn[it2].right + rcPadding.left,
rc.top + sz.cy + rcPadding.top + rcPadding.bottom };
pControl->SetPos(rcCtrl);
}
}
這裡面程式碼主要來自於CHorizontalLayoutUI,刪除了個人認為不需要的程式碼,當然本人接觸這東西才一個月,也有可能多刪除了一些東西。
重新寫OnSearch函式
CDialogBuilder builder;
CListContainerElementUI *plist_element = static_cast<CListContainerElementUI*>( builder.Create( _T("listmem.xml") , 0 , NULL , &m_pm , NULL ) );
if ( !plist_element )
{
return ;
}
if ( !plist )
{
return ;
}
plist->Add(plist_element);
現在可以看到拖動效果了
直接上圖吧,原始圖
拖動圖