关于WM_COMMAND与WM_NOTIFY
声明:原文来自MSDN 2001 Oct版,原文内涉及的连接由于是脱机连接,所以译文内的连接是本人尽量找自MSDN online)
TN061: ON_NOTIFY and WM_NOTIFY Messages
这个技术文章介绍了关于新WM_NOTIFY消息,还描述了建议使用的一种在你的MFC应用程序中处理WM_NOTIFY消息的方法。
Windows 3.x 的 通告消息
在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: Message Reflection for Windows Controls. (TN062: Windows控件的消息反射)
Win32下的通告消息
对于那些Windows 3.1的控件, Win32 API使用那些曾在Windows3.x有的绝大部分通告消息。However, Win32 also adds a number of sophisticated, complex controls to those supported in Windows 3.x.这些控件经常发送带附加数据的通告消息。设计者们没有为每一个需要附加数据的通告消息增加一个新的WM_*消息,而是只增加了一个消息,WM_NOTIFY,这个消息可以通过一标准化格式传递任意多的额外数据。
WM_NOTIFY消息包括保存发送消息控件ID的wParam和保存一个结构指针的lParam两部分。那个结构可以是一个NMHDR结构或者某些更大点的、以NMHDR结构为第一个成员的结构。这样的话,一个指向该结构的指针可以是NMHDR结构指针,也可以是那个更大点的结构指针,看你怎么转换他了。
在大多数情况下,那个指针会指向更大点的结构,当你用到的时候就需要转换它。 只有几个通告消息,如 common通告消息(名字以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结构作为第一个成员的结构的指针。举个例子,看看list view控件的LVN_KEYDOWN通告消息所使用的结构,在list view控件里键盘按键被按下时发送这个消息。那个指针就指向LV_KEYDOWN结构体,定义如下:
typedef struct tagLV_KEYDOWN {
NMHDR hdr;
WORD wVKey;
UINT flags;
} LV_KEYDOWN;
这样,因为NMHDR是这个结构的第一个成员,那个指针既可以转换为NMHDR型指针也可以转换为LV_KEYDOWN型指针。
(笔者注:标准命名约定,LV_KEYDOWN已经改名为:NMLVKEYDOWN。MSDN Library - October 2001上是这么说的呵呵。)
对新Windows控件通用的通告消息
一些通告消息对所有新的Windows控件来说是通用的,这些通告消息传递一个指向NMHDR结构体的指针。
Notification code | Sent because |
NM_CLICK | 用户在控件内单击鼠标左键 |
NM_DBLCLK | 用户在控件内双击鼠标左键 |
NM_RCLICK | 用户在控件内单击鼠标右键 |
NM_RDBLCLK | 用户在控件内双击鼠标右键 |
NM_RETURN | 用户在控件具有输入焦点的时候按下回车 |
NM_SETFOCUS | 控件获得输入焦点 |
NM_KILLFOCUS | 控件失去输入焦点 |
NM_OUTOFMEMORY | 控件因为没有足够的可用内存而不能完成一项操作 |
ON_NOTIFY: 在MFC应用程序里处理 WM_NOTIFY 消息
函数CWnd::OnNotify处理通告消息。其默认实现是检查通告消息处理函数的消息映射,然后调用。(checks the message map for notification handlers to call.)一般说来,你不用重载OnNotify。你可以写一个处理函数,然后在你自己的窗口类的消息映射表里添加一个该函数的消息映射入口。
ClassWizard,通过ClassWizard属性页或者WizardBar工具条,能够创建ON_NOTIFY消息映射入口,并且给您提供了一个处理函数的框架。更多关于通过ClassWizard使得添加消息映射更容易的信息,请看Visual C++ Programmer's Guide的 Mapping Messages to Functions。
ON_NOTIFY消息映射宏的语法如下:
ON_NOTIFY(wNotifyCode,id,memberFxn)
斜体字的参数被替换为:
wNotifyCode
要被处理的通告消息代码,如 LVN_KEYDOWN。
id
发送通告消息的控件ID。
memberFxn
通告消息发送后被调用的成员函数。
你的成员函数必须按照如下形式声明:
afx_msgvoidmemberFxn(NMHDR*pNotifyStruct,LRESULT*result);
斜体字参数为::
pNotifyStruct
指向通告消息结构的指针,类型如上声明。
result
指向函数返回之前要被设置结果值的变量指针。
代码实例
现指定你要成员函数OnKeydownList1函去处理ID为IDC_LIST1的CListCtrl控件的LVN_KEYDOWN消息,你可以通过ClassWizard把下面的内容加入到你的消息映射表里:
ON_NOTIFY( LVN_KEYDOWN, IDC_LIST1, OnKeydownList1 )
在上面的例子里,ClassWizard提供的函数是:
void CMessageReflectionDlg::OnKeydownList1(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN* pLVKeyDow = (LV_KEYDOWN*)pNMHDR;
// TODO: Add your control notification handler
// code here
*pResult = 0;
}
ClassWizard自动生成合适类型的指针。你可以通过pNMHDR或者pLVKeyDow访问通告消息结构体。
ON_NOTIFY_RANGE
如果你需要处理一组控件的同一个WM_NOTIFY消息,你可使用ON_NOTIFY_RANGE而不是ON_NOTIFY。例如,你有一组按钮,想让它们对某一通告消息执行相同的动作。
When you use ON_NOTIFY_RANGE, you specify a contiguous range of child identifiers for which to handle the notification message by specifying the beginning and ending child identifiers of the range.
(不太会翻译,大意就是,使用ON_NOTIFY_RANGE的时候,要指定一个你所需要相同相同消息处理函数控件的ID范围)
ClassWizard不去处理ON_NOTIFY_RANGE的使用,要用它,就自己在消息映射表里编辑。
ON_NOTIFY_RANGE的消息映射入口与函数原型如下表示:
ON_NOTIFY_RANGE( wNotifyCode, id, idLast, memberFxn )
斜体字参数被替换为:
wNotifyCode
要被处理的通告消息代码,如 LVN_KEYDOWN。
id
连续ID范围里的第一个。
idLast
连续ID范围里的最后一个。
memberFxn
通告消息发送后被调用的成员函数。
你的成员函数必须按照如下形式声明:
afx_msgvoidmemberFxn(UINT id, NMHDR*pNotifyStruct,LRESULT*result);
斜体字参数为:
id
发送通告消息的控件ID。
pNotifyStruct
指向通告消息结构的指针,类型如上声明。
result
指向函数返回之前要被设置结果值的变量指针。
ON_NOTIFY_EX, ON_NOTIFY_EX_RANGE(这部分不理解,先放一放)
If you want more than one object in the notification routing to handle a message, you can use ON_NOTIFY_EX (or ON_NOTIFY_EX_RANGE) rather than ON_NOTIFY (or ON_NOTIFY_RANGE). The only difference between the EX version and the regular version is that the member function called for the EX version returns a BOOL that indicates whether or not message processing should continue. Returning FALSE from this function allows you to process the same message in more than one object.
ClassWizard does not handle ON_NOTIFY_EX or ON_NOTIFY_EX_RANGE; if you want to use either of them, you need to edit your message map yourself.
The message-map entry and function prototype for ON_NOTIFY_EX and ON_NOTIFY_EX_RANGE are as follows. The meanings of the parameters are the same as for the non-EX versions.
ON_NOTIFY_EX(nCode,id,memberFxn)
ON_NOTIFY_EX_RANGE( wNotifyCode, id, idLast,memberFxn )
The prototype for both of the above is the same:
afx_msgBOOLmemberFxn(UINT id, NMHDR*pNotifyStruct,LRESULT*result);
In both cases, id holds the child identifier of the control that sent the notification.
Your function must return TRUE if the notification message has been completely handled or FALSE if other objects in the command routing should have a chance to handle the message.
关于WM_COMMAND与WM_NOTIFY相关推荐
- 详解Windows消息分类以及WM_COMMAND与WM_NOTIFY的区别,以及模拟发送控件通知消息
Windows消息的分类 1. 标准消息(队列消息) 除WM_COMMAND之外,所有以WM_开头的消息都是标准消息,如WM_MOUSEMOVE.WM_LBUTTONUP.WM_KEYDOWN.W ...
- 【转】详解Windows消息分类以及WM_COMMAND与WM_NOTIFY的区别,以及模拟发送控件通知消息
转自:http://blog.sina.com.cn/s/blog_4b3c1f950100nten.html Windows消息的分类 1. 标准消息(队列消息) 除WM_COMMAND之外,所 ...
- 【转】WM_MESSAGE、WM_COMMAND、WM_NOTIFY等消息有什么不同
转自:https://blog.csdn.net/newstarao/article/details/3775690 WM_MESSAGE是最普通的WINDOWS消息,对于这种类型的消息没什么好说的. ...
- 13_MFC工具条和状态栏
MFC工具条和状态栏 Windows控制窗口 Windows (Windows95或者以上版本) 提供了系列通用控制窗口,其中包括工具条(ToolBar).状态栏(StatusBar).工具条提示窗口 ...
- MFC消息处理学习总结
Windows消息机制概述 http://www.cppblog.com/suiaiguo/archive/2009/07/18/90412.html 消息是指什么? 消息系统对于一个win ...
- WTL 出现的SetMsgHandled和IsMsgHandled 错误
WTL 出现的SetMsgHandled和IsMsgHandled 错误 江西理工 FangSH 2010/8/26 在学WTL第二部界面基类时程序出现了一个错误 如下: mainfrm.cpp e: ...
- 【MFC】MFC消息处理和映射
00. 目录 文章目录 00. 目录 01. 概述 02. 框架中的消息和命令 2.1 消息 2.2 消息处理程序 2.3 消息类别 2.4 映射消息 2.5 命令ID 2.6 标准命令 2.7 命令 ...
- MFC原理 消息传递
一丶简介 通过上一讲我们的消息映射表.我们得知. 消息映射表 会保存父类的MessageMap 以及自己当前的消息结构体数组. 消息传递是一层一层的递进的.那么我们现在要看一下怎么递进的. 要学习的知 ...
- duilib学习领悟(2)
再次强调,duilib只不过是一种思想! 在上一节中,我剖析了duilib中窗口类的注册,其中遗留两个小问题没有细说的? 第一个问题:过程函数中__WndProc()中有这么一小段代码: pThis ...
最新文章
- Spring Cloud【Finchley】-05使用配置文件自定义Ribbon Client
- 洛谷 - P4011 孤岛营救问题(bfs+状态压缩)
- pcb中layer stack manager 中,右上角的layer pairs 、internal layer pairs和build-up,三者的区别?
- java私有属性和私有方法_Java私有,受保护,公共和默认
- listview控件在php的使用方法,Android_Android编程之控件ListView使用方法,本文实例讲述了Android编程之控 - phpStudy...
- Spring Boot 学习笔记(三)Spring boot 中的SSM
- 问答丨按量子力学来说,一个人撞墙,有多大概率能穿过去?
- aws lambda使用_如何使用AWS Lambda为发布/订阅消息选择最佳事件源
- Java提高篇——Java中的异常处理
- 帆软报表跨域之插件开发中Controller中定义的方法实现CROS的GET跨域,且请求头带自定义属性
- 华为机试HJ88:扑克牌大小
- anaconda虚拟环境python升级_使用Anaconda虚拟环境管理Python版本
- 前门狗不理双人餐一份 - 北京团购网|京东团购
- 京东饭粒捡漏V1.0.8
- 【BUCTOJ训练:字符串最大跨距(Python)】
- Linux从入门到实战 ---- 磁盘分区
- alarm中断慢系统调用
- 【北邮国院大三上】大三上高编/互联网协议/电信系统笔记
- 深度学习中GPU和显存
- ieee 分布式34节点模型