Listview控件使用技巧大汇总 连载(三)

时间:2021-09-09 19:15:51

一 、前言:

Listview,即列表框控件。它在应用程序中的使用率很高,在windows中也经常见到,如其四种常见的式样,分别为显示大图标,小目标,含有图标的多列列表,含有列标头的列表。我们也经常见到它的一些扩展功能,例如我们在资源管理器中的文件列表框中,在选用详细资料察看时,用鼠标单击列标头,如大小,则所列文件按大小排序;单机日期,则按文件日期进行排序等。

它的诸多功能增强了应用程序的可用性,使操作更直观、方便。很多朋友在该控件的使用会遇到各种问题,现将其常用功能做了一下汇总整理,因为篇幅较长,分为三篇连载,前面两篇为《Listview控件使用技巧大汇总 连载(一)》和《Listview控件使用技巧大汇总 连载(二)》下面介绍为其第三部分,希望对读者有所帮助。

在整理过程中感谢网络上各位朋友提供的建议和帮助,感谢身边朋友的理解和陪伴。因为没有你们的支持可能没有耐心完成关的汇总整理。

CListView中内置了CListCtrl,所以对CListView的操作实际上就是对内置CListCtrl的操作。下面代码例子中默认view 风格为report,相关类及处理函数为---MFC:CListCtrl类和SDK:以 “ListView_”开头的一些宏。如 ListView_InsertColumn。

二 、高级级用法:

2.1. 在CListCtrl显示文件,并根据文件类型来显示图标

示例代码如下:

