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函数进行设置即可。
------------------全文完--------------------

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

Win11小技巧分享:一招跳过微软账户登录Windows11是微软最新推出的操作系统,具有全新的设计风格和许多实用的功能。然而,对于一些用户来说,在每次启动系统时都要登录微软账户可能会感到有些烦扰。如果你是其中一员,不妨尝试一下以下的技巧,让你能够跳过微软账户登录,直接进入桌面界面。首先,我们需要在系统中创建一个本地账户,来代替微软账户登录。这样做的好处是

我们经常在excel中制作和编辑表格,但是作为一个刚刚接触软件的新手来讲,如何使用excel制作表格,并没有我们使用起来那么轻松。下边,我们针对新手,也就是初学者需要掌握的表格制作的一些步骤进行一些演练,希望对需要的人有些帮助。新手表格示例样板如下图:我们看看如何来完成!1,新建excel文档,有两种方法。可以在【桌面】空白位置,点击鼠标右键-【新建】-【xls】文件。也可以【开始】-【所有程序】-【MicrosoftOffice】-【MicrosoftExcel20**】2,双击我们新建的ex

C语言中,表示指针,存储其他变量的地址;&表示地址运算符,返回变量的内存地址。指针的使用技巧包括定义指针、解引用指针,需确保指针指向有效地址;地址运算符&的使用技巧包括获取变量地址,获取数组元素地址时返回数组第一元素地址。实战案例说明了使用指针和地址运算符反转字符串。

VSCode(VisualStudioCode)是一款由微软开发的开源代码编辑器,具有强大的功能和丰富的插件支持,成为开发者们的首选工具之一。本文将为初学者们提供一个入门指南,帮助他们快速掌握VSCode的使用技巧。在本文中,将介绍如何安装VSCode、基本的编辑操作、快捷键、插件安装等内容,并为读者提供具体的代码示例。1.安装VSCode首先,我们需

Win11技巧大揭秘:如何绕过微软账户登录近期,微软公司推出了全新的操作系统Windows11,引起了广泛关注。相比之前的版本,Windows11在界面设计、功能改进等方面做出了许多新的调整,但也引发了一些争议,其中最引人关注的一点就是强制要求用户使用微软账户登录系统。对于一些用户来说,他们可能更习惯于使用本地账户登录,而不愿意将个人信息与微软账户绑定。

标题:PHP编程技巧:如何实现3秒内跳转网页在Web开发中,经常会遇到需要在一定时间内自动跳转到另一个页面的情况。本文将介绍如何使用PHP实现在3秒内实现页面跳转的编程技巧,并提供具体的代码示例。首先,实现页面跳转的基本原理是通过HTTP的响应头中的Location字段来实现。通过设置该字段可以让浏览器自动跳转到指定的页面。下面是一个简单的例子,演示如何在P

在编写网站或应用程序时,表单是不可或缺的一部分。Laravel作为一款流行的PHP框架,提供了丰富而强大的表单类,使得表单处理变得更加简单和高效。本文将介绍一些Laravel表单类的使用技巧,帮助你提高开发效率。下面通过具体的代码示例来详细讲解。创建表单要在Laravel中创建表单,首先需要在视图中编写相应的HTML表单。在处理表单时,可以使用Laravel

PHP中POST请求的使用是在网站开发中常见的操作,通过POST请求可以向服务器发送数据,例如表单数据、用户信息等。正确使用POST请求可以确保数据安全性和准确性,下面将介绍PHP中POST请求的正确用法,并提供具体的代码示例。1.PHP中POST请求的基本原理在PHP中,通过使用$_POST全局变量可以获取通过POST方法提交的数据。POST方法将表单数
