关于duilib中的list的扩展探索

前端之家收集整理的这篇文章主要介绍了关于duilib中的list的扩展探索前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

原文地址:http://www.jb51.cc/article/p-zkotooxi-gt.html


今天在做一个程序的界面时,需要在一个列表中显示文字以外的其他控件,如:EditButtonCombo等;我做界面使用的是duilib,其自带CListUI并不能满足此项功能,需要进行扩展,在此记录,以便后续使用需要。

先看一下实现的效果

今天我们的扩展主要包含如下部分:

1.表头支持控件

在ListUI中,表头是CListHeaderItemUI,而这个类是从CControlUI继承而来,为了能支持在其中显示其他控件,它需要是一个窗口,那么需要将其父类改成CContainerUI,调整基类后,需要同时将CListHeaderItemUI类中引用CControlUI的地方全部改成CContainerUI,如:

  1. LPVOIDCListHeaderItemUI::GetInterface(LPCTSTRpstrName)
  2. {
  3. if(_tcscmp(pstrName,DUI_CTR_LISTHEADERITEM)==0)returnthis;
  4. returnCContainerUI::GetInterface(pstrName);
  5. }

如果此处不改,将无法从XML文件中加载内嵌控件。

还需要修改其他如DoEvent事件中的CControlUI,否则会导致表头无法拖拉,切记。

改造后,我们可以从XML文件加载了,XML文件可以这样写:

[html]
    <@H_403_146@Listname="listex"bkcolor="#FFFFFFFF"inset="0,0"itemshowhtml="true"vscrollbar="true"hscrollbar="true"headerbkimage="file='list_header_bg.png'"itemhotimage="file='tree_hot.bmp'corner='2,1,2,1'"itemselectedimage="file='tree_select.bmp'corner='2,1'"itemalign="center"itembkcolor="#FFE2DDDF"itemaltbk="true"hscrollbar="false"menu="true">
  1. ListHeaderheight="24"menu="true">
  2. ListHeaderItemtext=""inset="1,0"minwidth="60"endellipsis="true"font="1"width="95"normalimage="headerctrl_normal.bmp"hotimage="headerctrl_hot.bmp"pushedimage="headerctrl_down.bmp"sepimage="Headerctrl_Sperator.bmp"sepwidth="2"VerticalLayoutinset="1,5,0"CheckBoxname="selall"endellipsis="true"text="全选"textcolor="#FF386382"hottextcolor="#FF386382"selectedtextcolor="#FF386382"disabledtextcolor="#FFbac0c5"textpadding="20,3,0"align="left"selectedimage="file='checkBox_p.png'dest='0,15,17'"normalimage="file='checkBox_h.png'dest='0,17'"/>
  3. </@H_403_146@VerticalLayoutListHeaderItemListHeaderItemtext="域名"minwidth="100"endellipsis="true"font="1"width="200"normalimage="headerctrl_normal.bmp"hotimage="headerctrl_hot.bmp"pushedimage="headerctrl_down.bmp"sepimage="Headerctrl_Sperator.bmp"sepwidth="2"/>
  4. ListHeaderItemtext="描述"minwidth="120"endellipsis="true"font="1"width="150"normalimage="headerctrl_normal.bmp"hotimage="headerctrl_hot.bmp"pushedimage="headerctrl_down.bmp"sepimage="Headerctrl_Sperator.bmp"sepwidth="2"ListHeader>


这样显示出来的效果如下:

注意:

此处需要将内嵌控件的ListHeaderItem添加一个inset属性,控制内嵌的控件不要铺满整个ListHeaderItem,否则表头拖动不了,如:

ListHeaderItemtext=""inset="1,0"

2.列表项支持控件

CListUI的某一行CListContainerElementUI继承至容器CContainerUI,这样一来我们只需要将需要的控件添加到此容器中,即可正确的显示相关的控件了,此处并不需要做调整,只是这样一来会带来一个问题,那就是所添加的列的宽度无法与表头的宽度保持一致。

