WM_NOTIFY和NM_CUSTOMDRAW

时间:2013-01-24 14:38:28

标签: winapi

当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文章中返回值的含义列表中。

2 个答案:

答案 0 :(得分:2)

很容易。 lParam指针同时指向NMHDR*NMLVCUSTOMDRAW*。如果您查看NMLVCUSTOMDRAW的定义方式,您会看到它以NMHDR成员开头。

话说回来,您可以可靠地将LPARAM投射到您选择的任何地方:NMHDR*NMCUSTOMDRAW*NMLVCUSTOMDRAW*。如果通知来自listview,则邮件本身为WM_NOTIFYNMHDR::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开发。