duilib进阶教程 -- 改进List控件 (1)
Duilib确实很强大,而且源码开放,有些不满足的需求,可以通过阅读源码,Debug跟代码,来改进,废话不过说,开看看要改那些东西。前情提要:Duilib源码中的ListDemo,给我们提供了一个可以左右拖拉headerItem,下面的listitem也跟着变化。但实际工作中,往往HeaderItem和listitem都比较复杂,不可能只是一个text。这就要求他是个容器,可以放option,
Duilib确实很强大,而且源码开放,有些不满足的需求,可以通过阅读源码,Debug跟代码,来改进,废话不过说,开看看要改那些东西。
前情提要:Duilib源码中的ListDemo,给我们提供了一个可以左右拖拉headerItem,下面的listitem也跟着变化。但实际工作中,往往HeaderItem和listitem都比较复杂,不可能只是一个text。这就要求他是个容器,可以放option,button,image等。
类似这样的效果:
1 首先改进CListHeaderItemUI
原来CListHeaderItemUI继承的事CControlUI,让他改成继承CContainerUI就好了,另外需要重写void SetPos(RECT rc);否则其子控件的有效作用范围给headerItem的大小,拖拉的触发事件失效。
void SetPos(RECT rc); 参考void CHorizontalLayoutUI::SetPos(RECT rc) 拷贝过来就可以了。
另外xml中的写法有变化
<ListHeader height="30" menu="true">
<ListHeaderItem text="" font="1" width="60" hotimage="file='list_bg.png' source='1,0,2,58'" pushedimage="file='list_header_pushed.png'" sepimage="file='list_header_sepline.png'" sepwidth="5">
<Option float="true" pos="5,0,0,0" width="50" height="30" name="OptionOfListApplication" normalimage="file='checkbox.png' dest='23,8,37,22' source='0,0,14,14'" hotimage="file='checkbox.png' dest='23,8,37,22' source='14,0,28,14'" pushedimage="file='checkbox.png' dest='23,8,37,22' source='28,0,42,14'" disabledimage="file='checkbox.png' dest='23,8,37,22' source='42,0,56,14'" hottextcolor="#FF007AFF" selectedforeimage="file='check.png' dest='23,8,37,22'"/>
</ListHeaderItem>
<ListHeaderItem text="Domain" font="1" width="260" hotimage="file='list_bg.png' source='1,0,2,58'" pushedimage="file='list_header_pushed.png'" sepimage="file='list_header_sepline.png'" sepwidth="1">
</ListHeaderItem>
<ListHeaderItem text="Description" font="1" width="240" hotimage="file='list_bg.png' source='1,0,2,58'" pushedimage="file='list_header_pushed.png'" sepimage="file='list_header_sepline.png'" sepwidth="1">
</ListHeaderItem>
</ListHeader>
注意Option 要设置 float="true" pos="5,0,0,0" 两个属性
2 改进CListContainerElementUI
虽然他是个容器,但他对headeritem的拖拉无响应,不能随之改变。
源码中void CListContainerElementUI::DrawItemText(HDC hDC, const RECT& rcItem) 这个方法直接return了。需要实现。
void CListContainerElementUI::DrawItemText(HDC hDC, const RECT& rcItem)
{
if( m_pOwner == NULL ) return;
TListInfoUI* pInfo = m_pOwner->GetListInfo();
DWORD iTextColor = pInfo->dwTextColor;
if( (m_uButtonState & UISTATE_HOT) != 0 ) {
iTextColor = pInfo->dwHotTextColor;
}
if( IsSelected() ) {
iTextColor = pInfo->dwSelectedTextColor;
}
if( !IsEnabled() ) {
iTextColor = pInfo->dwDisabledTextColor;
}
for( int i = 0; i < pInfo->nColumns; i++ )
{
RECT rcItem = { pInfo->rcColumn[i].left, m_rcItem.top, pInfo->rcColumn[i].right, m_rcItem.bottom };
rcItem.left += pInfo->rcTextPadding.left;
rcItem.right -= pInfo->rcTextPadding.right;
rcItem.top += pInfo->rcTextPadding.top;
rcItem.bottom -= pInfo->rcTextPadding.bottom;
CControlUI* pControl = GetItemAt(i);
pControl->SetPos(rcItem);
}
}
而且需要在DoPaint中调用
void CListContainerElementUI::DoPaint(HDC hDC, const RECT& rcPaint)
{
if( !::IntersectRect(&m_rcPaint, &rcPaint, &m_rcItem) ) return;
DrawItemText(hDC, m_rcItem);
DrawItemBk(hDC, m_rcItem);
CContainerUI::DoPaint(hDC, rcPaint);
}
另外xml的写法有所改变,不能像以前那样随便写了,CListContainerElementUI下面的一级子控件为每一列的容器,也可以不是容器,但如果此列包含多个控件,就必须是个容器,可参考如下写法:
<ListContainerElement height="58">
<HorizontalLayout float="true" pos="0,0,60,58">
<Option float="true" pos="5,0,0,0" width="50" height="30" name="OptionOfListApplication" normalimage="file='checkbox.png' dest='23,8,37,22' source='0,0,14,14'" hotimage="file='checkbox.png' dest='23,8,37,22' source='14,0,28,14'" pushedimage="file='checkbox.png' dest='23,8,37,22' source='28,0,42,14'" disabledimage="file='checkbox.png' dest='23,8,37,22' source='42,0,56,14'" hottextcolor="#FF007AFF" selectedforeimage="file='check.png' dest='23,8,37,22'"/>
</HorizontalLayout>
<Label float="true" pos="60,0,320,58" name="docsize" text="2222" align="center" textcolor="#FF333333" width="260"/>
<Label float="true" pos="320,0,560,58" name="appversion" text="3333" align="center" textcolor="#FF333333" />
</ListContainerElement>
至此大功告成!佩服一下自己,呵呵!
更多推荐
所有评论(0)