解决这个问题,需要给CListContainerElementUI添加SetPos函数,在此函数中,重新校正数据列宽与表头宽度一致,具体如下:

    voidSetPos(RECTrc)
  1. CContainerUI::SetPos(rc);
  2. if(m_pOwner==NULL)return;
  3. if(m_pHeader==NULL)
  4. return;
  5. }
  6. TListInfoUI*pInfo=m_pOwner->GetListInfo();
  7. intnCount=m_items.GetSize();
  8. for(inti=0;i<nCount;i++)
  9. CControlUI*pHorizontalLayout=static_cast<CControlUI*>(m_items[i]);
  10. //if(pHorizontalLayout!=NULL)
  11. //{
  12. //RECTrtHeader=pHeaderItem->GetPos();
  13. //RECTrt=pHorizontalLayout->GetPos();
  14. //rt.left=pInfo->rcColumn[i].left;
  15. //rt.right=pInfo->rcColumn[i].right;
  16. //pHorizontalLayout->SetPos(rt);
  17. //}
  18. CListHeaderItemUI*pHeaderItem=static_cast<CListHeaderItemUI*>(m_pHeader->GetItemAt(i));
  19. if(pHorizontalLayout!=NULL&&pHeaderItem!=NULL)
  20. {
  21. RECTrtHeader=pHeaderItem->GetPos();
  22. RECTrt=pHorizontalLayout->GetPos();
  23. rt.left=rtHeader.left;
  24. rt.right=rtHeader.right;
  25. pHorizontalLayout->SetPos(rt);
  26. }
  27. CListHeaderUI*m_pHeader;

此处往列表项中添加了表头的指针,需要在插入一行的时候,将表头的指针传递进来,用于在SetPos的时候获取表头宽度。

注意以上代码中的注释部分,原本打算从TListInfoUI的rcColumn中获取表头项宽度的,但发现新添加行时,rcCulumn中的值全是0,需要在插入行前主动调用一次CListUI::SetPos(GetPos());才能正常,使用起来较麻烦,且容易忘记;即使是添加上了,测试发现获取到的位置有一定的偏移,所以采用将Header传入,实时获取了。

以下是一行数据的XML文件描述:

    <?@H_403_146@xmlversion="1.0"encoding="UTF-8"?>
  1. WindowListContainerElementCheckBoxname="selectme"endellipsis="true"text="亲,选我吧!"textcolor="#FF386382"hottextcolor="#FF386382"selectedtextcolor="#FF386382"disabledtextcolor="#FFbac0c5"textpadding="20,0); background-color:inherit; font-weight:bold">HorizontalLayoutinset="4,4,4"Edittext="测试文本"bordersize="1"height="20"bordercolor="#FF4775CC"name="domain">EditHorizontalLayoutHorizontalLayoutButtontext="按钮1"width="50"pushedimage="button_down.bmp"hotimage="button_over.bmp"normalimage="button_nor.bmp"name="ttt"ButtonButtontext="按钮2"width="50"pushedimage="button_down.bmp"hotimage="button_over.bmp"normalimage="button_nor.bmp"name="ttt"Labeltext="这是从XML文件中加载的列表项"LabelListContainerElement>
注意,此处需要确保 ListContainerElement 的子控件个数不少于列表的列数

代码中加载此XML文件,将行数据添加到列表中:

    CListUIEx*pList=static_cast<CListUIEx*>(m_PaintManager.FindControl(_T("listex")));
  1. CDialogBuilderbuilder;
  2. CListContainerElementUI*pLine=(CListContainerElementUI*)(builder.Create(_T("sigle_list_item_column.xml"),(UINT)0,this));
  3. if(pLine!=NULL)
  4. pList->InsertItem(0,60,pLine);//此函数是经过二次封装的
  5. }
加载的效果如下:

这样我们可以在列表的不同项中显示任意内容,甚至是一个完整的窗口了。

3.通过代码动态添加列及列表项

以上的处理均是调整后从XML加载相应的加载已经配置好的列表进行显示,在完成上述工作后,我这边进一步封装了几个函数,以便于动态的添加[指定内嵌控件]、动态的插入行以及动态的在某一行列中添加控件。

1).以下代码用于动态的添加列:

    BOOLCListUIEx::InsertColumn(
  1. intnCol,
  2. CListHeaderItemUI*pHeaderItem
  3. )
  4. CListHeaderUI*pHeader=CListUI::GetHeader();
  5. if(pHeader==NULL)
  6. returnFALSE;
  7. if(pHeader->AddAt(pHeaderItem,nCol))
  8. returnTRUE;
  9. deletepHeaderItem;
  10. pHeaderItem=NULL;
  11. returnFALSE;
  12. BOOLCListUIEx::SetHeaderItemData(intnColumn,CControlUI*pControl)
  13. CListHeaderUI*pHeader=CListUI::GetHeader();
  14. if(pHeader==NULL)
  15. CListHeaderItemUI*pHeaderItem=(CListHeaderItemUI*)pHeader->GetItemAt(nColumn);
  16. pHeaderItem->Add(pControl);
  17. }
