`
hcmfys
  • 浏览: 348359 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

消息

 
阅读更多

在MFC应用程序中传输的消息有三种类型:窗口消息、命令消息和控件通知。
窗口消息(Window Message)一般与窗口的内部运作有关,如创建窗口、绘制窗口和销毁窗
口等。通常,消息是从系统发送到窗口,或从窗口发送到窗口。
若需要窗口消息的完全的列表,请参考M F C文档。
命令消息
命令消息一般与处理用户请求相关,当用户单击一个菜单项或工具栏时,命令消息产生,
并被发送到能处理该请求的类对象(如,装载文件、编辑文本和保存选项等)。
控件通知
通常,控件通知在某些重要事件发生时,由控件窗口发送到父窗口,如打开一个组合框。
控件通知为父窗口进一步控制子窗口提供了机会。例如,打开一个组合框时,父窗口可以用
组合框初建时得不到的消息填充它。
ON_COMMAND 和ON_MESSAGE都是将消息处理函数加入消息路由表中,但是ON_COMMAND对应的消息ID一直都是WM_COMMAND,而ON_MESSAGE的消息ID为ON_COMMAND的第一个参数
在MFC中,ON_COMMAND, ON_MESSAGE, ON_NOTIFY它们的区别。
ON_NOTIFY是控件向其父窗口发送消息处理的宏,ON_COMMAND是菜单和工具栏项处理消息的宏,ON_MESSAGE是处理自定义消息的宏
ON_COMMAND用来处理WM_COMMAND消息。老式的windows控件发送WM_COMMAND作为对父窗口的通知消息。另外,菜单,工具栏也向框架窗口发送WM_COMMAND消息。
ON_MESSAGE主要用来处理用户自定义消息。
对于某些新型的windows控件(如ListCtrl等),向父窗口发送通知消息时需要包含大量的信息,WM_COMMAND已不适应这种要求(因为WM_COMMAND的wparam和lparam都已经填满了),ON_NOTIFY主要用来处理这些新型的windows控件向父窗口的发送的WM_NOTIFY通知消息。
对这几个消息的理解要先了解一下Window消息的背景。
在Windows3.1里,控件会将mouse, keybord等等的消息通知它的父窗口, 使用的消息就只有WM_COMMAND, 事件种类和控件ID被包含在wParam中,控件的句柄包含在lParam中。由于wParam和 lParam已经满了,当控件要向父窗口发送其它特殊消息同时附带很多信息的时候就没有地方可以存放它们了。所以Windows3.1中定义了许多其它的消息种类,比如WM_VSCROLL, WM_CTLCOLOR等等,每种消息wParam,lParam中附带的信息是不同的。
当到了Win32后,控件的种类越来越多,当然不可以为每一个控件都定义一套消息,这样也不利于系统的扩充。所以在Win32中定义了唯一一个强大的消息WM_NOTIFY。当然WM_NOTIFY也遵守原来的消息规则,既只带参数wParam和lParam。唯一不同处在于,此时的lParam中传送的是一个NMHDR指针。不同的控件可以按照规则对NMHDR进行扩充,因此WM_NOTIFY消息传送的信息量可以相当的大,这个可以看看MSDN中的相关说明,TreeControl中就有很多这种消息。
现在就可以知道为什么有ON_MESSAGE,ON_COMMAND,ON_NOTIFY了。
ON_MESSAGE是处理所有的Windows的消息的,因为所有的消息都以相同的格式传送,也就是ID, WPARAM, LPARAM.
ON_COMMAND是专门处理WM_COMMAND消息的,这样我们就不用自己解开WM_COMMAND中wParam和lParam中传送的控件ID,事件种类,所有的都在MFC内部解决了。
ON_NOTIFY更是不用说了,看看他的处理函数,是不是把NMHDR解出来了。
这样一样就一目了然了,ON_COMMAND和ON_NOTIFY都可以用ON_MESSAGE来处理,只不过自己要多做很多事情。ON_COMMAND和ON_NOTIFY最好就不要互换了!

ON_COMMAND是菜单和工具栏项处理消息的宏
ON_MESSAGE是处理自定义消息的宏

ON_NOTIFY 是控件向其父窗口发送消息处理的宏

/////////////////////////////////////////////////////////////////////////////////////////////////////

对这几个消息的理解要先了解一下Window消息的背景。
在Windows3.1里,控件会将mouse, keybord等等的消息通知它的父窗口, 使用的消息就只有WM_COMMAND, 事件种类和控件ID被包含在wParam中, 控件的句柄包含在lParam中。由于wParam和 lParam已经满了,当控件要向父窗口发送其它特殊消息同时附带很多信息的时候就没有地方可以存放它们了。所以Windows3.1中定义了许多其它的 消息种类,比如WM_VSCROLL, WM_CTLCOLOR等等,每种消息wParam,lParam中附带的信息是不同的。
当到了Win32后,控件的种类越来越多,当然不可以为每一个控件都定义一套消息,这样也不利于系统的扩充。所以在Win32中定义了唯一一个强大的消息 WM_NOTIFY。当然WM_NOTIFY也遵守原来的消息规则,既只带参数wParam和lParam。唯一不同处在于,此时的lParam中传送的 是一个NMHDR指针。不同的控件可以按照规则对NMHDR进行扩充,因此WM_NOTIFY消息传送的信息量可以相当的大,这个可以看看MSDN中的相 关说明,TreeControl中就有很多这种消息。

现在就可以知道为什么有ON_MESSAGE ,ON_COMMAND, , ON_NOTIFY了。
ON_MESSAGE是处理所有的Windows的消息的,因为所有的消息都以相同的格式传送,也就是ID, WPARAM, LPARAM.
ON_COMMAND是专门处理WM_COMMAND消息的,这样我们就不用自己解开WM_COMMAND中wParam和lParam中传送的控件ID, 事件种类…(所有的都在MFC内部解决了:),当然方便了。
ON_NOTIFY更是不用说了,看看他的处理函数,是不是把NMHDR解出来了。

这样一样就一目了然了,ON_COMMAND和ON_NOTIFY都可以用ON_MESSAGE来处理,只不过自己要多做很多事情。ON_COMMAND和ON_NOTIFY最好就不要互换了!

几点说明:

1、ON_COMMAND(id,memberFxn)
此宏通过ClassWizard或手工插入一个消息映射。它表明那个函数将从一个命令用户接口(例如一个菜单项或toolbar按钮)处理一个命令消息。 当一个命令对象通过指定的ID接受到一个Windows WM_COMMAND消息时,ON_COMMAND将调用成员函数memberFxn处理此消 息。在用户的消息映射中,对于每个菜单或加速器命令(必须被映射到一个消息处理函数)应该确实有一个ON_COMMAND宏语句。

2、ON_MESSAGE(message,memberFxn)
指明哪个函数将处理一用户定义消息。用户定义消息通常定义在WM_USER到0x7FF范围内。用户定义消息是那些不是标准 Windows WM_MESSAGE消息的任何消息。在用户的消息映射中,每个必须被映射到一个消息处理函数。用户定义消息应该有一个 ON_MESSAGE宏语句。

3、ON_Update_COMMAND_UI(id,memberFxn)
此宏通常通过ClassWizard被插入一个消息映射,以指明哪个函数将处理一个用户接口更改命令消息。在用户的消息映射中,每个用户接口更改命令(比讯被映射到一个消息处理函数)应该有一个ON_Update_COMMAND_UI宏语句。
4、ON_VBXEVENT(wNotifyCode,memberFxn)
此宏通常通过ClassWizard被插入一个消息映射,以指明哪个函数将处理一个来自VBX控制的消息。在用户的消息映射中每个被映射到一消息处理函数的VBX控制消息应该有一个宏语句。
5、ON_REGISTERED_MESSAGE(nmessageVarible,memberFxn)
Windows的RegisterWindowsMesage函数用于定义一个新窗口消息,此消息保证在整个系统中是唯一的。此宏表明哪个函数处理已注册消息。变量nMessageViable应以NEAR修饰符来定义。

6、ON_CONTROL(wNotifyCode,id,memberFxn)
表明哪个函数将处理一个常规控制表示消息。控制标识消息是那些从一个控制夫发送到母窗口的消息。

ON_NOTIFY是针对WM_NOTIFY的消息宏,

WM_NOTIFY是针对 ListCtrl,TreeCtrl,TabCtrl等通用控件使用的消息 button,listbox等基本控件是不会用到这个消息的


利用ON_COMMAND()宏创建的自定义消息处理机制确实无法使用wParam与lParam参数,这是由于ON_COMMAND()宏决定的。如果需要使用wParam与lParam参数,那么应当使用ON_MESSAGE()宏,由它扩展生成的消息处理函数的原型中才有这两个参数。

在.H文件中需要加入#define WM_MYMSG WM_USER+5以自定义一个消息,并在消息处理映射表中加入afx_msg void OnMyMessage(WPARAM wParam, LPARAM lParam)进行自定义消息的处理函数声明,这个声明一定要放在DECLARE_MESSAGE_MAP()宏之前。

afx_msg void OnMyMessage(WPARAM wParam, LPARAM lParam); //自定义消息的处理函数声明在.CPP文件中的消息映射表(BEGIN_MESSAGE_MAP与END_MESSAGE_MAP宏之间的内容)中需要加入ON_MESSAGE(WM_MYMSG, OnMyMessage)宏在自定义消息与其处理函数间建立映射关系,并实现消息处理函数void CModelessDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)。

void CModelessDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)
//从lParam中取出CString对象的指针,并将字符串内容在IDC_MSGEDIT中显示出来
{
CString* pStr = (CString*) lParam;
ASSERT(pStr != NULL);

CEdit* pEdit = (CEdit *) GetDlgItem(IDC_MSGEDIT);
ASSERT(pEdit != NULL);

pEdit->SetWindowText(*pStr);
}
///////////////////////////////////////////////////////////////////////////////////////////////

WM_NOTIF在WIN32中得到大量的应用,同时也是随着CommControl的出现WM_NOTIFY成为了CommControl的基本消息。可以这样说CommControl的所有的新增特性都通过WM_NOTIFY来表达。同时WM_NOTIFY也为CommControl的操作带来了一致性。
WM_NOTIFY消息中的参数如下:
idCtrl = (int) wParam;
pnmh = (LPNMHDR) lParam; 其中lParam为一个

typedef struct tagNMHDR
{
HWND hwndFrom;
UINT idFrom;
UINT code;
} NMHDR; 结构指针
从消息的参数我们已经可以分辩出消息的来源,但是这些信息还不足以分辩出消息的具体含义。所以我们需要更多的数据来得到更多的信息。MS的做法是对每种不同用途的通知消息都定义另一种结构来表示,同时这中结构里包含了struct tagNMHDR,所以你只要进行一下类型转换就可以得到数据指针。例如对于LVN_COLUMNCLICK消息(用于在ListCtrl的列表头有鼠标点击是进行通知),结构为;
typedef struct tagNMLISTVIEW{
NMHDR hdr;
int iItem;
int iSubItem;
UINT uNewState;
UINT uOldState;
UINT uChanged;
POINT ptAction;
LPARAM lParam;
} NMLISTVIEW, FAR *LPNMLISTVIEW;

在这个结构的最开始也就包含了struct tagNMHDR,所以在不损失数据和产生错误的情况下向处理消息的进程提供了更多的信息。
 

此外通过WM_NOTIFY我们可以一种完全一样的方式进行消息映射,如同在前几章中所见到的一样。
使用如下形式:ON_NOTIFY( wNotifyCode, id, memberFxn )。
处理函数也有统一的原型:afx_msg void memberFxn( NMHDR * pNotifyStruct, LRESULT * result );
在MFC消息映射的内部将根据定义消息映射时所使用的wNotifyCode和WM_NOTIFY中参数中pnmh->code(pnmh = (LPNMHDR) lParam)进行匹配,然后调用相应的处理函数。

还有一点是利用WM_NOTIFY/ON_NOTIFY_REFLECT可以在窗口内部处理一些消息,从而建立可重用的控件。大家可以参考Build Reusable MFC Control Classes。目前我也准备在空闲时翻译这篇文章。

分享到:
评论

相关推荐

    C#消息队列,windows使用消息队列,Queue消息队列

    此文档是C#开发的消息队列系统,适用于消息队列入门与新手。 在Windows 7 上安装消息队列的步骤 打开“控制面板”。 单击“程序”,然后在“程序和功能”下, 单击“打开或关闭 Windows 功能”。 -或者-单击“经典...

    linux c消息队列实现

    发送端读取指定的文件,并且按照环境变量中设置的消息队列键值进行发送。如果要改代码,只要把键值改一下,结构体储存要发送的消息的那个数组对应改成自己想发送的值,就可以很好的实现功能。接收端同样按环境变量...

    C#写的QQ自动发消息.rar

    ////发送消息,因为QQ屏蔽了 WM_SETTEXT, WM_PASTE 命令,所有采用 EM_REPLACESEL 来实现 NativeMethods.SendMessage(hwndRichEdit, NativeMethods.EM_REPLACESEL, IntPtr.Zero, msg); ////给发送按钮发 鼠标...

    利用服务器推送技术实现站内短消息(java)

    让client与service建立一个长连接,不用client手动request,service会自动response,当有好友在线的时候,会自动把好友的信息加载到select里,点击好友发送短消息时,会在浏览器(IE)右下角弹出消息框,但是现在有一...

    基于消息的通讯系统设计(C++源码)

    基于消息的通讯系统设计 目的与要求: 本设计的目的:是通过设计和调试一个基于消息的通讯系统,来实现进程之间的间接通讯,使学生对进程间的通讯机制、进程间的同步机制有一个深入的理解。 具体要求如下: ⑴设计...

    Delphi程序间消息传递.txt

    Delphi程序间消息传递 使用该消息涉及一个TcopyDataStruct结构类型的指针。该结构中有三个成员: dwData 是一个32位的附加参数 cbData 表示要传递的数据区的大小 lpData 表示要传递的数据区的指针 下面举个例子。该...

    基于高效缓存管理机制的可靠消息传输机会网络路由算法

    引入Spray and Wait机制,设计消息传输策略,对消息发送顺序、缓存清除机制以及消息转发机制进行优化,以确保携带消息节点在有限通信时间内向邻居节点转发更多的消息,节点相遇后,判断缓存中过期消息的目标节点是否为...

    JMS简明教程创建消息 -> 发送消息 -> 接收消息 -> 读取消息

    什么是消息 消息是一个用于在组件和应用程序之间通讯的的方法。消息之间的传递是点对点的。任何终端之间都可以相互接受和发送消息。并且每个终端都必须遵守如下的规则 -> 创建消息 -> 发送消息 -> 接收消息 -> 读取...

    ECDIS_AIS_消息接收解析入库代码-JAVA版

    1、ECDIS_AIS消息接收解析入库代码,java版本。 2、classA于classB类型消息都可以解析。 3、带数据库DDL语句,消息解析后直接入库。 4、消息解析使用多线程模式,没有阻塞。 5、此程序为整套ECDIS海图系统中的模块之...

    进程间通信之消息队列 ( message queue )——完整代码

    进程间通信之消息队列 ( message queue ) 消息队列是消息的链表,具有特定的格式,并由消息队列标识符标识. 七种进程间通信方式: 一.无名管道( pipe ) 二.有名管道( fifo ) 三.共享内存 ( shared memory ) 四....

    C# winform可忽略消息的自定义消息队列

    当winform中控件之间传递消息时,防止回调事件中有耗时操作,可以忽略一部分消息,只执行最终的消息

    Java消息服务的消息中间件的研究与设计

    Java消息服务的消息中间件的研究与设计

    Android仿QQ消息通知栏新消息实时更新效果

    Android仿QQ消息通知栏新消息实时更新效果,实时接收新消息显示并更新,点击通知栏清除所有新消息

    NC65消息通知.rar

    NC65消息通知功能,发送业务消息,审批消息,消息通知

    漂亮的消息提示框 消息提示组件 Javascript写的

    组件名称:ymPrompt消息提示组件 2.0 演示地址:http://bbs.okajax.com/demo/31/ =============================================================================== 组件说明:在web开发中,对于浏览器默认的消息...

    分布式消息队列----如何保证消息的顺序性?

    如何保证消息的顺序性?

    Java企业微信群机器人发送消息

    将企业微信群机器人发送 文字、图片、MarkDown、文件消息 封装成了一个工具类: 1.可以用于自建的群,即不是使用企业微信api创建的群,不需要群id; 2.主要使用 okhttp3 调用机器人api和上传文件到临时素材api; 3.有...

    消息推送,轮询,消息通知

    消息推送,轮询,消息通知

Global site tag (gtag.js) - Google Analytics