MFC--自定义消息
在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--自定义消息的更多相关文章
- MFC自定义消息
本文地址:http://blog.163.com/strive_only/blog/static/893801682010101911467765/ 消息机制是windows的典型运行机制,在MFC中 ...
- MFC自定义消息的实现方法
一.概述: 消息机制是windows程序的典型运行机制,在MFC中有很多已经封装好了的消息,如WM_BTN**等.但是在有些特殊情况下我们需要自定义一些消息去完成一些我们所需要的功能,这时候MFC的向 ...
- MFC在子线程中创建窗口(PostMessage方法)
1.创建子线程 C++创建线程的方式比较多 1)最简单易用的<thread>头文件,但是这种方法创建的子线程中无法给主线程PostMessage消息(也可能是我操作有误,总之没成功) 2) ...
- MFC用户自定义消息
之前做过佳能相机和位移平台的额二次开发,当时遇到一个棘手的问题,就是位移平台如何知道相机已经拍完照了,或者相机如何知道位移平台已经运行到指定位置,当时为了方便采用了定时器来定时检测位移平台的位置,结果 ...
- C#中自定义消息,与MFc对比
在C#中采用的是事件驱动方式,但在我们使用的过程中,有时候通过调用系统原有的消息,处理起来会比较简单一些,特别是在处理与DLL文件的交互时,的确是非常的方便. 在C#中使用自定义消息 ...
- MFC发送自定义消息-PostMessage和SendMessage
PostMessage:把消息投放到线程的消息队列,不能消息被处理就立即返回SendMessage:消息被处理完后才返回 几种发送消息的写法: ::PostMessage(GetSafeHwnd( ...
- MFC添加自定义消息
由于MFC中无法通过类向导来自定义消息,所以需要手动添加,主要过程如下: 本文基于vs2008下通过线程实现数据实时更新的对话框运用程序 1. 定义消息(Resource.h文件中): 由于很多新控件 ...
- MFC中创建自定义消息
消息映射.循环机制是Windows程序运行的基本方式.VC++ MFC 中有许多现成的消息句柄,可当我们需要完成其它的任务,需要自定义消息,就遇到了一些困难.在MFC ClassWizard中不允许添 ...
- MFC消息-自定义消息
转:http://blog.csdn.net/penpenandtongtong/article/details/18598907 像MFC的窗口发送消息,可以进行自定义的动作行为,因此很多时候非常有 ...
随机推荐
- 通过xml生成word文档
Xml生成word总结 使用xml生成word的基本步骤在<使用xslt转化xml数据形成word文档导出.doc>中说明比较清楚了.但是其中的细节并未说到,因此自己折腾了两天总算成功了. ...
- Java基础:多态(重载和重写)
转载请注明出处:jiq•钦's technical Blog (1)域与静态方法 记住"仅仅有普通方法的调用是多态的". 而域和静态方法不是:对于域的訪问.在编译期间就已经进行解析 ...
- [TroubleShootin]The backup set holds a backup of a database other than the existing 'xxdb' database.
One: he backup set holds a backup of a database other than the existing 'xxdb' database Sometime ...
- C++多继承的好处是增加了弹性和灵活性,Delphi类强迫单继承TObject是为了提供许多强大功能
要说灵活性,是C++更强.我自己开发已经好几次碰到需要多继承的情况了. 但是Delphi强迫继承TObject,虽然是单继承,但是提供了相当多的强力功能.要说强大,那还是Delphi当仁不让. 摘自& ...
- WCF技术剖析之一:通过一个ASP.NET程序模拟WCF基础架构
原文:WCF技术剖析之一:通过一个ASP.NET程序模拟WCF基础架构 细算起来,已经有好几个月没有真正的写过文章了.近半年以来,一直忙于我的第一本WCF专著<WCF技术剖析>的写作,一直 ...
- VS2008SP1中CDialogEx的使用问题及解决
系统环境:Windows 7软件环境:Visual Studio 2008 SP1本次目的:建立一个CDialogEx的对话框 我们知道在VS2008SP1引进了BCG第三方控件,可以使MFC界面编程 ...
- 关于innodb purge thread和master thread
由innodb_purge_threads控制purge线程数. (>= 5.6.5)的版本号中该值默觉得1.最大值为32.默认值1表示innodb的purge操作被分离到purge线程中,ma ...
- UVA 322 ships (POJ 1138)
题目地址: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
- hdoj 1286 找新朋友 【数论之欧拉函数】
找新朋友 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- poj 3466 A Simple Problem with Integers
题目链接:http://poj.org/problem?id=3468 http://poj.org/problem?id=3468 http://poj.org/problem?id=3468 思路 ...