01.BOOL C6Dlg::OnInitDialog()02.{03.CDialog::OnInitDialog();04.HIMAGELIST himlSmall;05.HIMAGELIST himlLarge;06.SHFILEINFO sfi;07.char cSysDir[MAX_PATH];08.CString strBuf;09.memset(cSysDir, 0, MAX_PATH);10.GetWindowsDirectory(cSysDir, MAX_PATH);11.strBuf = cSysDir;12.sprintf(cSysDir, "%s", strBuf.Left(strBuf.Find("//")+1));13.himlSmall = (HIMAGELIST)SHGetFileInfo ((LPCSTR)cSysDir,14.0,15.&sfi,16.sizeof(SHFILEINFO),17.SHGFI_SYSICONINDEX | SHGFI_SMALLICON );18.himlLarge = (HIMAGELIST)SHGetFileInfo((LPCSTR)cSysDir,19.0,20.&sfi,21.sizeof(SHFILEINFO),22.SHGFI_SYSICONINDEX | SHGFI_LARGEICON);23.if (himlSmall && himlLarge)24.{25.::SendMessage(m_list.m_hWnd, LVM_SETIMAGELIST,26.(WPARAM)LVSIL_SMALL, (LPARAM)himlSmall);27.::SendMessage(m_list.m_hWnd, LVM_SETIMAGELIST,28.(WPARAM)LVSIL_NORMAL, (LPARAM)himlLarge);29.}30.return TRUE; // return TRUE unless you set the focus to a control31.}32.void C6Dlg::AddFiles(LPCTSTR lpszFileName, BOOL bAddToDocument)33.{34.int nIcon = GetIconIndex(lpszFileName, FALSE, FALSE);35.CString strSize;36.CFileFind filefind;37.// get file size38.if (filefind.FindFile(lpszFileName))39.{40.filefind.FindNextFile();41.strSize.Format("%d", filefind.GetLength());42.}43.else44.strSize = "0";45.// split path and filename46.CString strFileName = lpszFileName;47.CString strPath;48.int nPos = strFileName.ReverseFind('//');49.if (nPos != -1)50.{51.strPath = strFileName.Left(nPos);52.strFileName = strFileName.Mid(nPos + 1);53.}54.// insert to list55.int nItem = m_list.GetItemCount();56.m_list.InsertItem(nItem, strFileName, nIcon);57.m_list.SetItemText(nItem, 1, strSize);58.m_list.SetItemText(nItem, 2, strFileName.Right(3));59.m_list.SetItemText(nItem, 3, strPath);60.}61.int C6Dlg::GetIconIndex(LPCTSTR lpszPath, BOOL bIsDir, BOOL bSelected)62.{63.SHFILEINFO sfi;64.memset(&sfi, 0, sizeof(sfi));65.if (bIsDir)66.{67.SHGetFileInfo(lpszPath,68.FILE_ATTRIBUTE_DIRECTORY,69.&sfi,70.sizeof(sfi),71.SHGFI_SMALLICON | SHGFI_SYSICONINDEX |72.SHGFI_USEFILEATTRIBUTES |(bSelected ? SHGFI_OPENICON : 0));73.return sfi.iIcon;74.}75.else76.{77.SHGetFileInfo (lpszPath,78.FILE_ATTRIBUTE_NORMAL,79.&sfi,80.sizeof(sfi),81.SHGFI_SMALLICON | SHGFI_SYSICONINDEX |82.SHGFI_USEFILEATTRIBUTES | (bSelected ? SHGFI_OPENICON : 0));83.return sfi.iIcon;84.}85.return -1;86.}

2.2. listctrl排序

示例代码如下:

001.void CMyView::OnInitialUpdate()002.{003.CFormView::OnInitialUpdate();004.m_listCtrl.InsertColumn(0, "Western States", LVCFMT_LEFT, 150);005.LV_ITEM lvItem;006.ZeroMemory(&lvItem, sizeof(lvItem));007.lvItem.mask = LVIF_TEXT | LVIF_STATE;008.lvItem.iItem = 0;009.lvItem.state = LVIS_CUT | LVIS_SELECTED;010.lvItem.pszText = "Washington";011.m_listCtrl.InsertItem(&lvItem); // initially selected012.lvItem.iItem = 1;013.lvItem.state = LVIS_CUT | LVIS_SELECTED;014.lvItem.pszText = "Arizona";015.m_listCtrl.InsertItem(&lvItem); // initially selected016.lvItem.iItem = 2;017.lvItem.state = LVIS_CUT;018.lvItem.pszText = "Alaska";019.m_listCtrl.InsertItem(&lvItem);020.lvItem.iItem = 3;021.lvItem.state = LVIS_CUT;022.lvItem.pszText = "California";023.m_listCtrl.InsertItem(&lvItem);024.lvItem.iItem = 4;025.lvItem.state = LVIS_CUT;026.lvItem.pszText = "Nevada";027.m_listCtrl.InsertItem(&lvItem);028.UINT nState;029.CString strText;030.int iItem = -1;031.// as long as GetNextItem found an item...032.while ((iItem = m_listCtrl.GetNextItem(iItem, LVNI_ALL)) > -1 )033.{034.// get item string035.strText = m_listCtrl.GetItemText(iItem, 0);036.// show initial state of flags037.nState = m_listCtrl.GetItemState(iItem, LVIS_SELECTED | LVIS_CUT);038.TRACE("%s state flag is %0x\n", strText, nState);039.// Get only LVIS_SELECTED flag040.// note that LVIS_CUT is not returned in nState041.nState = m_listCtrl.GetItemState(iItem, LVIS_SELECTED);042.// select states beginning with 'A'043.if (strText[0] == 'A' && !nState) {044.TRACE("%s needed to be selected\n", strText);045.m_listCtrl.SetItemState(iItem,046.LVIS_SELECTED,  // nState047.LVIS_SELECTED); // nMask048.// deselect states that don't begin with 'A'049.else if (strText[0] != 'A' && nState) {050.TRACE("%s needed to be deselected\n", strText);051.m_listCtrl.SetItemState(iItem,052.0,              // nState053.LVIS_SELECTED); // nMask054.}055.// show new flags if modified, note that LVIS_CUT wasn't affected056.nState = m_listCtrl.GetItemState(iItem, LVIS_SELECTED | LVIS_CUT);057.TRACE("%s state flag is now %0x\n", strText, nState);058.}059.}060.// 排序用的比较函数061.static int CALLBACK MyCompareProc(LPARAMlParam1, LPARAMlParam2, LPARAMlParamSort)062.{063.CString &lp1 = *((CString *)lParam1);064.CString &lp2 = *((CString *)lParam2);065.int &sort = *(int *)lParamSort;066.if (sort == 0)067.{068.returnlp1.CompareNoCase(lp2);069.}070.else071.{072.returnlp2.CompareNoCase(lp1);073.}074.}075.//要处理的事件076.ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST1, &CDlg::OnLvnColumnclickList1)077.//处理代码078.voidCDlg::OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult)079.{080.LPNMLISTVIEWpNMLV = reinterpret_cast(pNMHDR);081.intLength = m_ListCtrl.GetItemCount();082.CArray ItemData;083.ItemData.SetSize(Length);084.for (inti = 0; i < Length; i++)085.{086.ItemData[i] = m_ListCtrl.GetItemText(i,pNMLV->iSubItem);087.m_ListCtrl.SetItemData(i,(DWORD_PTR)&ItemData[i]);//设置排序关键字088.}089.staticintsort = 0;090.staticintSubItem = 0;091.if (SubItem != pNMLV->iSubItem)092.{093.sort = 0;094.SubItem = pNMLV->iSubItem;095.}096.else097.{098.if (sort == 0)099.{100.sort = 1;101.}102.else103.{104.sort = 0;105.}106.}107.m_ListCtrl.SortItems(MyCompareProc,(DWORD_PTR)&sort);//排序108.*pResult = 0;109.}

列表控件可以看作是功能增强的ListBox,它提供了四种风格,而且可以同时显示一列的多中属性值。MFC中使用CListCtrl类来封装列表控件的各种操作。通过调用 BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );创建一个窗口,dwStyle中可以使用以下一些列表控件的专用风格:

LVS_ICON LVS_SMALLICON LVS_LIST LVS_REPORT 这四种风格决定控件的外观,同时只可以选择其中一种,分别对应:大图标显示,小图标显示,列表显示,详细报表显示

LVS_EDITLABELS 结点的显示字符可以被编辑,对于报表风格来讲可编辑的只为第一列。

LVS_SHOWSELALWAYS 在失去焦点时也显示当前选中的结点

LVS_SINGLESEL 同时只能选中列表中一项

首先你需要设置列表控件所使用的ImageList,如果你使用大图标显示风格,你就需要以如下形式调用: CImageList* SetImageList( CImageList* pImageList, LVSIL_NORMAL); 如果使用其它三种风格显示而不想显示图标你可以不进行任何设置,否则需要以如下形式调用: CImageList* SetImageList( CImageList* pImageList, LVSIL_SMALL);

通过调用int InsertItem( int nItem, LPCTSTR lpszItem );可以在列表控件中nItem指明位置插入一项,lpszItem为显示字符。除LVS_REPORT风格外其他三种风格都只需要直接调用 InsertItem就可以了,但如果使用报表风格就必须先设置列表控件中的列信息。

通过调用int InsertColumn( int nCol, LPCTSTR lpszColumnHeading, int nFormat , int nWidth, int nSubItem);可以插入列。iCol为列的位置,从零开始,lpszColumnHeading为显示的列名,nFormat为显示对齐方式, nWidth为显示宽度,nSubItem为分配给该列的列索引。

在有多列的列表控件中就需要为每一项指明其在每一列中的显示字符,通过调用 BOOL SetItemText( int nItem, int nSubItem, LPTSTR lpszText );可以设置每列的显示字符。nItem为设置的项的位置,nSubItem为列位置,lpszText为显示字符。下面的代码演示了如何设置多列并插入数据:

1.m_list.SetImageList(&m_listSmall,LVSIL_SMALL);//设置ImageList2.m_list.InsertColumn(0,"Col 1",LVCFMT_LEFT,300,0);//设置列3.m_list.InsertColumn(1,"Col 2",LVCFMT_LEFT,300,1);4.m_list.InsertColumn(2,"Col 3",LVCFMT_LEFT,300,2);5.m_list.InsertItem(0,"Item 1_1");//插入行6.m_list.SetItemText(0,1,"Item 1_2");//设置该行的不同列的显示字符7.m_list.SetItemText(0,2,"Item 1_3");

此外CListCtrl还提供了一些函数用于得到/修改控件的状态。 COLORREF GetTextColor( )/BOOL SetTextColor( COLORREF cr );用于得到/设置显示的字符颜色。 COLORREF GetTextBkColor( )/BOOL SetTextBkColor( COLORREF cr );用于得到/设置显示的背景颜色。 void SetItemCount( int iCount );用于得到添加进列表中项的数量。 BOOL DeleteItem(int nItem);用于删除某一项,BOOL DeleteAllItems( );将删除所有项。 BOOL SetBkImage(HBITMAP hbm, BOOL fTile , int xOffsetPercent, int yOffsetPercent);用于设置背景位图。 CString GetItemText( int nItem, int nSubItem );用于得到某项的显示字符。

列表控件的消息映射同样使用ON_NOTIFY宏,形式如同:ON_NOTIFY( wNotifyCode, id, memberFxn ),wNotifyCode为知代码,id为产生该消息的窗口ID,memberFxn为处理函数,函数的原型如同void OnXXXList(NMHDR* pNMHDR, LRESULT* pResult),其中pNMHDR为一数据结构,在具体使用时需要转换成其他类型的结构。对于列表控件可能取值和对应的数据结构为:

LVN_BEGINLABELEDIT 在开始某项编辑字符时发送,所用结构:NMLVDISPINFO

LVN_ENDLABELEDIT 在结束某项编辑字符时发送,所用结构:NMLVDISPINFO

LVN_GETDISPINFO 在需要得到某项信息时发送,(如得到某项的显示字符)所用结构:NMLVDISPINFO

关于ON_NOTIFY有很多内容,将在以后的内容中进行详细讲解。

关于动态提供结点所显示的字符:首先你在项时需要指明lpszItem参数为: LPSTR_TEXTCALLBACK。在控件显示该结点时会通过发送TVN_GETDISPINFO来取得所需要的字符,在处理该消息时先将参数 pNMHDR转换为LPNMLVDISPINFO,然后填充其中item.pszText。通过item中的iItem,iSubItem可以知道当前显示的为那一项。下面的代码演示了这种方法:

01.char szOut[8][3]={"No.1","No.2","No.3"};02.//添加结点03.m_list.InsertItem(LPSTR_TEXTCALLBACK,...)04.m_list.InsertItem(LPSTR_TEXTCALLBACK,...)05.//处理消息06.void CParentWnd::OnGetDispInfoList(NMHDR* pNMHDR, LRESULT* pResult)07.{08.LV_DISPINFO* pLVDI = (LV_DISPINFO*)pNMHDR;09.pLVDI->item.pszText=szOut[pTVDI->item.iItem];//通过iItem得到需要显示的字符在数组中的位置10.*pResult = 0;11.}

关于编辑某项的显示字符:(在报表风格中只对第一列有效)首先需要设置列表控件的 LVS_EDITLABELS风格,在开始编辑时该控件将会发送LVN_BEGINLABELEDIT,你可以通过在处理函数中返回TRUE来取消接下来的编辑,在编辑完成后会发送LVN_ENDLABELEDIT,在处理该消息时需要将参数pNMHDR转换为LPNMLVDISPINFO,然后通过其中的item.pszText得到编辑后的字符,并重置显示字符。如果编辑在中途中取消该变量为NULL。下面的代码说明如何处理这些消息:

01.//处理消息 LVN_BEGINLABELEDIT02.void CParentWnd::OnBeginEditList(NMHDR* pNMHDR, LRESULT* pResult)03.{04.LV_DISPINFO* pLVDI = (LV_DISPINFO*)pNMHDR;05.if(pLVDI->item.iItem==0);//判断是否取消该操作06.*pResult = 1;07.else08.*pResult = 0;09.}10.//处理消息 LVN_BEGINLABELEDIT11.void CParentWnd::OnBeginEditList(NMHDR* pNMHDR, LRESULT* pResult)12.{13.LV_DISPINFO* pLVDI = (LV_DISPINFO*)pNMHDR;14.if(pLVDI->item.pszText==NULL);//判断是否已经取消取消编辑15.m_list.SetItemText(pLVDI->item.iItem,0,pLVDI->pszText);//重置显示字符16.*pResult = 0;17.}

上面讲述的方法所进行的消息映射必须在父窗口中进行(同样WM_NOTIFY的所有消息都需要在父窗口中处理)。
如何得到当前选中项位置:在列表控件中没有一个类似于ListBox中GetCurSel()的函数,但是可以通过调用GetNextItem( -1, LVNI_ALL | LVNI_SELECTED);得到选中项位置。

2.3.listctrl内容进行大数据量更新时,避免闪烁

1.m_list.SetRedraw(FALSE);2.//更新内容3.m_list.SetRedraw(TRUE);4.m_list.Invalidate();5.m_list.UpdateWindow();

或者参考

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_mfc_cwnd.3a3a.setredraw.asp

2.4.在listctrl中选中某个item时动态改变其icon或bitmap

Q141834: How to change the icon or the bitmap of a CListCtrl item in Visual C++

http://support.microsoft.com/kb/141834/en-us

2.5.在添加item后,再InsertColumn()后导致整列数据移动的问题

Q151897: CListCtrl::InsertColumn() Causes Column Data to Shift

http://support.microsoft.com/kb/151897/en-us

2.6.关于listctrl第一列始终居左的问题

解决办法:把第一列当一个虚列,从第二列开始插入列及数据,最后删除第一列。

2.7.锁定column header的拖动

http://msdn.microsoft.com/msdnmag/issues/03/06/CQA/

2.8.如何隐藏clistctrl的列

把需隐藏的列的宽度设为0,然后检测当该列为隐藏列时,用上面第27点的锁定column 的拖动来实现

2.9.listctrl进行大数据量操作时,使用virtual list

http://www.microsoft.com/msj/archive/S2061.aspx

http://www.codeguru.com/cpp/controls/listview/advanced/article.php/c4151/

http://www.codeproject.com/listctrl/virtuallist.asp

2.10.关于item只能显示259个字符的问题

解决办法:需要在item上放一个edit。

2.11.响应在listctrl的column header上的鼠标右键单击

Q125694: How To Find Out Which Listview Column Was Right-Clicked

http://support.microsoft.com/kb/125694/en-us

2.12.类似于windows资源管理器的listview

Q234310: How to implement a ListView control that is similar to Windows Explorer by using DirLV.exe

http://support.microsoft.com/kb/234310/en-us

2.13.在ListCtrl中OnTimer只响应两次的问题

Q200054:

PRB: OnTimer() Is Not Called Repeatedly for a List Control

http://support.microsoft.com/kb/200054/en-us

2.14.以下为一些为实现各种自定义功能的listctrl派生类

(1) 拖放

http://www.codeproject.com/listctrl

在CListCtrl和CTreeCtrl间拖放

http://support.microsoft.com/kb/148738/en-us

(2) 多功能listctrl

支持subitem可编辑,图标,radiobutton,checkbox,字符串改变颜色的类

http://www.codeproject.com/Articles/8112/CQuickList

支持排序,subitem可编辑,subitem图标,subitem改变颜色的类

http://www.codeproject.com/Articles/5560/Another-Report-List-Control

(3) subitem中显示超链接

http://www.codeproject.com/Articles/4821/CListCtrl-With-Web-Links

(4) subitem的tooltip提示

http://www.codeproject.com/Articles/1548/CToolTipListCtrl-A-CListCtrl-derived-class-providi

(5) subitem中显示进度条

http://www.codeproject.com/Articles/6813/List-Control-Extended-for-Progress-Control

http://www.codeproject.com/Articles/1342/Adding-progress-bars-to-a-list-control

http://www.codeguru.com/Cpp/controls/listview/article.php/c4187/

(6) 动态改变subitem的颜色和背景色

http://www.codeproject.com/Articles/1316/Dynamically-Highlight-Elements-in-a-List-Control

http://www.codeguru.com/Cpp/controls/listbox/colorlistboxes/article.php/c4757/

(7) 类vb属性对话框

http://www.codeproject.com/Articles/614/An-Adaptable-Property-List-Control

http://www.codeguru.com/Cpp/controls/listview/propertylists/article.php/c995/

http://www.codeguru.com/Cpp/controls/listview/propertylists/article.php/c1041/

(8) 选中subitem(只高亮选中的item)

http://www.codeproject.com/Articles/8194/SubItem-Selection-in-List-Control

http://www.codeproject.com/Articles/9155/SubItem-Selection-in-List-Control

(9) 改变行高

http://www.codeproject.com/Articles/1401/Changing-Row-Height-in-an-owner-drawn-Control

(10) 改变行颜色

http://www.codeproject.com/Articles/12343/Alternate-Row-Colors-for-the-CListCtrl

(11) 可编辑subitem的listctrl

http://www.codeproject.com/Articles/1317/Editable-Table-Control

http://www.codeproject.com/Articles/1124/Editing-Sub-Items-in-List-Control

(12) subitem可编辑,插入combobox,改变行颜色,subitem的tooltip提示

http://www.codeproject.com/Articles/12344/A-Simple-Reusable-List-Control

(13) header 中允许多行字符串

http://www.codeproject.com/Articles/510/A-Multiline-Header-Control-Inside-a-CListCtrl

(14) 插入combobox

http://www.codeguru.com/Cpp/controls/listview/editingitemsandsubitem/article.php/c979/

(15) 添加背景图片

http://www.codeguru.com/Cpp/controls/listview/backgroundcolorandimage/article.php/c4173/

http://www.codeguru.com/Cpp/controls/listview/backgroundcolorandimage/article.php/c983/

(16) 自适应宽度的listctrl

http://www.codeproject.com/Articles/11483/Let-Your-ListCtrl-Adjust-its-Column-Widths-Automat

(17) 改变ListCtrl高亮时的颜色(默认为蓝色)

处理 NM_CUSTOMDRAW

http://www.codeproject.com/Articles/79/Neat-Stuff-to-Do-in-List-Controls-Using-Custom-Dra

(18) 改变header颜色

http://www.pocketpcdn.com/articles/hdr_color.html

2.15.CListCtrl显示样式的改变

01.m_pCtrl = &this->GetListCtrl(); //获得指针02.//CListCtrl样式改变03.LONG lStyle;04.lStyle = GetWindowLong(m_pCtrl->m_hWnd, GWL_STYLE); //获取当前窗口style05.lStyle &= ~LVS_TYPEMASK; //清除显示方式06.lStyle |= LVS_REPORT; //设置style为Report显示07.SetWindowLong(m_pCtrl->m_hWnd, GWL_STYLE, lStyle);08.//CListCtrl扩展样式改变09.DWORD dwStyle;10.dwStyle = m_pCtrl->GetStyle(); //取得样式11.dwStyle |= LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT ; //添加样式12.m_pCtrl->SetExtendedStyle(dwStyle); //重新设置

需要的样式(根据自己的需要的样式选择) LVS_ICON: 为每个item显示大图标 LVS_SMALLICON: 为每个item显示小图标 LVS_LIST: 显示一列带有小图标的item LVS_REPORT: 显示item详细资料 LVS_EX_FULLROWSELECT: 表示选中某行使整行高亮(只适用与report风格的CListCtrl) LVS_EX_GRIDLINES: 表示显示网格线(只适用与report风格的CListCtrl)

2.16.添加CListCtrl的记录

1.//插入列2.m_pCtrl->InsertColumn(1,"第一列",LVCFMT_CENTER,47); //序号,标题,标题显示位置,列宽度3.m_pCtrl->InsertColumn(2,"第二列",LVCFMT_CENTER,100);4.//写入数据5.int nRow = m_list.InsertItem(0, “无用字符串”); //插入行6.m_list.SetItemText(nRow, 1, “1111”); //设置数据7.m_list.SetItemText(nRow, 2, “2222”); //设置数据

2.17.判断CListCtrl的哪行记录被选中了

01.int n = -1;02.POSITION pos = m_pCtrl->GetFirstSelectedItemPosition(); //返回第一个选中的行位置03.if (pos != NULL)04.{05.while (pos)06.{07.n = m_pCtrl->GetNextSelectedItem(pos); //返回下一个选中的行数(返回值从0开始)08.//做相应操作09.}10.}

2.18. CListCtrl,CListView与LVN_ITEMCHANGED消息

若要在CListCtrl中行发生改变时得到通知,可以映射LVN_ITEMCHANGED消息。

01.ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnItemchanged)02.afx_msg void OnItemchanged(NMHDR* pNMHDR,LRESULT* pResult);03.// 行选择改变04.void CMyListCtrl::OnItemchanged(NMHDR* pNMHDR, LRESULT* pResult)05.{06.NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;07....您要进行的操作...08.*pResult = 0;09.}

