声明:原文来自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保存控件的句柄。此时注意,wParamlParam已经装满了数据,再也传递不了别的数据了,这些消息只能是简单的通告消息。举个例子,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_SHOWTTN_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 GuideMapping 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相关推荐

  1. 详解Windows消息分类以及WM_COMMAND与WM_NOTIFY的区别,以及模拟发送控件通知消息

    Windows消息的分类 1. 标准消息(队列消息)   除WM_COMMAND之外,所有以WM_开头的消息都是标准消息,如WM_MOUSEMOVE.WM_LBUTTONUP.WM_KEYDOWN.W ...

  2. 【转】详解Windows消息分类以及WM_COMMAND与WM_NOTIFY的区别,以及模拟发送控件通知消息

    转自:http://blog.sina.com.cn/s/blog_4b3c1f950100nten.html Windows消息的分类 1. 标准消息(队列消息)   除WM_COMMAND之外,所 ...

  3. 【转】WM_MESSAGE、WM_COMMAND、WM_NOTIFY等消息有什么不同

    转自:https://blog.csdn.net/newstarao/article/details/3775690 WM_MESSAGE是最普通的WINDOWS消息,对于这种类型的消息没什么好说的. ...

  4. 13_MFC工具条和状态栏

    MFC工具条和状态栏 Windows控制窗口 Windows (Windows95或者以上版本) 提供了系列通用控制窗口,其中包括工具条(ToolBar).状态栏(StatusBar).工具条提示窗口 ...

  5. MFC消息处理学习总结

    Windows消息机制概述 http://www.cppblog.com/suiaiguo/archive/2009/07/18/90412.html 消息是指什么?      消息系统对于一个win ...

  6. WTL 出现的SetMsgHandled和IsMsgHandled 错误

    WTL 出现的SetMsgHandled和IsMsgHandled 错误 江西理工 FangSH 2010/8/26 在学WTL第二部界面基类时程序出现了一个错误 如下: mainfrm.cpp e: ...

  7. 【MFC】MFC消息处理和映射

    00. 目录 文章目录 00. 目录 01. 概述 02. 框架中的消息和命令 2.1 消息 2.2 消息处理程序 2.3 消息类别 2.4 映射消息 2.5 命令ID 2.6 标准命令 2.7 命令 ...

  8. MFC原理 消息传递

    一丶简介 通过上一讲我们的消息映射表.我们得知. 消息映射表 会保存父类的MessageMap 以及自己当前的消息结构体数组. 消息传递是一层一层的递进的.那么我们现在要看一下怎么递进的. 要学习的知 ...

  9. duilib学习领悟(2)

    再次强调,duilib只不过是一种思想! 在上一节中,我剖析了duilib中窗口类的注册,其中遗留两个小问题没有细说的? 第一个问题:过程函数中__WndProc()中有这么一小段代码: pThis ...

最新文章

  1. Spring Cloud【Finchley】-05使用配置文件自定义Ribbon Client
  2. 洛谷 - P4011 孤岛营救问题(bfs+状态压缩)
  3. pcb中layer stack manager 中,右上角的layer pairs 、internal layer pairs和build-up,三者的区别?
  4. java私有属性和私有方法_Java私有,受保护,公共和默认
  5. listview控件在php的使用方法,Android_Android编程之控件ListView使用方法,本文实例讲述了Android编程之控 - phpStudy...
  6. Spring Boot 学习笔记(三)Spring boot 中的SSM
  7. 问答丨按量子力学来说,一个人撞墙,有多大概率能穿过去?
  8. aws lambda使用_如何使用AWS Lambda为发布/订阅消息选择最佳事件源
  9. Java提高篇——Java中的异常处理
  10. 帆软报表跨域之插件开发中Controller中定义的方法实现CROS的GET跨域,且请求头带自定义属性
  11. 华为机试HJ88:扑克牌大小
  12. anaconda虚拟环境python升级_使用Anaconda虚拟环境管理Python版本
  13. 前门狗不理双人餐一份 - 北京团购网|京东团购
  14. 京东饭粒捡漏V1.0.8
  15. 【BUCTOJ训练:字符串最大跨距(Python)】
  16. Linux从入门到实战 ---- 磁盘分区
  17. alarm中断慢系统调用
  18. 【北邮国院大三上】大三上高编/互联网协议/电信系统笔记
  19. 深度学习中GPU和显存
  20. ieee 分布式34节点模型

热门文章

  1. windows开启远程连接
  2. 凡子谷机器人创客教育_创客机器人教育基地
  3. [答疑]举报卖家、举报买家还是举报
  4. 跨境电商亚马逊运营的五大小技巧你都知道哪些
  5. iOS 打开AppStore指定app下载页
  6. 贴片电容介质X5R与X7R之间的区别
  7. 【5G RRC】Master Information Block (NR-MIB)
  8. 第一积分中值定理(两种形式)的证明
  9. 中介兴风 深圳楼市起浪
  10. 面试题:o2o,b2c、b2b、c2c、p2p、b2b2c....这些内容是什么意思