调用代码如下 [ 添加一列,并且向此列中嵌入一个 CheckBox]

    CListHeaderItemUI*pHeaderItem=newCListHeaderItemUI;
  1. pHeaderItem->SetTextStyle(DT_RIGHT|DT_VCENTER|DT_SINGLELINE);
  2. pHeaderItem->SetText("新增列");
  3. pHeaderItem->SetAttribute(_T("sepimage"),_T("Headerctrl_Sperator.bmp"));
  4. pHeaderItem->SetAttribute(_T("sepwidth"),_T("1"));
  5. pHeaderItem->SetAttribute(_T("pushedimage"),_T("headerctrl_down.bmp"));
  6. pHeaderItem->SetAttribute(_T("hotimage"),_T("headerctrl_hot.bmp"));
  7. pHeaderItem->SetAttribute(_T("normalimage"),_T("headerctrl_normal.bmp"));
  8. pHeaderItem->SetFixedWidth(150);
  9. pList->InsertColumn(3,pHeaderItem);
  10. CCheckBoxUI*pBtnUI=newCCheckBoxUI;
  11. pBtnUI->SetText("选择");
  12. pBtnUI->SetAttribute(_T("selectedimage"),_T("file='checkBox_p.png'dest='0,17'"));
  13. pBtnUI->SetAttribute(_T("normalimage"),_T("file='checkBox_h.png'dest='0,17'"));
  14. pBtnUI->SetAttribute(_T("textpadding"),_T("20,0"));
  15. pBtnUI->SetAttribute(_T("align"),_T("right"));
  16. pBtnUI->SetFloat(true);
  17. pBtnUI->SetAttribute("pos","20,65,20");
  18. pList->SetHeaderItemData(3,pBtnUI);
2). 以下代码用于动态的添加行,动态的指定一列的内容

    intCListUIEx::InsertItem(intnItem,intnHeight)
  1. CListContainerElementUIEx*pListItem=newCListContainerElementUIEx;
  2. pListItem->SetFixedHeight(nHeight);/*固定一个行高*/
  3. pListItem->SetList(this);
  4. if(NULL!=pHeader)
  5. intnHeaderCount=pHeader->GetCount();
  6. inti=0;i<nHeaderCount;i++)
  7. pListItem->InsertColumn(i);
  8. if(!CListUI::AddAt(pListItem,nItem))
  9. deletepListItem;
  10. pListItem=NULL;
  11. return-1;
  12. returnnItem;
  13. voidCListUIEx::SetItemData(LPCTSTRText,87); background-color:inherit; font-weight:bold">LPCTSTRName)
  14. //存放文本
  15. CHorizontalLayoutUI*pSubHor=GetListSubItem(nItem,nColumn);
  16. CLabelUI*pLabel=newCLabelUI;
  17. pLabel->SetText(Text);//控件属性就根据需求设置吧,我简单设置一下
  18. pLabel->SetTextStyle(DT_CENTER);
  19. pLabel->SetAttribute("endellipsis","true");
  20. pSubHor->SetAttribute("inset","3,1");
  21. pLabel->SetName(Name);
  22. pSubHor->Add(pLabel);//添加到父控件
  23. pSubHor->Add(pControl);//添加到父控件
  24. }

通过如下代码添加一行数据:

    intnIndex=pList->GetCount();
  1. pList->InsertItem(nIndex);
  2. CEditUI*pControl=newCEditUI;
  3. pControl->SetText("");
  4. pControl->SetName("edit");
  5. pControl->SetBorderColor(RGB(255,0));
  6. pControl->SetAttribute("bordersize","1");
  7. pControl->SetAttribute("bordercolor","#FF4775CC");
  8. pList->SetItemData(nIndex,pControl);
  9. CButtonUI*pBtnUI=newCButtonUI;
  10. pBtnUI->SetText("添加");
  11. pBtnUI->SetFixedWidth(60);
  12. pBtnUI->SetAttribute(_T("pushedimage"),_T("button_down.bmp"));
  13. pBtnUI->SetAttribute(_T("hotimage"),_T("button_over.bmp"));
  14. pBtnUI->SetAttribute(_T("normalimage"),_T("button_nor.bmp"));
  15. "这是一行动态添加的数据","testid");
  16. if(pList->GetHeader()->GetCount()>3)
  17. pList->SetItemData(nIndex,"新增列数据","testid1");
  18. }

至此,ListUI的扩展就告一段落了,目前已经完全满足了的使用需求,相信也能满足绝大部分其他人的需求了,测试程序的完整效果图如下:

测试程序代码下载地址:http://download.csdn.net/detail/tragicguy/7087559

后记:

扩展此控件,参考了文章http://www.jb51.cc/article/p-nwcssmsk-ua.html

此份测试代码改自 群友【朗】的ListExtension.

同时特别感谢群友tojen的帮助!

duilib功能确实很强大,给我这种UI小白带来了希望,希望有越来越多的高级控件能纳入的基础源码库中,方便大众;也希望其他扩展过duilib功能的大侠,放出代码来,造福众人。

猜你在找的XML相关文章