duilib 之 List控件
List控件是我们常用到的控件,也是应用很广泛。
对LIST控件添加元素有两种方法,一种是直接在XML中写死元素,另一种是动态创建。另外,LIST的应用也分为两种,一种需要表头,另一种是不需要表头。对应带表头的LIST,还会分为可拖动表头,和不可拖动表头,以下将会一一举例说明。
先看在XML中添加元素,格式如下:
<List name="list_data" float="true" pos="0,10,0,0" width="615" height="280" header="hidden" itemlinecolor="FFB8BDC6" vscrollbar="true" bkcolor="#FFE6ECF7" > <ListContainerElement name="menu_Open" height="22" inset="40,0,0,0"> <Label text="打开" mouse="false"/> </ListContainerElement> <ListContainerElement name="menu_Mark" height="22" inset="40,0,0,0"> <Label text="标注" mouse="false"/> </ListContainerElement> <ListContainerElement name="menu_Delete" height="22" inset="40,0,0,0"> <Label text="删除" mouse="false"/> </ListContainerElement> </List>
这样就插入了三行到List中。
对于动态添加元素,只需要动态创建元素,然后插入到LIST中,对应的XML如下:
<List name="list_data" float="true" pos="0,10,0,0" width="615" height="280" header="hidden" itemlinecolor="FFB8BDC6" vscrollbar="true" bkcolor="#FFE6ECF7" > </List>
对应的元素XML如下,可在XML中添加任意控件,就能在LIST显示所添加的控件:
<?xml version="1.0" encoding="UTF-8"?> <Window size="1820,701" caption="0,0,0,701"> <ListContainerElement name="display_camera_preset_item" height="38" minheight="38"> <HorizontalLayout> <Control width="20"/> <Label name="number_lab" width="50" text="136" textcolor="FF6B6B6B" /> <VerticalLayout > <HorizontalLayout /> <Label name="name_lab" width="156" text="test" align="left" textpadding="10,4,0,0" textcolor="#FF000000" disabledtextcolor="#FF808080" /> <HorizontalLayout /> </VerticalLayout> </HorizontalLayout> </ListContainerElement> </Window>
在初始化函数中,添加如下代码:
CDialogBuilder builder; if(!builder.GetMarkup()->IsValid()) pEle = static_cast<CListContainerElementUI *>(builder.Create(_T("list_item.xml"),(UINT)0,this,&m_PaintManager)); else pEle = static_cast<CListContainerElementUI*>(builder.Create(this,&m_PaintManager)); pEle->SetMinHeight(60); CLabelUI *pLab = static_cast<CLabelUI *>(pEle->FindSubControl(_T("number_lab"))); pLab->SetText(_T("11")); pLab = static_cast<CLabelUI *>(pEle->FindSubControl(_T("name_lab"))); pLab->SetText(_T("ko")); CListUI *pList = static_cast<CListUI*>(m_PaintManager.FindControl(_T("list_data"))); if(NULL == pList) return; pList->Add(pEle);
添加完成后,就插入元素到LIST中。
对应带表头的XML,先说说可拖动的表头,默认情况下,表头是可以拖动的,XML如下:
<List name="list_data" bkcolor="#FFFFFFFF" inset="0,0,0,0" bordersize="1" bordercolor="#FFD7D7D7" itemshowhtml="true" vscrollbar="true" hscrollbar="true" itemalign="left" itemaltbk="true" itemshowrowline="true" itemshowcolumnline="true" itemlinecolor="#FFD7D7D7"> <ListHeader height="40" bkcolor="#FFE6ECF7" bordersize="1" bordercolor="#FFD7D7D7"> <ListHeaderItem text="序号" name="es_header_name_dbclick" width="350" align="left" textpadding="15,0,0,0" /> <Control width="1" bkcolor="#FFD7D7D7"/> <ListHeaderItem text="名称" name="es_header_username_dbclick" width="350" align="left" textpadding="15,0,0,0" /> <Control width="1" bkcolor="#FFD7D7D7"/> </ListHeader> </List>
此时创建出来的表头是可以拖动的,如果不需拖动,需在ListHeaderItem中加入属性dragable="false",这样,表头就不能拖动。
对应的元素XML如下:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <Window size="1740,900" > <ListContainerElement height="40" > <!--序号--> <VerticalLayout width="109" height="40" > <Label name="number_lab" textpadding="15,0,0,0" font="6" valign="center" height="40" textcolor="#FF5E5E5E" disabledtextcolor="#FFA7A6AA" /> </VerticalLayout> <Control width="1" bkcolor="#FFCACACA"/> <!--名称--> <VerticalLayout width="149" height="40" > <Label name="name_lab" textpadding="15,0,0,0" font="6" valign="center" height="40" textcolor="#FF5E5E5E" disabledtextcolor="#FFA7A6AA" /> </VerticalLayout> </ListContainerElement> </Window>
如是,我们动态创建元素,插入LIST中。但是我们发现,插入后元素布局发生了变化,而且拖延表头时,元素不跟着拖动。此时,遇到这种情况,我们需要在ListContainerElement中重写SetPos,并添加如下代码:
# if 1 void CListContainerElementUI::SetPos( RECT rc, bool bNeedInvalidate /*= true*/ ) { __super::SetPos(rc,bNeedInvalidate); #if 1 if(GetOwner()->GetListInfo()->nColumns > 0) { 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); } } #endif } #endif
到此,我们就制作出了带表头,可拖动的LIST。,效果如下图:
PS:多说一句,制作出了带表头的LIST,那我们如何响应表头消息勒?其实很简单,修改CListHeaderItemUI中的DoEvent函数,在响应UIEVENT_BUTTONDOWN或UIEVENT_DBLCLICK事件时候,将响应消息SendNotify出来就行!