TN061:ON_NOTIFY和WM_NOTIFY消息
备注
以下技术声明,则它在联机文档,首先包括了不更新。因此,某些过程和主题可能已过时或不正确。有关最新信息,建议您搜索议题在联机文档的索引。
此技术说明在新 WM_NOTIFY 消息在您的 MFC 应用程序提供背景信息并描述进程 WM_NOTIFY 消息建议的 (最常用方式。)
在 windows 3.x 的通知消息
中那样,控件通过发送信息通知用户的活动的父级 (如鼠标单击)、更改在目录中并选择控件背景绘制到父级。 简单的通知发送为特定 WM_COMMAND 消息,与通知代码 (例如 BN_CLICKED) 和控件 ID 打包到 wParam 和在 lParam控件的句柄。 从 wParam 请注意,和 lParam 已满,则无法通过所有其他数据 —这些消息只简单的通知。 例如,在中,单击按钮时,在 BN_CLICKED 通知,无法将关于鼠标光标位置的信息。
在 windows 3.x 的控件需要发送包含其他数据的信息通知时,它们使用多种专用消息,包括 WM_CTLCOLOR, WM_VSCROLL, WM_HSCROLL, WM_DRAWITEM, WM_MEASUREITEM, WM_COMPAREITEM, WM_DELETEITEM, WM_CHARTOITEM, WM_VKEYTOITEM,依此类推。 这些消息可反映回发送自己的控件。 有关更多信息,请参见 TN062:windows 控件的消息反映。
在 Win32 中的通知消息
于 Windows 3.1 的控件,的大多数 Win32 API 使用用于 windows 3.x. 通知消息。 但是, Win32 还将许多复杂,复杂控件向 windows 支持的一些 3.x。 通常,这些控件需要发送与其通知消息的其他数据。 而不是将需要其他数据的每个新的通知的新 WM_* 消息, Win32 API 的设计器选择添加消息, WM_NOTIFY,可以通过任意数量的附加数据的标准化方式。
WM_NOTIFY 消息。 wParam 包含发送消息和指针的控件的 ID 为结构在 lParam。 此结构是 NMHDR 结构或具有 NMHDR 结构作为其第一个成员的一些更大的结构。 请注意,由于 NMHDR 成员是第一个,该结构的指针可用作指向 NMHDR 的指针或为更大的结构的指针具体取决于如何转换它。
在大多数情况下,指针将指向更大的结构,需要转换,而则可以使用。 仅在几个通知,例如通用名称从 **NM_**开头) 的通知 (和工具提示控件的 TTN_SHOW 和 TTN_POP 请注意,是实际使用的 NMHDR 结构。
这个 NMHDR 结构或初始成员包含发送消息和通知代码的控件句柄和 ID (例如 TTN_SHOW)。 NMHDR 结构的格式如下所示:
typedef struct tagNMHDR {
HWND hwndFrom;
UINT idFrom;
UINT code;
} NMHDR;
对于 TTN_SHOW 消息, code 成员将设置为 TTN_SHOW。
大多数通知通过指向包含 NMHDR 结构作为其第一个成员的更大的结构。 例如,请考虑 framework 使用列表视图控件的 LVN_KEYDOWN 通知信息,发送键,以为按下列表视图控件时。 指针指向 LV_KEYDOWN 结构,定义如下所示:
typedef struct tagLV_KEYDOWN {
NMHDR hdr;
WORD wVKey;
UINT flags;
} LV_KEYDOWN;
请注意,由于 NMHDR 成员是第一个此结构,可以在通知消息传递的指针可以被转换到 " NMHDR 的指针或为 LV_KEYDOWN的指针。
通知共有的所有新的 windows 控件
某些通知对所有共有的新 windows 控件。 这些通知通过指向 NMHDR 结构。
通知代码 |
发送,因为 |
---|---|
NM_CLICK |
用户在控件中单击的鼠标左键 |
NM_DBLCLK |
用户在控件中双击的鼠标左键 |
NM_RCLICK |
用户在控件中单击鼠标右键的事件 |
NM_RDBLCLK |
用户在控件中双击的鼠标右键 |
NM_RETURN |
,在控件中输入了焦点时,用户按下了 enter 键 |
NM_SETFOCUS |
控件将输入焦点 |
NM_KILLFOCUS |
控件失去输入焦点 |
NM_OUTOFMEMORY |
,因为不可用,足够的内存控件无法完成操作 |
ON_NOTIFY:处理在 MFC 应用程序的 WM_NOTIFY 消息
功能 CWnd::OnNotify 处理通知消息。 其默认实现检查消息映射通知处理程序。 通常,不要重写 OnNotify。 相反,您提供了一个处理程序函数并添加该处理程序的消息映射项添加到您的所有者窗口的类消息映射。
类向导,通过类向导属性表,可以创建 ON_NOTIFY 消息映射项和提供了一个主干处理程序函数。 有关使用类向导的更多信息使此过程更加简单,请参见 映射到功能的消息。
ON_NOTIFY 消息映射宏具有以下语法:
ON_NOTIFY( wNotifyCode, id, memberFxn )
在斜体的参数替换为:
wNotifyCode
通知消息的代码中需要处理,如 LVN_KEYDOWN。id
通知发送控件的子标识符。memberFxn
将调用成员函数,当发送此通知。
必须声明为的成员函数与以下原型:
afx_msg void memberFxn( NMHDR * pNotifyStruct, LRESULT * result );
备注
在斜体的参数:
pNotifyStruct
注意到结构的指针,如上一节中所述。result
对您要设置的结果代码的指针,在返回之前。
示例
若要指定希望成员函数 OnKeydownList1 处理从 ID 是 IDC_LIST1的 CListCtrl 的 LVN_KEYDOWN 消息,则应使用类向导将以下内容添加到您的消息映射:
ON_NOTIFY( LVN_KEYDOWN, IDC_LIST1, OnKeydownList1 )
在上面的示例中,类向导提供的函数是:
void CMessageReflectionDlg::OnKeydownList1(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
// TODO: Add your control notification handler
// code here
*pResult = 0;
}
请注意类向导自动提供适当类型的指针。 通过 pNMHDR 或 pLVKeyDow可以访问通知机制。
ON_NOTIFY_RANGE
如果需要处理的同一 WM_NOTIFY 消息设置控件中,可以使用 ON_NOTIFY_RANGE 而不是 ON_NOTIFY。 例如,您可能具有要执行某些通知消息的同一事件的设置按钮。
当您使用 ON_NOTIFY_RANGE时,指定的子标识符的一个连续范围处理通知消息通过指定范围的开头和结尾子标识符。
类向导不处理 ON_NOTIFY_RANGE;若要使用它,您需要编辑您的消息映射。
ON_NOTIFY_RANGE 的消息映射项和函数原型如下所示:
ON_NOTIFY_RANGE( wNotifyCode, id, idLast, memberFxn )
在斜体的参数替换为:
wNotifyCode
通知消息的代码中需要处理,如 LVN_KEYDOWN。id
在该标识符的连续范围的第一个标识符。idLast
在该标识符的连续范围的最后一个标识符。memberFxn
将调用成员函数,当发送此通知。
必须声明为的成员函数与以下原型:
afx_msg void memberFxn( UINT id, NMHDR * pNotifyStruct, LRESULT * result );
备注
在斜体的参数:
id
发送通知控件的子标识符。pNotifyStruct
注意到结构的指针,如上所述。result
对您要设置的结果代码的指针,在返回之前。
ON_NOTIFY_EX, ON_NOTIFY_EX_RANGE
如果要超过路由处理消息的通知的对象,则可以使用 ON_NOTIFY_EX (或 ON_NOTIFY_EX_RANGE) 而不是 ON_NOTIFY (或 ON_NOTIFY_RANGE)。 在 EX 版本和 normal 版本之间的唯一区别是针对指定的 EX 版本称为的成员函数返回 BOOL 处理消息是否应继续。 返回从该函数的 FALSE 可以处理在多个对象相同的消息。
类向导不处理 ON_NOTIFY_EX 或 ON_NOTIFY_EX_RANGE;如果要使用之一,也需要编辑您的消息映射。
ON_NOTIFY_EX 的消息映射项和函数原型和 ON_NOTIFY_EX_RANGE 如下所示。 参数的含义与非EX 版本。
ON_NOTIFY_EX( nCode, id, memberFxn )
ON_NOTIFY_EX_RANGE( wNotifyCode, id, idLast, memberFxn )
两个原型在上面是相同的:
afx_msg BOOL memberFxn( UINT id, NMHDR * pNotifyStruct, LRESULT * result );
备注
在这两种情况下, id 保存发送通知控件的子标识符。
您的函数必须返回 TRUE ,如果通知消息完全已处理 " 或 FALSE ,如果命令路由的其他对象应有机会处理消息。