在windows程序中,消息是一个重要的概念,最常见的消息一般都是以WM_开头,WM就是window message,窗口消息的缩写,通过处理标准的windows消息,我们可以改变窗口的外观,如使用WM_ERASEBKGND消息可以改变窗口默认的窗口背景,窗口每次需要绘制窗口的背景的时候,就会发送一次这个消息,如果我们处理这个消息,我们就可以绘制我们自己的特性化的背景,如果不处理,默认窗口过程就会处理,绘制背景。通过处理标准的windows消息,我们可以对用户的输入做出响应,如WM_LBUTTONDOWN,当鼠标按下的时候,就可以对用户的操作作出响应,通过命令消息WM_COMMAND消息,可以获取来自菜单,按钮的命令。另外,控件还有自己的notification消息,当控件的状态发生改变的时候,如点击按钮,点击编辑框,选择一个列表框项目时,就会发送相应的消息,通过处理消息,就可以对获取控件的一些消息,做出一些处理。在sdk中还有一种消息,也是用于控件的,也是通过发送消息来控制控件的属性和操作,而这个在MFC中变成了成员函数,但是底层的原理还是一样的。消息的作用还有很多,我们不能单一的去理解消息这个概念,一方面,我们可以通过阅读msdn可以深入的学习消息,另一方面,我们可以通过在使用的过程中,加深对消息的理解。除了使用上面说的这些windows提供的预定义消息(系统消息)之外,我们也可以使用我们自定义的消息。

每个消息有一个ID,对于自定义消息,我们在定义的时候,也要定义一个ID,而这个ID的范围是有要求的,可以是WM_USER (0x0400) 到 0x7FFF,也可以是 WM_APP (0x8000) 到0xBFFF,别的ID范围呢,系统保留。在使用的时候,通常都是以WM_USER+X,WM_APP+X或是在定义消息ID的时候,有两种方法:

第一种方法是通过常量声明幅值的方法,也就是常量的使用方法,因为一个消息的ID就是一个常量,确定之后,就不能改变,因此,可以使用定义常量的方法来为一个消息附上ID,如下:

const UINT WM_MYMESSAGE1=WM_APP+1;

第二种方法是通过#define,如下:

#define WM_MYMESSAGE2 WM_APP+2

通过这两种方法,我们就可以在为一个消息指定ID。下面是要说说,上面这两句定义消息ID的表达式所放的位置的不同所产生的使用方法的不同。下面以实例来说明:

第一种情况,当我把定义消息ID的表达式放在了头文件MyView.h中

当我在SINView.cpp文件中接收和处理这两个消息时,必须事先包含声明两个消息ID的头文件,这里是MyView.h。否则,在cpp中处理的时候,就是出现语法错误,提示未声明的标示符。

第二种情况,如果我们由于一些原因,不能包含声明消息ID的头文件,例如,如果我们包含了,就会出现互相包含的情况,就会造成错误,或是,将在发送这个消息的cpp文件和接受处理这个消息的cpp文件中定义这两个消息的ID,那么这个时候,我们必须在两个地方声明和幅值消息ID,一个地方是发送的类的源文件或头文件中,另一个地方是接收和处理这个自定义消息的源文件中。例如,WM_MYMESSAGE3,我在MyView.h或是MyView.cpp中进行声明,因为我要从MyView.cpp中发送这个消息,如图:

在接收消息的地方,我再次定义一次,可以直接复制上次定义的,我要在SINView.cpp中接收和处理,于是在这个文件的开头,如下图:

现在已经定义好了消息的ID,接下来是发送消息,发送消息,一般是是用SendMessage和PostMessage,SendMessage必须要等到这个消息被处理并返回之后才会结束执行,否则会一直等待,如果消息一直得不到处理,函数一直等待,就会造成发送消息的线程阻塞。PostMessage是将消息发送之后,就立即返回,不管消息是否到达目的地,处理。如果在单线程程序中,我们最好是用PostMessage,用SendMessage容易造成线程锁死。另外,在MFC中使用这两个函数,如果直接使用,第一个参数就是要发送的消息,这样只能向本窗口发送消息,如果在MFC中使用::PostMessage,这样就是使用的是win32函数的api,第一个参数是目标窗口句柄,就可以向任意窗口发送消息。

