可编辑子项的CListCtrl类

浅谈mfc子类化 一、引入子类化概念的原因: 如果你对CEdit控件有这样的需求:只允许用户输入数字或是字幕!你会怎么做? 1. 你可以二话不说的重写这个类。 2. 在CEdit控件的父窗口中的PreTranslateMessage中拦截这个控件的输入。 两个方法都能实现这个需求,但方法1太过于费时费力。在这里,方法二看似可以完美的解决这个问题。 但是某些情况下,消息不经过消息队列(sendMessage 阅读详情


转自:http://www.vckbase.com/index.php/wv/1548


  • 文章概要:
  • 本文对CListCtrl控件进行了一个扩展,使它即可以编辑主项(Item),又可以编辑子项(SubItem),并尽量符合CListCtrl的操作习惯。
  • 一、说明

    大家都知道在MFC中通过给CListCtrl设置LVS_EDITLABELS属性,并且在程序中响应控件的LVN_ENDLABELEDIT消息可以修改列表控件每一行的第一项,也就是主项(Item)。代码如下:

    1.void CEditListCtrlSampleDlg::OnEndlabeleditList1(NMHDR* pNMHDR, LRESULT* pResult)
    2.{
    3.LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
    4.// TODO: Add your control notification handler code here
    5. 
    6.*pResult = TRUE;   //TRUE值表示可以修改主项,FALSE值表示不修改主项
    7.}

    但是让人郁闷的是,微软留了一手,CListCtrl不支持直接修改子项(SubItem)。无奈之下只好自力更生,对CListCtrl进行扩展。>_

    二、原理

    通过在浩如烟海的互联网上查找资料(当然包括了大名鼎鼎的VCKBASE),发现现有的实现大都是对子项鼠标单击一次就可以编辑。但本人对CListCtrl的单击一次高亮文本,再单击一次才开始编辑的操作模式感觉比较喜欢,所以就有了这篇文章的诞生。
    要想实现高亮文本也就是对文本进行着色处理,这可以通过对NM_CUSTOMDRAW消息进行处理实现,但是类向导中没有这个消息映射只能进行手工添加。

    要想编辑文本则可以通过EditLabel(int nItem)成员函数以及对LVN_BEGINLABELEDIT和LVN_ENDLABELEDIT的消息处理实现。

    三、实现

    本文最终实现的CEditListCtrl扩展类在尽量符合CListCtrl操作步骤的情况下实现对主项及子项的可编辑。

    成员变量说明:

    1.int m_iItem; //主项标识符
    2.int m_iSubItem; //子项标识符
    3.BOOL m_bFocus; //是否绘制项文本焦点框
    4.BOOL m_bHighLight; //是否高亮项文本
    5.CItemEdit m_edtItemEdit; //用于子类化EditLabel函数返回的CEdit*指针

    列表控件中所有项文本的绘制以及特效(焦点框、高亮)都在NM_CUSTOMDRAW消息处理中实现:

    01.void CEditListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
    02.{
    03.NMLVCUSTOMDRAW* pNMLVCustomDraw = (NMLVCUSTOMDRAW*)pNMHDR;
    04. 
    05.// Take the default processing unless we set this to something else below.
    06.*pResult = CDRF_DODEFAULT;
    07. 
    08.// First thing - check the draw stage. If it's the control's prepaint
    09.// stage, then tell Windows we want messages for every item.
    10. 
    11.if (pNMLVCustomDraw->nmcd.dwDrawStage == CDDS_PREPAINT)
    12.{
    13.*pResult = CDRF_NOTIFYITEMDRAW;
    14.}
    15.else if (pNMLVCustomDraw->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
    16.{
    17.// This is the notification message for an item.  We'll request
    18.// notifications before each subitem's prepaint stage.
    19.*pResult = CDRF_NOTIFYSUBITEMDRAW;
    20.}
    21.else if (pNMLVCustomDraw->nmcd.dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM))
    22.{
    23.//当前要绘制的主项标识符和子项标识符
    24.int iItem = (int)pNMLVCustomDraw->nmcd.dwItemSpec;
    25.int iSubItem = pNMLVCustomDraw->iSubItem;
    26. 
    27.CDC* pDC = CDC::FromHandle(pNMLVCustomDraw->nmcd.hdc);
    28. 
    29.CString strItemText = GetItemText(iItem, iSubItem);
    30.CRect rcItem, rcText;
    31.GetSubItemRect(iItem, iSubItem, LVIR_LABEL, rcItem);
    32.rcText = rcItem;
    33. 
    34.CSize size = pDC->GetTextExtent(strItemText);
    35.if(strItemText == _T(""))
    36.{
    37.size.cx = 41;
    38.}
    39. 
    40.//设置文本高亮矩形
    41.rcText.left += 4;
    42.rcText.right = rcText.left + size.cx + 6;
    43.if(rcText.right > rcItem.right)
    44.{
    45.rcText.right = rcItem.right;
    46.}
    47. 
    48.COLORREF crOldTextColor = pDC->GetTextColor();
    49. 
    50.//绘制项焦点/高亮效果
    51.if(m_bFocus)
    52.{
    53.if((m_iItem == iItem) && (m_iSubItem == iSubItem))
    54.{  
    55.if(m_bHighLight)
    56.{                  
    57.pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
    58.pDC->FillSolidRect(&rcText, ::GetSysColor(COLOR_HIGHLIGHT));
    59.}
    60.pDC->DrawFocusRect(&rcText);
    61.}      
    62.}
    63. 
    64.//绘制项文本
    65.rcItem.left += 6;
    66.pDC->DrawText(strItemText, &rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOCLIP);
    67. 
    68.pDC->SetTextColor(crOldTextColor);
    69.*pResult = CDRF_SKIPDEFAULT;// We've painted everything.
    70.}  
    71.}

    单击一次文本高亮,再单击一次文本开始编辑在WM_LBUTTONDOWN消息处理中实现:

    01.void CEditListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
    02.{
    03.m_bFocus = TRUE;
    04.LVHITTESTINFO  lvhit;
    05.lvhit.pt = point;
    06.int item = SubItemHitTest(&lvhit);
    07. 
    08.//if (over a item/subitem)
    09.if (item != -1 && (lvhit.flags & LVHT_ONITEM))
    10.{
    11.CListCtrl::OnLButtonDown(nFlags, point);
    12. 
    13.if(m_bHighLight && m_iItem == lvhit.iItem && m_iSubItem == lvhit.iSubItem)
    14.{
    15.//第二次单击
    16.EditLabel(m_iItem);
    17.return;
    18.}
    19.else
    20.{
    21.//第一次单击
    22.m_iItem = lvhit.iItem;
    23.m_iSubItem = lvhit.iSubItem;
    24.m_bHighLight = TRUE;
    25.}
    26.}
    27.else
    28.{
    29.if(m_edtItemEdit.m_hWnd == NULL)
    30.{
    31.//未出现文本编辑框时
    32.m_bHighLight = FALSE;
    33.}
    34. 
    35.CListCtrl::OnLButtonDown(nFlags, point);
    36.}
    37. 
    38.Invalidate(); //强制重绘控件
    39.}

    关键的一步,对项文本进行编辑。在以上代码中当执行到EditLabel时将会产生一个编辑框,这时需要将它进行子类化处理,以控制它出现的位置。

    01.void CEditListCtrl::OnBeginlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
    02.{
    03.LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
    04. 
    05.if (m_iSubItem >= 0)
    06.{
    07.ASSERT(m_iItem == pDispInfo->item.iItem);
    08.CRect  rcSubItem;
    09.GetSubItemRect( pDispInfo->item.iItem, m_iSubItem, LVIR_BOUNDS, rcSubItem);
    10. 
    11.//get edit control and subclass
    12.HWND hWnd= (HWND)SendMessage(LVM_GETEDITCONTROL);
    13.ASSERT(hWnd != NULL);
    14.VERIFY(m_edtItemEdit.SubclassWindow(hWnd));
    15. 
    16.//move edit control text 4 pixel to the right of org label,
    17.//as Windows does it...编辑框定位
    18.m_edtItemEdit.m_iXPos = rcSubItem.left + 4;
    19.m_edtItemEdit.SetWindowText(GetItemText(pDispInfo->item.iItem, m_iSubItem));
    20.}
    21. 
    22.*pResult = 0;
    23.}
    24. 
    25.void CEditListCtrl::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
    26.{
    27.LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
    28.LV_ITEM *plvItem = &pDispInfo->item;
    29. 
    30.if (m_iSubItem >= 0)
    31.{
    32.if (plvItem->pszText != NULL )
    33.{
    34.SetItemText(plvItem->iItem,m_iSubItem, plvItem->pszText);
    35.}
    36. 
    37.VERIFY(m_edtItemEdit.UnsubclassWindow()!=NULL);
    38.*pResult = 0;
    39.}
    40. 
    41.//编辑文本时对控件父窗口操作(如单击其它控件)引发"OnEndlabeledit"时刷新控件
    42.CRect rect;
    43.GetWindowRect(&rect);
    44.CPoint point;
    45.::GetCursorPos(&point);
    46.if(!rect.PtInRect(point))
    47.{
    48.m_iItem = -1;
    49.m_iSubItem = -1;
    50.m_bFocus = FALSE;
    51.m_bHighLight = FALSE;
    52.}
    53.}

    通过以上三个步骤大体实现了本文要达到的目的,但是还不能放松。接下来还要进行一些显示细节方面的处理。这包括对WM_PAINT、WM_SETFOCUS和WM_KILLFOCUS消息的处理,限于篇幅,就不进行细讲了,有兴趣的朋友可以查看本文提供的源代码。最后实现的效果如下图所示:

    四、参考资料

    1. Simplified Subitem Editing

    http://www.codeguru.com/cpp/controls/listview/editingitemsandsubitem/article.php/c4175/

    2. 可设置单元格颜色的ClistCtrl类

    http://www.vckbase.com/document/viewdoc/?id=891


Windows编程实践:父子窗口数据通信与CListCtrl高级应用 本文还有配套的精品资源,点击获取 简介:本课程详细介绍了Windows编程中的三个关键技能点:CListCtrl控件的高级应用,包括隔行变色的技巧;模态和非模态对话框的使用;以及父子窗口间的数据传递方法。通过实际的代码示例,学习如何设计用户友好的界面,处理窗口间的数据交互,以及提高应用程序的交互性和用户体验。 1. CListCtrl控件高级应用 在 Win... 阅读详情

相关推荐

可编辑子项的ListCtrl (ComboBox与EditBox)

可编辑子项的ListCtrl (ComboBox与EditBox)

可编辑子项的ListCtrl

MFC提供的ListCtrl控件本身是不具备编辑子项功能的。 本文实现可以在ListCtrl中双击项Item出现编辑框和下拉列表框的编辑功能。 如下图所示:源代码下载 示例程序下载源代码中包含六个以下文件: 1. EditableListCtrl.h 2. EditableListCtrl.cpp 3. ListCtrlEdit.h 4. ListCtrlEdit.cpp 5. Li

Hisin Wang的专栏 3389

控件子类化的消息处理

控件子类化以后,只能处理标准的wm消息,对通过资源ID向父窗口的消息不能处理。 附录:孙皓等编著的《visual c++ 范例大全》的实例62有误。

可编辑的CListCtrl

<br /><br />一、引言<br />     列表控件主要用来以各种方式显示一组数据记录供用户进行各种操作,是最常见的控件之一。WindowsXP资源管理器中的“查看”菜单下的 “图标|平铺|列表|详细信息”就是一个非常典型的应用。MFC中的CListCtrl类提供了对列表控件操作的基本方法,包括插入一个新的项目InsertItem、删除一个项目DeleteItem、排序项目SortItems等,但CListCtrl类不支持对项目的直接编辑,只能用SetItem或者SetItemText来输入数据

mythic_y的专栏 6107

《供应链金融风控模型设计:多维度数据整合与动态风险预警机制》

注:方案突出供应链金融「三流合一」(资金流、物流、信息流)的风控逻辑,通过多维度数据整合与动态预警,解决传统风控中中小企业信用评估难、链条风险传导监测滞后的问题。◦ 构建供应链拓扑图,计算「核心企业违约对上下游企业的影响系数」(如某电子厂商违约时,其前五大供应商的风险权重自动提升40%)• 区块链应用:将核心企业应付账款上链存证,防止「一票多融」欺诈(如某供应商用同一应收账款在多家银行融资)◦ 财务数据:核心企业审计报告、上下游企业纳税数据(增值税发票频次/金额)

2501_91651383的博客 1549

【毕业设计】QT实战:从零构建仿QQ通讯系统,打造你的简历亮点项目

本文为计算机专业毕业生提供了一份详尽的毕业设计实战指南,教你如何从零开始使用QT框架构建一个仿QQ的即时通讯系统。文章深入剖析了项目规划、核心模块(登录、聊天、好友管理)的实现、TCP粘包处理、数据库设计等关键技术难点,并分享了如何将此项目打造成简历亮点,有效提升求职竞争力。

omega的博客 443

[转]可编辑子项的CListCtrl类

Technorati 标签: VC,ListCtrl 原文地址:http://www.vckbase.com/document/viewdoc/?id=1853 可编辑子项的CListCtrl类 作者:Nobita 下载源代码 关键词:可编辑子项 CListCtrl 摘 要:本文对CListCtrl控件进行了一个扩展,使它即可以编辑主项(Item),又可以编辑子

jiaolongdy的专栏 1013

PaddleOCR转ONNX模型实战:5分钟搞定中文OCR推理部署(附完整代码)

本文详细介绍了将PaddleOCR模型转换为ONNX格式并进行高效推理部署的完整实战方案。通过Paddle2ONNX工具实现模型转换,利用ONNX Runtime构建跨平台推理引擎,涵盖环境配置、模型优化、批量处理及多平台部署等关键步骤,显著提升中文OCR在边缘设备上的推理性能。

weixin_29051811的博客 617

可编辑子项的CListCtrl类(失去焦点时,CEdit消息被屏蔽的问题)

from: 可编辑子项的CListCtrl类 http://www.vckbase.com/index.php/wv/1548.html 同时实现:MFC实现CListCtrl子项可编辑的简便操作   code: http://u.download.youkuaiyun.com/upload/success

lys07962000的专栏 809

phaser3适配微信小游戏

phaser3适配微信小游戏

SilenzioX的博客 1803

从想法到零件:手把手拆解一个汽车功能如何从PRD写到SSTS和CTS

本文详细拆解了汽车电子需求从市场文档(MRD)到零部件技术规范(CTS)的完整流程,以雨天自动关窗功能为例,展示了PRD、SSTS和CTS的编写要点与交互设计。文章重点解析了系统分解的艺术和零部件落地的精确参数要求,为汽车电子工程师提供了从概念到实现的全流程实践指南。

weixin_30300225的博客 481

使CListCtrl可编辑

<br />CListCtrl 是一个经常使用的控件,通常用来显示数据库的内容。但是,CListCtrl并不好用。我们当然希望CListCtrl能像Excel那样好用,因此,得在原来的基础上进行改进。<br />一、使CListCtrl能够编辑子项<br />1、在对话框中添加一个CListCtrl控件,并添加CListCtrl类型的变量m_list。<br />2、初始化控件<br />设置控件风格(照抄网上的)<br />LONG lStyle;<br />lStyle = GetWindowLong(

spinaches的专栏 1407

Matlab图像处理频域滤波实现——高斯低通、高通、带通带阻滤波器

如果你想要进一步了解更多的相关知识,

小嘤熊的博客 1万+

MFC实现CListCtrl子项可编辑的简便操作

相信很多人用过MFC的新手都知道,MFC虽然封装了一些常用的控件,但不少控件真正使用起来,与个人的要求可能会有一些差别,总有一些功能不是很方便就能实现的,例如CTabCtrl(Tab控件)的颜色(涉及到自绘、头大)/CListCtrl的子项编辑。       这两天用列表控件做东西,需要编辑列表控件的子项,尝试了一通MFC提供的功能,觉得不是很好用,我需要的是报表风格的列表控件,估计不少人都知道

公子轩的专栏 8080

向量数据库:PGVector

PGVector 是一个基于 PostgreSQL 的扩展插件,为用户提供了一套强大的向量存储和查询的功能

m0_37559973的博客 1万+

PCL RANSAC拟合直线并插值

空间直线线性插值的原理与实现方法。

点云侠的博客 136
上一篇: C/C++:遍历子目录,枚举文件,FindFirstFile + FindNextFile
下一篇: MFC 显示位图
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值