当NM_CUSTOMDRAW通知代码由WM_NOTIFY消息发送到控件的父级时,此WM_NOTIFY消息的lParam参数是NMCUSTOMDRAW结构的地址,如下所示:
http://msdn.microsoft.com/en-us/library/windows/desktop/ff919569(v=vs.85).aspx
另一方面,WM_NOTIFY消息的lParam应为
A pointer to an NMHDR structure that contains the notification code and additional
information. For some notification messages, this parameter points to a larger
structure that has the NMHDR structure as its first member.
在许多代码示例中,对于WM_NOTIFY消息的处理程序,我看到
LPNMLISTVIEW pnm = (LPNMLISTVIEW)lParam;
switch (pnm->hdr.code){ ....
但问题是,我们不知道这个lParam是NMHDR结构还是NM_CUSTOMDRAW结构,如何正确地投射lParam?如果lParam只是一个NMHDR, 一个人应该使用LPNMHDR和pnm->代码,不是吗?
更糟糕的是,不同的控件使用不同类型的结构:NMLVCUSTOMDRAW,NMTVCUSTOMDRAW,NMLVCUTTOMDRAW和NMTBCUSTOMDRAW。那么在WM_NOTIFY处理程序的开头做什么是正确的方法,区分它是否与NM_CUSTOMDRAW区分开来,并确定正确的NMCUSTOMDRAW结构类型。
当我阅读文章时
http://msdn.microsoft.com/en-us/library/windows/desktop/ff919569%28v=vs.85%29.aspx
在MSDN上,我无法理解某些部分。例如,
CDRF_NOTIFYPOSTPAINT当整个控件的绘制周期完成时,控件将发送NM_CUSTOMDRAW通知。当dwDrawStage等于CDDS_PREPAINT时会发生这种情况。
当控件在整个控件的绘制周期完成时发送NM_CUSTOMDRAW通知时,此NM_CUSTOMDRAW应该有dwDrawState等于CDDS_PREPOSTPAINT,不是吗?
有人可以解释什么"这发生在...."在该MSDN文章中返回值的含义列表中。
答案 0 :(得分:2)
很容易。 lParam
指针同时指向NMHDR*
和NMLVCUSTOMDRAW*
。如果您查看NMLVCUSTOMDRAW
的定义方式,您会看到它以NMHDR
成员开头。
话说回来,您可以可靠地将LPARAM
投射到您选择的任何地方:NMHDR*
,NMCUSTOMDRAW*
,NMLVCUSTOMDRAW*
。如果通知来自listview,则邮件本身为WM_NOTIFY
且NMHDR::code
等于NM_CUSTOMDRAW
,则三个演员中的任何一个都将是正确的。
将NMLVCUSTOMDRAW
视为通用NMHDR
的通知特定扩展。
答案 1 :(得分:2)
Microsoft Windows构建它的结构的方式是普通的旧数据格式。因此,如果我定义:
struct A {
int a;
};
struct B {
A a;
int b;
};
struct C {
A a;
int c;
};
内存中B的布局实际上是两个整数,A(整数)的全部内容则是B的整个内容(另一个整数)。因此,只要我能获得一个值,就可以安全地将B视为A,并且从一个成员中确定我的指针是否真的是B类型或C类型。在示例中,您提供的NMHDR是通用值( A)和NMLISTVIEW是特定值(B或C)。您测试hdr值(类型为NMHDR)以查看lParam的类型以及将其转换为正确的子类型。这适用于C和C ++ Windows开发。