MFC总结之CListCtrl用法及技巧(二)
本篇重点介绍: 禁 止拖动表头、让第一列居中显示、设置行高与字体、虚拟列表技术、点击表头时进行归类、向上与向下移动、动态调整大小问题、避免闪烁问题 。 6 、禁止拖动表头 重载 OnNotify 消息响应函数,屏蔽两个消息通知码: HDN_BEGINTRACKW 和 HDN_DIV
本篇重点介绍:禁止拖动表头、让第一列居中显示、设置行高与字体、虚拟列表技术、点击表头时进行归类、向上与向下移动、动态调整大小问题、避免闪烁问题。
6、禁止拖动表头
重载OnNotify消息响应函数,屏蔽两个消息通知码:HDN_BEGINTRACKW 和HDN_DIVIDERDBLCLICKW。示例如下:
[cpp] view plaincopy
- BOOL CXXXX::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
- {
- // TODO: Add your specialized code here and/or call the base class
- //屏蔽两个消息通知码,使得禁止拖动List表头
- NMHEADER* pNMHeader = (NMHEADER*)lParam;
- if(((pNMHeader->hdr.code == HDN_BEGINTRACKW) |
- (pNMHeader->hdr.code == HDN_DIVIDERDBLCLICKW)))
- {
- *pResult = TRUE;
- return TRUE;
- }
- return CDialog::OnNotify(wParam, lParam, pResult);
- }
7、让第一列居中显示
在插入列时,我们可以通过参数nFormat来设置文本居中显示,但是这种设置对于第一列是没有作用的。这时我们可以考虑将我们的内容从第二列开始插入(设置为居中显示)。先插入第一列,然后删除第一列,这样原先的第二列就充当了第一列。
8、设置行高和字体
设置CListCtrl的行高没有函数接口,可以通过自绘来实现,但是比较麻烦。有一个比较简单的方法是通过使用一个空白的图像将行撑起来,使其高度发生变化。示例如下:
[cpp] view plaincopy
- CImageList m_image;
- m_image.Create(1,24,ILC_COLOR32,1,0);
- m_listInfo.SetImageList(&m_image, LVSIL_SMALL);
[cpp] view plaincopy
- //设置字体和大小
- void CMyListView::SetFontSelf(int nHeight, LPCTSTR lpszFacename)
- {
- //先删除原有字体
- if(m_font != NULL)
- delete m_font;
- m_font = new CFont;
- //创建字体
- m_font->CreateFont(
- nHeight, // nHeight
- 0, // nWidth
- 0, // nEscapement
- 0, // nOrientation
- FW_NORMAL, // nWeight
- FALSE, // bItalic
- FALSE, // bUnderline
- 0, // cStrikeOut
- ANSI_CHARSET, // nCharSet
- OUT_DEFAULT_PRECIS, // nOutPrecision
- CLIP_DEFAULT_PRECIS, // nClipPrecision
- DEFAULT_QUALITY, // nQuality
- DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
- lpszFacename); // lpszFacename
- //设置字体
- CListCtrl &theCtrl = GetListCtrl(); //获取控制权,引用变量
- theCtrl.SetFont(m_font, TRUE);
- }
9、虚拟列表技术
给一个链接,介绍的比较详细:http://hi.baidu.com/qi_xian/blog/item/929b04ce27d02c0592457ef8.html当数据量大时,使用InsertItem插入数据的过程是很漫长的。这时我们有两个方法来解决该问题:一是使用CListCtrl的虚拟列表技术,二是采用分页显示的方法。对于虚拟列表技术,上述链接中的文章讲的很详细,我用过它的比较简单的方法,后来改用了分页方法。
使用虚拟列表技术,有三点需要搞清楚:
① 使用虚拟技术时,需要将CListCtrl控件的Owner Data属性设置为ture。
② 给虚拟列表添加元素时,不需要使用InserItem函数,通过调用SetItemCount设置数据总个数,然后由系统产生不同的消息,在相应的消息响应函数中完成插入工作。
③ 虚拟列表向父窗口发送的消息有三种: ⑴ 当它需要数据时,发送LVN_GETDISPINFO消息; ⑵ 当用户试图查找某个元素时,发送LVN_ODFINDITEM消息; ⑶当需要缓冲数据时,发送 LVN_ODCACHEHINT消息。
当我们使用LVN_GETDISPINFO 的消息处理函数来插入元素时,必须首先检查列表请求的是什么数据(如LVIF_TEXT、LVIF_IMAGE等),然后插入不同的子项。示例如下:
[cpp] view plaincopy
- void CDataAnalysis::OnLvnGetdispinfoAnalysisList(NMHDR *pNMHDR, LRESULT *pResult)
- {
- NMLVDISPINFO *pDispInfo = reinterpret_cast
(pNMHDR); - // TODO: Add your control notification handler code here
- LV_ITEM* pItem= &(pDispInfo)->item;
- int iItemIndex= pItem->iItem;
- size_t converted = 0;
- wchar_t wStr[30]; //Unicode字符串
- if (pItem->mask & LVIF_TEXT) //字符串缓冲区有效
- {
- switch(pItem->iSubItem)
- {
- case 0: //填充数据项的名字,xxxxx表示要填充的字符
- mbstowcs_s(&converted, wStr, 30, xxxxxx, _TRUNCATE);
- lstrcpy(pItem->pszText,wStr);
- break;
- case 1: //填充子项1
- mbstowcs_s(&converted, wStr, 30, xxxxxx, _TRUNCATE);
- lstrcpy(pItem->pszText,wStr);
- break;
- case 2: //填充子项2
- mbstowcs_s(&converted, wStr, 30, xxxxxx, _TRUNCATE);
- lstrcpy(pItem->pszText,wStr);
- break;
- case 3: //填充子项3
- lstrcpy(pItem->pszText,xxxxxx);
- break;
- }
- }
- *pResult = 0;
- }
10、点击表头时进行归类排序
系统通过发送LVM_SORTITEMS消息来处理归类问题,在该消息的处理函数中需要调用一个回调函数,这个回调函数需要我们来设计,以完成不同的归类方法。回调函数原型如下:int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
针对上述回调函数,有以下几点需要搞清楚:
① 对于参数lparam1和lparam2,分别为CListCtrl的两行数据,是用于比较的对象。通过CListCtrl的成员函数SetItemData来设置,该函数原型:
int SetItemData(int nIndex, DWORD_PTR dwItemData )
其第一个参数为行号,第二个参数指明了该行对应的参数。参数dwItemData 通常设为一行参数的数组,如: pData[2][2] = {{1, 3},{2, 3}}; 每次使用pData[i]作为dwItemData。
② 对于参数lParamSort,用于指明列项,即第几列。该参数和回调函数一同通过CListCtrl的成员函数SortItems来设置,其函数原型为:
BOOL SortItems( PFNLVCOMPARE pfnCompare,DWORD_PTR dwData )
参数 pfnCompare 为回调函数入口地址, 参数dwData 为列项。
③ SetItemData在初始插入数据时进行调用来设置,SortItems则在点击列表头时响应的消息处理函数中进行设置。
示例如下:
[cpp] view plaincopy
- //初始化列表视图控件
- BOOL CDataAnalysis::InitListCtl()
- {
- //其他处理,包括设置风格,插入列等等
- //插入行
- for(int i=0; i
- {
- //要将char*转换为wchar_t*
- mbstowcs_s(&converted, wStr, 30, m_analysis[i].Date, _TRUNCATE);
- m_listAnalysis.InsertItem(i, wStr); //日期
- mbstowcs_s(&converted, wStr, 30, m_analysis[i].Time, _TRUNCATE);
- m_listAnalysis.SetItemText(i, 1, wStr); //时间
- mbstowcs_s(&converted, wStr, 30, m_analysis[i].ID, _TRUNCATE);
- m_listAnalysis.SetItemText(i, 2, wStr); //ID
- m_listAnalysis.SetItemText(i, 3, m_analysis[i].lpszEvent); //事件
- //设置回调函数的参数
- m_listAnalysis.SetItemData(i, (LPARAM)(m_analysis+i));
- }
- return TRUE;
- }
- void CDataAnalysis::OnHdnItemclickAnalysisList(NMHDR *pNMHDR, LRESULT *pResult)
- {
- LPNMHEADER phdr = reinterpret_cast
(pNMHDR); - // TODO: Add your control notification handler code here
- //设置回调函数的参数和入口地址
- m_listAnalysis.SortItems(SortFunc, phdr->iItem);
- *pResult = 0;
- }
- //排序的回调函数
- int CALLBACK SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
- {
- int result; //返回值
- //两行的参数,用于比较
- ANALYSISFORMAT* pAnalysis1 = (ANALYSISFORMAT*)lParam1;
- ANALYSISFORMAT* pAnalysis2 = (ANALYSISFORMAT*)lParam2;
- //排序
- switch(lParamSort)
- {
- case 0: //日期
- result = strcmp(pAnalysis1->Date, pAnalysis2->Date);
- break;
- case 1: //时间
- result = strcmp(pAnalysis1->Time, pAnalysis2->Time);
- break;
- case 2: //ID
- result = strcmp(pAnalysis1->ID, pAnalysis2->ID);
- break;
- case 3: //事件
- result = wcscmp(pAnalysis1->lpszEvent, pAnalysis2->lpszEvent);
- break;
- default:
- break;
- }
- return result;
- }
11、向上与向下移动
有时需要向上或向下移动表项内容,这里给出向上移动的方法,向下移动的方法类似。
① 利用第2节所述的内容获取行号nItem,判断行号是否为行首,如果不是行首则进入②;
② 获取第nItem行的所有子项内容;
③ 删除第nItem行,并在nItem-1的位置重新插入原先的第nItem行的内容;
④ 使nItem-1的位置高亮显示
示例如下:
[cpp] view plaincopy
- /*************************上移子项**************************/
- void CStudyTestDlg::OnPageup()
- {
- if (nItem == 0)
- {
- MessageBox("该子项已经位于第一行!");
- return;
- }
- // 提取内容
- CString temp[4];
- int i;
- for(i=0;i
- temp[i] = m_ListCtrl.GetItemText(nItem, i);
- // 删除
- m_ListCtrl.DeleteItem(nItem);
- // 在nItem-1位置处插入
- for (i=0; i
- m_ListCtrl.SetItemText(nItem-1,i,temp[i]);
- //高亮显示
- UINT flag = LVIS_SELECTED|LVIS_FOCUSED;
- m_ListCtrl.SetItemState(--nItem, flag, flag);
- }
- /*************************下移子项**************************/
- void CStudyTestDlg::OnPagedown()
- {
- if (nItem == m_ListCtrl.GetItemCount()-1)
- {
- MessageBox("该子项已经位于最后一行!");
- return;
- }
- // 提取内容
- CString temp[4];
- int i;
- for (i=0; i
- temp[i] = m_ListCtrl.GetItemText(nItem, i);
- // 删除
- m_ListCtrl.DeleteItem(nItem);
- // 在nItem+1位置处插入
- for (i=0; i
- m_ListCtrl.SetItemText(nItem+1, i,temp[i]);
- //高亮显示
- UINT flag = LVIS_SELECTED|LVIS_FOCUSED;
- m_ListCtrl.SetItemState(++nItem, flag, flag);
- }
12、避免闪烁问题
这个问题在我的前面一篇博文有提到。http://blog.csdn.net/zwgdft/article/details/7394318
13、动态调整大小
有时由于不确定软件运行时的电脑屏幕大小,需要根据屏幕大小动态设置CListCtrl控件的大小。动态大小的设置时,需要注意不要将高度和宽度设置的超过区域限制,否则就没有滚动条了,导致部分内容无法查看。以我遇到的一个例子来说,其情况见第12节提到的那篇博文所述:将View划分为三个窗格,在左上角View上有个CPropertySheet,其上有几个CPropertyPage,每个属性页上有个CListCtrl,供用户查看信息。那么这时需要设置的CListCtrl的大小即为:
宽度 = 左上角View宽度
高度 = 左上角View高度 - 属性页的Tab项高度
调用MoveWindow函数进行设置即可。
------------------全文完--------------------

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Win11 Tips Sharing: One trick to skip Microsoft account login Windows 11 is the latest operating system launched by Microsoft, with a new design style and many practical functions. However, for some users, having to log in to their Microsoft account every time they boot up the system can be a bit annoying. If you are one of them, you might as well try the following tips, which will allow you to skip logging in with a Microsoft account and enter the desktop interface directly. First, we need to create a local account in the system to log in instead of a Microsoft account. The advantage of doing this is

In C language, it represents a pointer, which stores the address of other variables; & represents the address operator, which returns the memory address of a variable. Tips for using pointers include defining pointers, dereferencing pointers, and ensuring that pointers point to valid addresses; tips for using address operators & include obtaining variable addresses, and returning the address of the first element of the array when obtaining the address of an array element. A practical example demonstrating the use of pointer and address operators to reverse a string.

We often create and edit tables in excel, but as a novice who has just come into contact with the software, how to use excel to create tables is not as easy as it is for us. Below, we will conduct some drills on some steps of table creation that novices, that is, beginners, need to master. We hope it will be helpful to those in need. A sample form for beginners is shown below: Let’s see how to complete it! 1. There are two methods to create a new excel document. You can right-click the mouse on a blank location on the [Desktop] - [New] - [xls] file. You can also [Start]-[All Programs]-[Microsoft Office]-[Microsoft Excel 20**] 2. Double-click our new ex

VSCode (Visual Studio Code) is an open source code editor developed by Microsoft. It has powerful functions and rich plug-in support, making it one of the preferred tools for developers. This article will provide an introductory guide for beginners to help them quickly master the skills of using VSCode. In this article, we will introduce how to install VSCode, basic editing operations, shortcut keys, plug-in installation, etc., and provide readers with specific code examples. 1. Install VSCode first, we need

Title: PHP Programming Tips: How to Jump to a Web Page within 3 Seconds In web development, we often encounter situations where we need to automatically jump to another page within a certain period of time. This article will introduce how to use PHP to implement programming techniques to jump to a page within 3 seconds, and provide specific code examples. First of all, the basic principle of page jump is realized through the Location field in the HTTP response header. By setting this field, the browser can automatically jump to the specified page. Below is a simple example demonstrating how to use P

Win11 tricks revealed: How to bypass Microsoft account login Recently, Microsoft launched a new operating system Windows11, which has attracted widespread attention. Compared with previous versions, Windows 11 has made many new adjustments in terms of interface design and functional improvements, but it has also caused some controversy. The most eye-catching point is that it forces users to log in to the system with a Microsoft account. For some users, they may be more accustomed to logging in with a local account and are unwilling to bind their personal information to a Microsoft account.

In Go language program development, function reconstruction skills are a very important part. By optimizing and refactoring functions, you can not only improve code quality and maintainability, but also improve program performance and readability. This article will delve into the function reconstruction techniques in the Go language, combined with specific code examples, to help readers better understand and apply these techniques. 1. Code example 1: Extract duplicate code fragments. In actual development, we often encounter reused code fragments. At this time, we can consider extracting the repeated code as an independent function to

Forms are an integral part of writing a website or application. Laravel, as a popular PHP framework, provides rich and powerful form classes, making form processing easier and more efficient. This article will introduce some tips on using Laravel form classes to help you improve development efficiency. The following explains in detail through specific code examples. Creating a form To create a form in Laravel, you first need to write the corresponding HTML form in the view. When working with forms, you can use Laravel
