WM_COMMAND 和 WM_NOTIFY 的区别
Posted 牧秦丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WM_COMMAND 和 WM_NOTIFY 的区别相关的知识,希望对你有一定的参考价值。
当我们按下一个菜单选项,或者一个控件需要通知父窗口一个事件发生(如鼠标单击、双击等),或者快捷键被按下时,Windows将会发送一个 WM_COMMAND 消息给父窗口。那么 WM_COMMAND 消息参数是什么呢?
WM_COMMAND 消息来源 | WPARAM 高位 | WPARAM 低位 | LPARAM |
---|---|---|---|
菜单 | 0 | 菜单 ID | 0 |
快捷键 | 1 | 快捷键对应菜单 ID | 0 |
控件 | 响应 Code(如BN_CLICKED) | 控件 ID | 控件句柄 |
OK,一切运行的很好,通过 WPARAM 高位置 1或 0区分菜单、快捷键、或者控件事件 Code,通过 WPARAM 低位可以知道发出 WM_COMMAND消息的菜单项或控件 ID,通过 LPARAM知道控件句柄。
然而,有一天,当选中一个 ListControl 控件中的某一行时,人们忽然发现父窗口需要知道被选中该行的索引,这下为难了,对于控件来看,整个WM_COMMAND消息的WPARAM、LPARAM 都被塞的满满的。怎么办呢?这儿有一种解决办法:新增一个消息,就叫WM_LIST_CONTROL_CLICKED吧,如下:
消息类型 | WPARAM 高位 | WPARAM 低位 | LPARAM |
---|---|---|---|
WM_LIST_CONTROL_CLICKED | 被选中行的索引 | ListControl 控件的 ID | ListControl 控件的句柄 |
呃,看起来的确解决了问题,我们把事件 Code 通过消息 ID 体现了出来,然后把被选中行的索引塞进了WPARAM的高位,看起来非常完美!然而又有一天,人们发现对ListView,父窗口需要知道单击该控件时选中的行号和列号,以便处理,照猫画虎,我们又加了一个WM_LIST_VIEW_CLICKED。接着人们发现其他一些控件都需要这样的改进,如果这样增加消息的话,岂不是没完没了了?!!
于是,WM_NOTIFY消息横空出世:
消息类型 | WPARAM | LPARAM |
---|---|---|
WM_NOTIFY | 发生 WM_NOTIFY 消息的控件 ID | NMHDR 指针 |
现在,我们将所有附加信息都存放在 NMHDR( Notify Message Handler)的一个结构体中,该结构体指针通过 LPARAM 通知到父窗口。 NMHDR如下:
typedef struct tagNMHDR
HWND hwndFrom; // 控件句柄.
UINT_PTR idFrom; // 控件 ID.
UINT code; // NM_ code.
NMHDR;
这只是一个一般的结构,如果我们需要知道
ListView选中的行和列,那么需要:
typedef struct tagNMLISTVIEW
NMHDR hdr; // NMHDR.
int iItem; // 行号.
int iSubItem; // 列号.
UINT uNewState;
UINT uOldState;
UINT uChanged;
POINT ptAction;
LPARAM lParam;
NMLISTVIEW, *LPNMLISTVIEW;
像其他的控件,都会对应这样一个结构体,它们的第一个字段一定是
NMHDR。但一些微软标准控件并不会发送
WM_NOTIFY 消息,这些控件有:
Edit、
ComboBox、
ListBox、
Button、
ScrollBar、
Static等。所以在使用过程中请注意用法,最好的做法是参考
MSDN。
以上是关于WM_COMMAND 和 WM_NOTIFY 的区别的主要内容,如果未能解决你的问题,请参考以下文章
子类化SHBrowseForFolder并处理WM_NOTIFY
WinAPI 中的菜单:我对 WM_COMMAND 使用 LPARAM 还是 WPARAM?
在 WM_COMMAND win32 GUI C++ 中处理 WM_LBUTTONDOWN 和 WM_LBUTTONUP