注意,LVN_ITEMCHANGED消息的产生有以下几种可能:

1、由选中到没选中的变化;

2、由没选中到选中的变化;

3、由选中一行到选中另外一行的变化;

4、使用CListCtrl::SetItem函数更改了行;

如何检测LVN_ITEMCHANGED消息是由那一变化产生的呢?

NM_LISTVIEW结构成员变量uChanged和uNewState包含着这类信息,看如下代码:

01.void CRunListView::OnItemchanged(NMHDR* pNMHDR, LRESULT* pResult)02.{03.NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;04.if(pNMListView->uChanged == LVIF_STATE)05.{06.if(pNMListView->uNewState)07.TRACE0("选择改变且有选中的行/r/n");08.else09.TRACE0("选择改变且没有选中的行/r/n");10.}11.else12.TRACE0("行改变(CListCtrl::SetItem)/r/n");13.*pResult = 0;14.}

2.19.响应单击CListCtrl事件

01.//响应CMyListView的=NUM_CLICK消息02.//直接用VC类向导生成后,不用再次添加声明和消息映射03.//添加函数声明04.afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult);05.//添加消息映射06.ON_NOTIFY_REFLECT(NM_CLICK, OnClick)07.void CMyListView::OnClick(NMHDR* pNMHDR, LRESULT* pResult)08.{09.// TODO: Add your control notification handler code here10.NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;11.if(pNMListView->iItem != -1)12.{13. 14.//值从0开始计算,无数据区不相应时间15.//相应操作16.}17.*pResult = 0;18.}

