MFC总结之CListCtrl用法及技巧Word文档格式.docx
- 文档编号:17812265
- 上传时间:2022-12-10
- 格式:DOCX
- 页数:22
- 大小:65.14KB
MFC总结之CListCtrl用法及技巧Word文档格式.docx
《MFC总结之CListCtrl用法及技巧Word文档格式.docx》由会员分享,可在线阅读,更多相关《MFC总结之CListCtrl用法及技巧Word文档格式.docx(22页珍藏版)》请在冰豆网上搜索。
插入列时,可指明列号、列名称、列名称显示样式,列宽等信息。
对于列号为0的那一列,始终是靠左显示,后面会有修改使其剧中显示的方法,其他列通过设置nFormat属性可以居中显示。
插入行:
intInsertItem(intnItem,LPCTSTRlpszItem)
直接插入一行,nItem指明行号,lpszItem指明该行第0列的信息。
设置信息:
BOOLSetItemText(intnItem,intnSubItem,LPCTSTRlpszText)设置第nItem行nSubItem列的信息(nItem:
0,1,2,3……;
nSubItem:
1,2,3……)
删除操作
有三个操作函数:
BOOLDeleteAllItems()-------删除所有的行
BOOLDeleteItem(nItem)--------删除某一行
BOOLDeleteColumn(nCol)-----删除某一列
获取/设置属性函数
有很多函数了,就不一一介绍了。
常用的有
intGetItemCount()--------获取已插入信息的行数
BOOLSetItemState(intiLink,UINTstate,UINTstateMask)---------设置行状态,如高亮显示等
等等
2、获取选中行的行号
获取选中行的行号,然后对该行进行相关处理,这点在编程中用的非常多。
当鼠标单击item时,控件向父窗口发送NM_CLICK消息,其响应函数为OnNMClickXXXX(NMHDR*pNMHDR,LRESULT*pResult),在该函数下来编写代码获取鼠标点击的行号。
有两种方法来获取行号:
第一种是使用GetFirstSelectedItemPosition和GetNextSelectedItem配合来获取;
第二种是先获取鼠标位置信息,然后调用HitTest函数来找出行号。
示例分别如下:
第一种方法,该示例截自MSDN,可作修改后使用。
1.POSITIONpos=pList->
GetFirstSelectedItemPosition();
2.if(pos==NULL)
3.TRACE0("
Noitemswereselected!
\n"
);
4.else
5.{
6.while(pos)
7.{
8.intnItem=pList->
GetNextSelectedItem(pos);
9.TRACE1("
Item%dwasselected!
nItem);
10.//youcoulddoyourownprocessingonnItemhere
11.}
12.}
第二种方法,该示例来自我的项目,可作修改后使用。
1.//获取单击所在的行号
2.//找出鼠标位置
3.DWORDdwPos=GetMessagePos();
4.CPointpoint(LOWORD(dwPos),HIWORD(dwPos));
5.m_listCtrl.ScreenToClient(&
point);
6.
7.//定义结构体
8.LVHITTESTINFOlvinfo;
9.lvinfo.pt=point;
10.
11.//获取行号信息
12.intnItem=m_listCtrl.HitTest(&
lvinfo);
13.if(nItem!
=-1)
14.m_itemSel=lvinfo.iItem;
//当前行号
对于LVHITTESTINFO结构体,其有四个成员,在上述HitTest调用中,其第一个成员
作为输入,另外三个作为输出。
具体变量含义可查看MSDN。
1.typedefstruct_LVHITTESTINFO{
2.POINTpt;
3.UINTflags;
4.intiItem;
5.intiSubItem;
6.}LVHITTESTINFO,*LPLVHITTESTINFO;
3、复选框操作
有时需要在item前面添加一个CheckBox,供用户选择,然后对所有选中项进行处理。
这里涉及到两个问题:
第一个,如何添加CheckBox风格;
第二个,如何判断某一行的
CheckBox状态是否发生改变。
对于第一个问题,在基本操作里已经有所阐述了,即通过SetExtendedStyle函数添加
LVS_EX_CHECKBOXES扩展风格。
这里重点探讨第二个问题,首先,操作复选框状态的有两个函数:
BOOLGetCheck(intnItem)-------获取复选框状态
BOOLSetCheck(intnItem,BOOLfCheck=TRUE)-------设置复选框状态
其次,我们要搞清楚以下四点:
当列表的项item改变时,控件会向父窗口发送LVN_ITEMCHANGED消息,因此可以在LVN_ITEMCHANGED消息的响应函数中对复选框的状态进行处理(查询或设置)。
?
鼠标点击CheckBox时,消息的顺序是NM_CLICK—>
LVN_ITEMCHANGED,即CheckBox的状态是在NM_CLICK消息函数结束后才会发生变化,在NM_CLICK中使用GetCheck无效。
鼠标点击Item(非CheckBox区域)时,消息的顺序是LVN_ITEMCHANGED—>
NM_CLICK。
调用InsertItem函数时,也会产生LVN_ITEMCHANGED消息。
鉴于此,通常会自定义一个BOOL型变量m_bHit来判断是点击操作还是插入操作,该变量初始赋FALSE,当有鼠标点击item时赋TRUE,检测完是否有CheckBox被点击后重新复位为FALSE。
示例如下所示:
1.voidCXXXX:
:
OnNMClickXXXX(NMHDR*pNMHDR,LRESULT*pResult)
2.{
3.//获取单击所在的行号
4.//找出鼠标位置
5.DWORDdwPos=GetMessagePos();
6.CPointpoint(LOWORD(dwPos),HIWORD(dwPos));
7.m_listCtrl.ScreenToClient(&
8.//定义结构体
9.LVHITTESTINFOlvinfo;
10.lvinfo.pt=point;
15.
16.//判断是否点击在CheckBox上
17.if(lvinfo.flags==LVHT_ONITEMSTATEICON)
18.m_bHit=TRUE;
19.
20.*pResult=0;
21.}
22.
23.voidCXXXX:
OnLvnItemchangedXXXX(NMHDR*pNMHDR,LRESULT*pResult)
24.{
25.LPNMLISTVIEWpNMLV=reinterpret_cast<
LPNMLISTVIEW>
(pNMHDR);
26.//判断m_bHit,即是否点击了CheckBox
27.if(m_bHit)
28.{
29.m_bHit=FALSE;
//复位
30.
31.if(m_listCtrl.GetCheck(m_itemSel))
32.{//CheckBox被选中
33.//doyourownprocessing
34.}
35.else
36.{//CheckBox取消选择
37.//doyourownprocessing
38.}
39.}
40.
41.*pResult=0;
42.}
4、动态设置选中行的字体颜色
有时可能需要设置某行的文字为特殊颜色,以表示某种特殊含义,比如正在下载的信息用绿色,暂停下载的用灰色。
首先,给出一个CodeProject的链接,这篇文章讲的非常好,主要是利用CustomDraw。
Custom-Dra
然后,来谈谈我的方法,这里主要谈对选中行的字体颜色进行动态修改,当然也是我通过上面文章和自己实践结合得出的。
我们需要搞清楚以下几点(可以结合下面修改某一行的字体颜色的方法来看):
当控件绘制时,会发送NM_CUSTOMDRAW消息,该消息的消息响应函数为
OnNMCustomdrawXXXX(NMHDR*pNMHDR,LRESULT*pResult)
3.LPNMLVCUSTOMDRAWpLVCD=reinterpret_cast<
LPNMLVCUSTOMDRAW>
4.//TODO:
Addyourcontrolnotificationhandlercodehere
5.*pResult=CDRF_DODEFAULT;
6.//………………
7.}
其中,pNMHDR为输入参数,其指向NMLVCUSTOMDRAW结构体,该结构包含了很多信息,包括字体颜色、背景等等,特别是第一个成员,为NMCUSTOMDRAW结构体变量,其包含了Currentdrawingstage(不知道怎么编译比较好),其可能的值如下图(截自MSDN)所示
pResult为输出参数,该参数决定了接下来向windows发送什么消息(与绘制有关的),通过发送该消息我们可以进入下一步需要的处理阶段。
具体输出哪个值取决于Currentdrawingstage,其可能的值如下图(截自MSDN)所示
有一点必须注意(英文的,我觉得看起来比翻译过来更精确):
Onethingtokeepinmindisyoumustalwayscheckthedrawstagebefore
doinganythingelse,becauseyourhandlerwillreceivemanymessages,andthe
drawstagedetermineswhatactionyourcodetakes.
下面我们来看看如何修改某一行的字体颜色:
首先,我们应该明白要修改字体颜色,应该在pre-paint阶段来完成?
因此,在消息响应函数中,我们首先判断是否处于pre-paintstage(即pLVCD->
nmcd.dwDrawStage==CDDS_PREPAINT),然后通过修改输出值pResult的值来通知windows我们需要处理每个item的消息(即设置*pResult=CDRF_NOTIFYITEMDRAW)。
再次进入消息响应函数时,我们判断是否处于Item的pre-paintstage(即pLVCD->
nmcd.dwDrawStage==CDDS_ITEMPREPAINT),如果是则进行相关处理,即修改字体颜色等等。
处理完了后重新设置*pResult=CDRF_DODEFAULT,表示我们不再需要其他特殊的消息了,默认执行即可。
示例如下:
4.*pResult=CDRF_DODEFAULT;
5.
6.//Firstthing-checkthedrawstage.Ifit'
sthecontrol'
spre-paints
tage,
7.//thentellWindowswewantmessagesforeveryitem.
8.if(CDDS_PREPAINT==pLVCD->
nmcd.dwDrawStage)
9.{
10.*pResult=CDRF_NOTIFYITEMDRAW;
12.elseif(CDDS_ITEMPREPAINT==pLVCD->
13.{
14.//Thisisthenotificationmessageforanitem.
15.//处理,将item改变背景颜色
16.if(/*符合条件*/)
17.pLVCD->
clrText=RGB(255,0,255);
18.
19.*pResult=CDRF_DODEFAULT;
20.}
上面谈的方法主要用于设置静态字体颜色,当然,如果你的列表的信息在不断变化(即用SetItemText不断修改),那么也就实现了动态改变了,否则需要在合适的地方调用重绘函数:
BOOLRedrawItems(intnFirst,intnLast)
表示在nFirst和nLast之间的行需要进行重绘。
5、设置选中行的背景颜色
设置选中行的背景颜色,可以将选中行以特殊颜色显示,容易明白当前处理的是哪一行。
尽管有高亮,但是高亮是基于焦点的,如果你选中了某一行,然后焦点转移了,这是就无法判断你选的是哪一行了。
设置选中行的背景颜色的方法和第四节中讲的修改字体颜色的方法是相似的,都是利用CustomDraw。
这里涉及到设置当前选中行为特殊颜色,同时要恢复前一次选中行的颜色,否则就乱了。
因此需要记录前一次选中行、当前选中行的行号,相信通过前面的总结,这点并不难实现。
然后在当前选中行和前一次选中行之间进行重绘即可。
3.//…………
4.
5.//重绘item,更改背景颜色
6.intnFirst=min(m_itemSel,m_itemForeSel);
7.intnLast=max(m_itemSel,m_itemForeSel);
8.m_listCtrl.RedrawItems(nFirst,nLast);
//在前一次选中的item和当前选中的
Item之间进行重绘
9.
10.*pResult=0;
12.voidCXXXX:
OnNMCustomdrawXXXX(NMHDR*pNMHDR,LRESULT*pResult)13.{
14.LPNMLVCUSTOMDRAWpLVCD=reinterpret_cast<
15.*pResult=CDRF_DODEFAULT;
16.
17.//Firstthing-checkthedrawstage.Ifit'
sprepaint
18.//stage,thentellWindowswewantmessagesforeveryitem.19.if(CDDS_PREPAINT==pLVCD->
nmcd.dwDrawStage)20.{
21.*pResult=CDRF_NOTIFYITEMDRAW;
22.}
23.elseif(CDDS_ITEMPREPAINT==pLVCD->
nmcd.dwDrawStage)24.{
25.//Thisisthenotificationmessageforanitem.26.//处理,将item改变背景颜色
27.if(m_itemSel==pLVCD->
nmcd.dwItemSpec)28.{//当前选中的item
29.pLVCD->
clrTextBk=RGB(255,0,0);
30.}
31.elseif(m_itemForeSel==pLVCD->
nmcd.dwItemSpec)32.{//前一次选中的item,恢复为白色
33.pLVCD->
clrTextBk=RGB(255,255,255);
35.
36.*pResult=CDRF_DODEFAULT;
37.}
MFC总结之CListCtrl用法及技巧
(二).
续第一篇:
(一)
本篇重点介绍:
禁止拖动表头、让第一列居中显示、设置行高与字体、虚拟列表技术、点击表头时进行归类、向上与向下移动、动态调整大小问题、避免闪烁问题。
6、禁止拖动表头
重载OnNotify消息响应函数,屏蔽两个消息通知码:
HDN_BEGINTRACKW和HDN_DIVIDERDBLCLICKW。
1.BOOLCXXXX:
OnNotify(WPARAMwParam,LPARAMlParam,LRESULT*pResult)
3.//TODO:
Addyourspecializedcodehereand/orcallthebaseclass
4.//屏蔽两个消息通知码,使得禁止拖动List表头
5.NMHEADER*pNMHeader=(NMHEADER*)lParam;
6.if(((pNMHeader->
hdr.code==HDN_BEGINTRACKW)|
7.(pNMHeader->
hdr.code==HDN_DIVIDERDBLCLICKW)))
8.{
9.*pResult=TRUE;
10.returnTRUE;
12.
13.returnCDialog:
OnNotify(wParam,lParam,pResult);
14.}
7、让第一列居中显示
在插入列时,我们可以通过参数nFormat来设置文本居中显示,但是这种设置对于第一列是没有作用的。
这时我们可以考虑将我们的内容从第二列开始插入(设置为居中显示)。
先插入第一列,然后删除第一列,这样原先的第二列就充当了第一列。
8、设置行高和字体
设置CListCtrl的行高没有函数接口,可以通过自绘来实现,但是比较麻烦。
有一个比较简单的方法是通过使用一个空白的图像将行撑起来,使其高度发生变化。
1.CImageListm_image;
2.m_image.Create(1,24,ILC_COLOR32,1,0);
3.m_listInfo.SetImageList(&
m_image,LVSIL_SMALL);
对于字体的设置,我们可以使用SetFont函数来实现。
以修改CListView的字体为例,在OnInitialUpdate函数中插入列之前调用SetFontSelf函数(该函数自定义,如下示例所示)。
首先创建一个字体,然后调用SetFont进行设置。
需要注意的是,在退出时需要delete掉创建的字体,避免内存泄露。
1.//设置字体和大小
2.voidCMyListView:
SetFontSelf(intnHeight,LPCTSTRlpszFacename)3.{
4.//先删除原有字体
5.if(m_font!
=NULL)
6.deletem_font;
7.m_font=newCFont;
8.//创建字体
9.m_font->
CreateFont(
10.nHeight,//nHeight
11.0,//nWidth
12.0,//nEscapement13.0,//nOrientation14.FW_NORMAL,//
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MFC 总结 CListCtrl 用法 技巧