下面说说如何处理发送的消息,首先介绍一种最为简单的处理方法,这种方法和在win32 sdk中的窗口过程一样,通过switch/case语句来处理.在MFC窗口类都有一个WindowProc虚函数,当这个窗口的消息进入这个窗口的消息映射之前,会首先通过这个虚函数,因此,我们在这里就可以拦截处理我们的自定义消息,甚至是别的任何消息,当然,标准窗口消息仍然是推荐使用MFC的消息映射的方法来处理。如下图:

使用这种方法,有一点很重要,那就是最后那一句return语句:return CView::WindowProc(message, wParam, lParam);这样保证别的消息可以正确处理。这种处理方式和win32 sdk中的窗口过程处理消息的方式是一样的。

接着介绍一种MFC标准的自定义消息处理的方式,也就是是用ON_MESSAGE宏。使用这种方式,就和我的博文"MFC-消息机制"中描述的消息处理方式一样,要使用这种处理方式,首先要声明一个消息响应函数原型,接着添加消息映射,最后实现消息响应函数。我们一步一步来看,首先看ON_MESSAGE宏的原型:

ON_MESSAGE(message, memberFxn)

第一个参数是消息ID,第二个参数消息响应函数。现在,针对WM_MYMESSAGE3消息,我们使用这种处理方式。首先在CSINView类中声明一个消息响应函数:

afx_msg LRESULT OnMyMessage3(WPARAM wParam, LPARAM lParam);

消息响应函数的名称由自己确定,这里我使用的是OnMyMessage3。在声明这个消息响应函数的时候,一般就是按照这个样式,而且一般声明为protected。

接着是消息添加消息映射,使用ON_MESSAGE,如下:

最后是实现消息响应函数,在SINView.cpp中,如下:

通过ON_MESSAGE宏,当窗口接收到消息的时候,就会自动调用我们的消息响应函数了。

以上就阐述了一下,在MFC自定义消息的使用方法,下面是效果图:

最后在说说消息过滤的问题,使用过win32 sdk编写程序的人都知道,可以在使用while从消息队列中获取消息的时候,在派发消息到窗口之前,可以做一个消息过滤,在MFC这里也可以,CWinApp有一个虚函数CWinApp::PreTranslateMessage,这个虚函数就是消息循环获取消息,派发之前,就调用这个虚函数,我们就可以在这个虚函数中,拦截过滤一些消息,主要是通过这个虚函数的参数,一个消息结构体,来判断要过滤的消息。一个是判断句柄,一个是判断消息id。

本文中涉及到的信息,如有疑问,请参考msdn。

author email:andyhl1987@126.com

本文代码:http://download.csdn.net/detail/xinzhiyounizhiyouni/6680781

windows7 vs2010环境下

