在对listctrl的控件进行重载的过程中,GetHeaderCtrl()返回NULL的问题
先谈谈我的问题吧!
在使用listctrl的过程中,我需要在列表头部添加checkbox,实现全选的功能。
经过网上资料的罗列,我找到了一个demo,使用的重绘的方法,在使用的过程中,我发现我的列表头无法绘出checkbox,于是开始找问题,最后发现是因为cheadctlcl这个重载的类里面的函数无法响应,
于是问题一步步逼近,为什么重载函数无法调用?cheadctlcl类的所有函数都无法响应。于是找了下问题,最后发现问题出在:
void CListCtrlEx::PreSubclassWindow()
{
// TODO: 在此添加专用代码和/或调用基类
//__super::PreSubclassWindow();
ModifyStyle(0,LVS_OWNERDRAWFIXED);
CListCtrl::PreSubclassWindow();
ModifyStyle(0,LVS_REPORT|LVS_SHOWSELALWAYS|LVS_SORTDESCENDING );
CHeaderCtrl *pHeader = this->GetHeaderCtrl();
m_Header.SubclassWindow(pHeader->GetSafeHwnd());
}
调试发现,GetHeaderCtrl()调用返回老是为空。
于是就到网上找资料,找到下面这篇文章!!!
//////////////////////////////////////// 引用:http://wangqingyun84.blog.163.com/blog/static/7908361720119744913240////////////////////////////////////////////////
如果要自定义CListCtrl控件的表头, 比如最常用的双行显示文字, 或者要显示一些图片什么的, 最常用的方法就是自定义一个CHeaderCtrl类, 然后子类化. 步骤如下:
1. 先自定义一个CHeaderCtrl类的子类, 比如CHeaderCtrlEx. 接下来有两种方法
其一, 最暴力的方法是重写OnPaint()函数, 也就是给CHeaderCtrlEx添加ON_WM_PAINT()消息处理函数, 但这时所有的东西都要自已来绘制, 也就是整个的表头都要自已来绘制, 甚至包括中间的分隔线. 显然过于激进...
其二, 稍微温和点的方法. 使用HDI_FORMAT这个style. 实际上每当调用InsertColumn()插入一列时, 都可以指定该style, 那么绘制该列时就会调用OnDrawItem()函数, 当然了这是需要使用ON_WM_DRAWITEM()宏的, 在该消息响应函数中就可以自定义的绘制各种东西. 当然了每次绘制都是一个某列的表头. 这可不像CListCtrl的那个LVS_OWNERDRAWFIXED, 那个是一下绘制整个的一个item也就是一行.
2. 其次呢就是要子类化CListCtrl类的header control, 当然了我都是定义一个CListCtrl的子类, 假设名字叫做CListCtrlEx. 那么我们需要做的就是在该类中定义一个CHeaderCtrEx _headerCtrl, 之后呢选个合适的机会_headerCtrl.SubClassWindow(GetHeaderCtrl()->GetSafeHwnd())就可以了
我们的问题就是: 何时子类化, 也就是调用这条代码...
1. 网上好多地方都说是要在PreSubclassWindow()函数中...
2. 但一baidu这个GetHeaderCtrl(), 大家就有一个永恒的问题了: GetHeaderCtrl()返回值为NULL...
3. 有人说在PreSubclassWindow()中返回NULL, 但是在OnCreate()函数中就OK了...
但实际上好多的都用不同的方法解决了这个问题:
1. 最会逃避的方法就是用资源编辑器添加一个CListCtrl, 然后子类化成CListCtrlEx, 然后无论是在PreSubclassWindow()还是OnCreate()都没有任何的问题...
2. 有人说在PreSubclassWindow()中不行, 要在OnCreate()中才可以...
3. 但动态创建时还会有问题了, 也就是_listCtrl.Create(...), 用这种方法创建的控件, 在PreSubclassWindow()和OnCreate()时都还会有问题
4. 还有人极具创造力, 如,引用如下:
I noticed this too. If the list control is created as part of a dialog
template (for example) then the HWND of the header control exists inside of
the PreSubclassWindow function, whereas if the list control is created
dynamically (with a call to CListCtrl::Create()) then it does not.
I solved the problem by PostMessage'ing a user?defined message to myself
from inside of the PreSubclassWindow function. In the handler for the
user?defined message, the HWND for the header always exists, regardless of
how the list control was created, and I subclass the header from inside this
handler (and not from inside the PreSubclassWindow function).
I think it works because the user?defined message is posted at the end of
the message queue and is therefore handled at a later time, when everything
has "settled down" and both the list control and its header both have been
created.
也就是说, 这是在PreSubclassWindow()函数中没有直接调用GetHeaderCtrl(), 而是朝自己发了一个自定义消息, 然后添加该消息处理函数, 在收到该消息时再调用GetHeaderCtrl(), 这时"一般"都没有问题.
那么问题的关键是怎么呢???
很简单: 就是GetHeaderCtrl()只有在LVS_REPORT时才会返回表头对象, 其它style时肯定会返回空.
之所以在资源编辑器中静态的拖进去控件不会有问题, 可能是因为拖进去控件时就已经设置其style为LVS_REPORT, 通过实验可以发现, 如果不是LVS_REPORT时, 那么在PreSubclassWindow()函数中GetHeaderCtrl()依然会返回NULL.
唯一让人迷惑不解的是, 静态添加时, 如果不指定其style为LVS_REPORT, 那么虽然PreSubclassWindow()中是不可能的, 但OnCreate()中却一直GetHeaderCtrl()可能正常工作, 故, 不解...
所以, 解决方法为:
1. 通过静态的资源编辑器来添加控件, 那么如果是指定了LVS_REPORT时, 那么无论是在PreSubclassWindow()还是OnCreate()均没有问题, GetHeaderCtrl()都好使.
2. 通过静态的资源编辑器来添加控件, 那么如果没有指定LVS_REPORT, 则只能在OnCreate()中使用GetHeaderCtrl(), 在PreSubclassWindow()中是不可以的.
3. 最好的方法是, 在_listCtrl.Create()中务必要指定LVS_REPORT, 那么在调用了基类的CListCtrl::OnCreate()后, GetHeaderCtrl()必然可以工作...
或者更好一点, 就是在GetHeaderCtrl()之前, 先修改一下: ModifyStyle(0, LVS_REPORT), 这样最有把握..., 但是啊, 这种方法在PreSubclassWindow()中不是特别好用, 因为PreSubclassWindow()是在OnCreate()调用之前使用, 此时控件还不存在, 所以不好用
////////////////////////////////////////////////////////////////////////////////////////////////
最后的解决方法,是对clistctrlex类中重载OnCreate函数,在OnCreate函数中实现子类化就实现了功能。
在对listctrl的控件进行重载的过程中,GetHeaderCtrl()返回NULL的问题的更多相关文章
- 如何使用免费PDF控件从PDF文档中提取文本和图片
如何使用免费PDF控件从PDF文档中提取文本和图片 概要 现在手头的项目有一个需求是从PDF文档中提取文本和图片,我以前也使用过像iTextSharp, PDFBox 这些免费的PD ...
- 因为此控件已在 web.config 中注册并且与该页位于同一个目录中
在web.config文件配置了用户控件 <pages> <controls> <add tagPrefix="my" tagName="l ...
- 《ASP.NET1200例》解决母版页报错“内容控件必须是内容页中的顶级控件,或是引用母版页的嵌套母版页。”
VS2005下,添加了母版页这个控件,我们可以讲N个页面中共同的部分放在母版页来实现,并让WEB窗体集成自我们的母版页,就可以让我们的站点具有统一的风格了.在VS2005SP1之前的版本中,我们只能创 ...
- VS2010 Chart控件(一)Chart控件在ASP.NET网站中的应用示例详解(C#语言)
步骤如下: 1. Chart控件(一)Chart控件在ASP.NET网站中的应用示例详解(C#语言)" title="VS2010 Chart控件(一)Chart控件在ASP.NE ...
- 玩转控件:重绘DEVEXPRESS中DateEdit控件 —— 让DateEdit支持只选择年月 (提供源码下载)
前言 上一篇博文<玩转控件:重绘ComboBox —— 让ComboBox多列显示>中,根据大家的回馈,ComboBox已经支持筛选了,更新见博文最后最后最后面. 奇葩 这两天遇到 ...
- MFC中给控件添加变量,DoDataExchange中
DoDataExchange函数其实是一项数据动态绑定技术.比如你在写动态按钮过程中须对按钮添加变量时,怎么添加?控件类已经写好了,其变量是已经固定的.你要添加新的变量就要用到DoDataExchan ...
- 列表控件ListBox关联的MFC中的类:CListBox
列表控件ListBox关联的MFC中的类:CListBox ######################################################## 1.在列表的结尾添加一项: ...
- WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探
原文:WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探 最近因为项目需要,开始学习如何使用WPF开发桌面程序.使用WPF一段时间之后,感 ...
- qt 在ui界面添加控件后在cpp文件中无法调用?
问题:qt 在ui界面添加控件后在cpp文件中无法调用? 解决方法:在build选项中选择“重新build项目”,再次在cpp中调用添加的控件发现可以调用了. 还有一种情况导致添加控件后无法调用,就是 ...
随机推荐
- sureface 屏幕残影问题官方解决方案 - 卸载显卡驱动
您进入桌面,左下角微软图标(单击右键),选择设备管理器,点开“显示适配器”前面的小三角,找到“Intel(r) hd gRAPHICS 520”, 单击右键卸载,卸载的时候不要勾选“删除此设备的驱动软 ...
- python标准库介绍——24 traceback 模块详解
==traceback 模块== [Example 2-18 #eg-2-18] 展示了 ``traceback`` 模块允许你在程序里打印异常的跟踪返回 (Traceback)信息, 类似未捕获异常 ...
- 分享一:关于mysql中避免重复插入记录方法
一: INSERT ON DUPLICATE KEY UPDATE 如果您指定了ON DUPLICATE KEY UPDATE,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重 ...
- 【JUnit4.10源码分析】5.2 Rule
标注@Rule TestRule是一个工厂方法模式中的Creator角色--声明工厂方法. package org.junit.rules; import org.junit.runner.Descr ...
- JAX-RS(REST Web Services)2.0 can not be installed: One or more constraints have not been satisfied
eclipse出错: JAX-RS(REST Web Services)2.0 can not be installed: One or more constraints have not been ...
- 【Android】8.4 让主题自适应不同的Android版本
分类:C#.Android.VS2015: 创建日期:2016-02-17 一.简介 默认情况下,高版本提供的主题不能在低版本的Android系统上运行.但是,通过自定义主题,可以让你的系统自适应各自 ...
- [phpcms v9]自定义表单添加验证码验证功能
修改 \phpcms\templates\default\formguide\show.html 中添加验证码显示 <input type="text" id=" ...
- 日期时间函数(1)-time()&gmtime()&strftime()&localtime()
◆time() 取得当前时间.此函数会返回从公元1970年1月1日的UTC时间从0时0分0秒算起到现在所经过的秒数.如果参数t为非空指针的话, 此函数也会将返回值存到t指针所指的内存. 成功则返回秒数 ...
- angular学习笔记(六)-非入侵式javascript
这篇主要讲解非入侵式javascript. 在传统的前端开发中,把js写在html中,称为入侵式的javascript: <span id="select_area" onc ...
- jQuery-File-Upload文件上传
http://blueimp.github.io/jQuery-File-Upload/index.html