Winapi WM_通知和NM_定制绘图
当NM_CUSTOMDRAW通知代码通过WM_NOTIFY消息发送给控件的父控件时,此WM_NOTIFY消息的lParam参数是NMCUSTOMDRAW结构的地址,如下所示: 另一方面,WM_NOTIFY消息的LPRAM应该是Winapi WM_通知和NM_定制绘图,winapi,Winapi,当NM_CUSTOMDRAW通知代码通过WM_NOTIFY消息发送给控件的父控件时,此WM_NOTIFY消息的lParam参数是NMCUSTOMDRAW结构的地址,如下所示: 另一方面,WM_NOTIFY消息的LPRAM应该是 A pointer to an NMHDR structure that contains the notification code and additional information. For some notification messages, this pa
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){ ....
但问题是,我们不知道这个LPRAM是一个NMHDR结构还是一个NM_CUSTOMDRAW结构一个proior,如何才能正确地转换LPRAM?如果LPRAM只是一个NMHDR,
应该使用LPNMHDR和pnm->code,不是吗
更糟糕的是,不同的控件使用不同类型的结构:NMLVCUSTOMDRAW、NMTVCUSTOMDRAW、NMLVCUTTOMDRAW和NMTBCUSTOMDRAW。那么,在WM_NOTIFY处理程序开始时,正确的方法是什么,将其与NM_CUSTOMDRAW区分开来,并确定正确的NMCUSTOMDRAW结构类型
当我读到这篇文章时 在MSDN上,我无法理解某些部分。比如说, CDRF_NOTIFYPOSTPAINT当整个控件的绘制周期完成时,控件将发送NM_CUSTOMDRAW通知。当dwDrawStage等于CDDS_PREPAINT时会发生此情况。 当一个控件在整个控件的绘制周期完成时发送NM_CUSTOMDRAW通知时,此NM_CUSTOMDRAW应该具有dwDrawState等于CDDS_PREPOSTPAINT,不是吗
有人能解释一下在那篇MSDN文章中返回值的含义列表中“当……发生这种情况时”是什么意思吗。
lParam
指针同时是NMHDR*
和NMLVCUSTOMDRAW*
。如果查看NMLVCUSTOMDRAW
是如何定义的,您将看到它以NMHDR
成员开头
话虽如此,您可以可靠地将LPARAM
强制转换为您选择的任何对象:NMHDR*
,NMCUSTOMDRAW*
,NMLVCUSTOMDRAW*
。如果通知来自listview,消息本身是WM_NOTIFY
,并且NMHDR::code
等于NM_CUSTOMDRAW
,则三个强制转换中的任何一个都是正确的
将
NMLVCUSTOMDRAW
视为通用NMHDR
的特定于通知的扩展,这很容易。lParam
指针同时是NMHDR*
和NMLVCUSTOMDRAW*
。如果查看NMLVCUSTOMDRAW
是如何定义的,您将看到它以NMHDR
成员开头
话虽如此,您可以可靠地将LPARAM
强制转换为您选择的任何对象:NMHDR*
,NMCUSTOMDRAW*
,NMLVCUSTOMDRAW*
。如果通知来自listview,消息本身是WM_NOTIFY
,并且NMHDR::code
等于NM_CUSTOMDRAW
,则三个强制转换中的任何一个都是正确的
可以将
NMLVCUSTOMDRAW
看作通用NMHDR
的通知特定扩展,Microsoft Windows以普通的旧数据格式构建其结构。因此,如果我定义:
struct A {
int a;
};
struct B {
A a;
int b;
};
struct C {
A a;
int c;
};
内存中B的布局实际上是两个整数,A(一个整数)的全部内容,然后是B(另一个整数)的全部内容。因此,只要我能得到A值,就可以安全地将B视为A,并从A成员中确定我的指针是类型B还是类型C。在您提供的示例中,NMHDR是通用值(A),NMLISTVIEW是特定值(B或C)。测试hdr值(类型为NMHDR)以查看LPRAM是什么类型,并从中将其转换为正确的子类型。对于C和C++窗口开发来说,这是正确的。 < P>微软Windows结构的方式是一种普通的旧数据格式。因此,如果我定义:
struct A {
int a;
};
struct B {
A a;
int b;
};
struct C {
A a;
int c;
};
内存中B的布局实际上是两个整数,A(一个整数)的全部内容,然后是B(另一个整数)的全部内容。因此,只要我能得到A值,就可以安全地将B视为A,并从A成员中确定我的指针是类型B还是类型C。在您提供的示例中,NMHDR是通用值(A),NMLISTVIEW是特定值(B或C)。测试hdr值(类型为NMHDR)以查看LPRAM是什么类型,并从中将其转换为正确的子类型。对于C和C++窗口开发来说,这是正确的。< / P>你是对的,我只是没意识到。但是如果控件是TreeView,我想使用TreeView,并且在WM_NOTIFY中,我将lParam转换为LPNMLVCUSTOMDRAW,虽然这并不重要,但在我看来它看起来并不好。你可以单独转换,不会带来任何麻烦。一旦您铸造,您就会看到控件标识符是treeview的标识符,并且不再使用这种铸造错误的结构。好或坏-这是如何通知工作,并开始工作多年前。当时,让它简单而不臃肿是非常重要的。@user565739:通常,您首先将
lParam
强制转换为NMHDR*
,这样您就可以检查它的code
成员,然后根据需要将lParam
重新强制转换为更合适的NM…*
类型。您是对的,我只是没有意识到。但是如果控件是TreeView,我想使用TreeView,并且在WM_NOTIFY中,我将lParam转换为LPNMLVCUSTOMDRAW,虽然这并不重要,但在我看来它看起来并不好。你可以单独转换,不会带来任何麻烦。一旦您铸造,您就会看到控件标识符是treeview的标识符,并且不再使用这种铸造错误的结构。好或坏-这是如何通知工作,并开始工作多年前。在那个时候,让它简单而不臃肿是非常重要的。@user565739:通常,您会首先将lParam
强制转换为NMHDR*
,以便检查它的代码