MFC--自定义消息的更多相关文章

  1. MFC自定义消息

    本文地址:http://blog.163.com/strive_only/blog/static/893801682010101911467765/ 消息机制是windows的典型运行机制,在MFC中 ...

  2. MFC自定义消息的实现方法

    一.概述: 消息机制是windows程序的典型运行机制,在MFC中有很多已经封装好了的消息,如WM_BTN**等.但是在有些特殊情况下我们需要自定义一些消息去完成一些我们所需要的功能,这时候MFC的向 ...

  3. MFC在子线程中创建窗口(PostMessage方法)

    1.创建子线程 C++创建线程的方式比较多 1)最简单易用的<thread>头文件,但是这种方法创建的子线程中无法给主线程PostMessage消息(也可能是我操作有误,总之没成功) 2) ...

  4. MFC用户自定义消息

    之前做过佳能相机和位移平台的额二次开发,当时遇到一个棘手的问题,就是位移平台如何知道相机已经拍完照了,或者相机如何知道位移平台已经运行到指定位置,当时为了方便采用了定时器来定时检测位移平台的位置,结果 ...

  5. C#中自定义消息,与MFc对比

    在C#中采用的是事件驱动方式,但在我们使用的过程中,有时候通过调用系统原有的消息,处理起来会比较简单一些,特别是在处理与DLL文件的交互时,的确是非常的方便.    在C#中使用自定义消息      ...

  6. MFC发送自定义消息-PostMessage和SendMessage

    PostMessage:把消息投放到线程的消息队列,不能消息被处理就立即返回SendMessage:消息被处理完后才返回 几种发送消息的写法:   ::PostMessage(GetSafeHwnd( ...

  7. MFC添加自定义消息

    由于MFC中无法通过类向导来自定义消息,所以需要手动添加,主要过程如下: 本文基于vs2008下通过线程实现数据实时更新的对话框运用程序 1. 定义消息(Resource.h文件中): 由于很多新控件 ...

  8. MFC中创建自定义消息

    消息映射.循环机制是Windows程序运行的基本方式.VC++ MFC 中有许多现成的消息句柄,可当我们需要完成其它的任务,需要自定义消息,就遇到了一些困难.在MFC ClassWizard中不允许添 ...

  9. MFC消息-自定义消息

    转:http://blog.csdn.net/penpenandtongtong/article/details/18598907 像MFC的窗口发送消息,可以进行自定义的动作行为,因此很多时候非常有 ...

随机推荐

  1. 第2次增加ssh 主机信任脚本

    dr-mysql01:/root# cat a1.sh #用户名 uname="$1" #密码 passwd="$2" #执行检测并安装expect模块 ep= ...

  2. CCIE路由实验(4) -- BGP路由控制

    1.过滤BGP路由的方法2.用AS-path filter控制路由3.用Community Filter控制路由 enableconf tno ip do loenable pass ciscolin ...

  3. vb和vb.net事件机制

    学习java事件前,回顾了下vb6和vb.net的事件机制,总结在这里,供对比用. 事件是面对对象中对象间通信的方法.事件发生者(又叫事件源)发生一个事件时,通过发送一条消息,给事件接受者(事件处理者 ...

  4. CSipSimple最新版本号(二)--加入视频功能

    前面我们编译好了最新版本号的CSipSimple,并且測试已经能够打电话了.如今要把视频功能加上去. 不知道怎么编译的,能够看我的上一篇博文:CSipSimple最新版本号 我们先来看一下之前的项目是 ...

  5. 深度优先搜索(DFS)递归形式改为非递归形式

    DFS将递归改为非递归这个方法的需求来自于一道三维积木组合的题目,还在苦苦调试中,暂且不提. 普通的认识对于递归向非递归的转化无非是使用栈,但是结合到深度搜索如何将栈很好利用,如何很好保存现场,都不是 ...

  6. [Boost]boost的时间和日期处理-(2)时间的操作

    <开篇> 本篇紧接着boost上篇叙述Boost::DateTime的时间处理.在C++中,常见的时间有time_t, FILETIME和tm,而boost中用ptime. 构造ptime ...

  7. Java I/O流-ObjectInputStream、ObjectOutputStream

    一.整体代码 ObjectStreamDemo.java import java.io.File; import java.io.FileInputStream; import java.io.Fil ...

  8. Swift - 使用UI Dynamics给UIKit组件添加移动吸附行为

    UI Dynamics是UIKit的一个新组成部分,它向iOS中的视图提供了与物理学有关的功能和动画.可以让你向视图中引入力和物理属性,可以让你的视图弹跳,舞动,受重力影响等等. 下面通过样例,演示使 ...

  9. Hadoop源代码导入Eclipse

    须要进一步学习hadoop.须要看看内部源代码实现.因此须要将hadoop源代码导入都eclipse中,简单总结一下,详细过程例如以下: 首先确保已经安装了git.maven3.protobuf2.5 ...

  10. C语言,C++,static

    术语static有着不寻常的历史.起初,在C中引入关键字static是为了表示退出一个块后仍然存在的局部变量.随后,static在C中有了第二种含义:用来表示不能被其它文件访问的全局变量和函数.为了避 ...