2.20.自绘ListCtrl类

示例如下:

01.//自绘CListCtrl类,重载虚函数DrawItem02.void CNewListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)03.{04.// TODO: Add your code to draw the specified item05.ASSERT(lpDrawItemStruct->CtlType == ODT_LISTVIEW);06.CDC dc;07.dc.Attach(lpDrawItemStruct->hDC);08.ASSERT(NULL != dc.GetSafeHdc());09.// Save these value to restore them when done drawing.10.COLORREF crOldTextColor = dc.GetTextColor();11.COLORREF crOldBkColor = dc.GetBkColor();12.// If this item is selected, set the background color13.// and the text color to appropriate values. Also, erase14.// rect by filling it with the background color.15.if ((lpDrawItemStruct->itemAction | ODA_SELECT) &&16.(lpDrawItemStruct->itemState & ODS_SELECTED))17.{18.dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));19.dc.SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));20.dc.FillSolidRect(&lpDrawItemStruct->rcItem,21.::GetSysColor(COLOR_HIGHLIGHT));22.}23.else24.{25.if(lpDrawItemStruct->itemID%2)26.dc.FillSolidRect(&lpDrawItemStruct->rcItem, RGB(128,128,128));27.else28.dc.FillSolidRect(&lpDrawItemStruct->rcItem, RGB(255,128,255));29.}30.// If this item has the focus, draw a red frame around the31.// item's rect.32.if ((lpDrawItemStruct->itemAction | ODA_FOCUS) &&33.(lpDrawItemStruct->itemState & ODS_FOCUS))34.{35.CBrush br(RGB(0, 0, 128));36.dc.FrameRect(&lpDrawItemStruct->rcItem, &br);37.}38.// Draw the text.39.CString strText(_T(""));40.CRect rcItem;41.for(int i=0; iGetItemCount(); i++)42.{43.strText = GetItemText(lpDrawItemStruct->itemID, i);44.GetSubItemRect(lpDrawItemStruct->itemID, i, LVIR_LABEL, rcItem);45.rcItem.left += 5;46.dc.DrawText(47.strText,48.strText.GetLength(),49.&rcItem,50.DT_LEFT|DT_SINGLELINE|DT_VCENTER);51.}52.// Reset the background color and the text color back to their53.// original values.54.dc.SetTextColor(crOldTextColor);55.dc.SetBkColor(crOldBkColor);56.dc.Detach();57.}58.// 调用59.CNewListCtrl m_list; // 类的成员变量60.#define IDC_LIST 0x110161.m_list.Create(WS_CHILD|WS_VISIBLE|WS_BORDER|WS_VSCROLL|WS_HSCROLL|LVS_OWNERDRAWFIXED, CRect(0, 0, 280, 280), this, IDC_LIST);62.m_list.ModifyStyle(0, LVS_REPORT|LVS_SINGLESEL);63.m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);64.m_list.InsertColumn(0, _T("VVV"), LVCFMT_LEFT, 100);65.m_list.InsertColumn(1, _T("CCC"), LVCFMT_LEFT, 100);66.CString strText(_T(""));67.for(int i=0; i<10; i++)68.{69.m_list.InsertItem(i, _T(""));70.strText.Format(_T("%d - Hello, Vckbase!"), i+1);71.m_list.SetItemText(i, 0, strText);72.strText.Format(_T("%d – All Is Well"), i+1);73.m_list.SetItemText(i, 1, strText);74.}

三、总结:

以上为该控件的高级用法,谢谢您的关注^_^。