消息映射编程实验
实验十一 MFC的简单消息映射与处理

实验十一 MFC的简单消息映射与处理(4学时)[实验目的]1、基本掌握Windows环境下MFC程序的开发流程和方法;2、基本掌握MFC中的消息映射与处理方法;[实验内容]创建一个单文档的MFC工程,使用ClassWizard在视图类中添加WM_KEYDOWN、WM_KEYUP、WM_CHAR键盘消息映射和消息响应函数,添加WM_LBUTTON、WM_ RBUTTON鼠标消息映射和消息响应函数及。
界面如图所示,实现如下功能:程序运行界面图(1)用户按下/释放Shift键时,程序在视图窗口中显示有关的提示信息。
(2)用户按下Shift+B键时,程序在视图窗口中显示有关的提示信息。
(3)用户在视图窗口中按下鼠标左键,并拖动鼠标时,在窗口中绘制一个随鼠标位置变化的椭圆。
当用户释放鼠标键时,停止椭圆的绘制。
[实验步骤](1)创建一个单文档的MFC工程;(2)使用ClassWizard在其视图类中添加键盘消息WM_KEYDOWN、WM_KEYUP和WM_CHAR(分别对应键的按下、松开和按键动作)和消息响应函数;(3)在视图类的头文件中添加成员变量,以记录按键状态:protected:BOOL bShiftdown, bShiftup, bShiftB;并在视图类的构造函数中,对上述成员变量进行初始化:*View::*View(){// TODO: add construction code herebShiftdown=bShiftup=bShiftB=FALSE; //赋初值}其中,红色内容对应VC自动生成部分。
*View为视图类名。
(4)在键盘消息响应函数中,判断按键的状态,并设置上述成员变量的值。
代码如下:void *View::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags){// TODO: Add your message handler code here and/or call default//判断Shift键是否被按下if(nChar==VK_SHIFT){//AfxMessageBox("dd");bShiftdown=TRUE;bShiftup=FALSE;Invalidate(TRUE); //显示信息}CView::OnKeyDown(nChar, nRepCnt, nFlags);}void *View::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags){// TODO: Add your message handler code here and/or call default//判断Shift键是否被释放if(nChar==VK_SHIFT){//AfxMessageBox("dd");bShiftup=TRUE;//显示信息Invalidate(TRUE);bShiftdown=FALSE;}CView::OnKeyUp(nChar, nRepCnt, nFlags);}void *View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags){// TODO: Add your message handler code here and/or call defaultif((nChar==98)||(nChar==66)) //判断是否敲击了字符键B键或b键{if(bShiftdown){bShiftB=TRUE;bShiftdown=FALSE;//显示信息Invalidate(TRUE);}}CView::OnChar(nChar, nRepCnt, nFlags);}(5)对视图类的OnDraw函数进行重载,根据成员变量的值(实际对应着按键的状态),显示相关信息。
MFC消息映射原理仿真

#include"my.h"CMyWinApp theApp;//global objectBOOL CMyWinApp::InitInstance(){cout<<"CMyWinApp::InitInstance \n";m_pMainWnd=new CMyFrameWnd;return TRUE;}CMyFrameWnd::CMyFrameWnd(){Create();}BEGIN_MESSAGE_MAP(CMyWinApp,CWinApp)ON_COMMAND(CMyWinAppid,0)END_MESSAGE_MAP()BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd) ON_COMMAND(CMyFrameWndid,0)END_MESSAGE_MAP()BEGIN_MESSAGE_MAP(CMyDoc,CDocument)ON_COMMAND(CMyDocid,0)END_MESSAGE_MAP()BEGIN_MESSAGE_MAP(CMyView,CView)ON_COMMAND(CMyViewid,0)END_MESSAGE_MAP()void printlpEntries(AFX_MSGMAP_ENTRY* lpEntry) {struct{int classid;char* classname;}classinfo[]={CCmdTargetid,"CCmdTarget ",CWinThreadid,"CWinThread ",CWinAppid, "CWinApp ",CMyWinAppid, "CMyWinApp ",CWndid, "CWnd ",CFrameWndid, "CFrameWnd ",CMyFrameWndid,"CMyFrameWnd ",CViewid, "CView ",CMyViewid, "CMyView ",CDocumentid, "CDocument ",CMyDocid, "CMyDoc ",0, " "};for(int i=0;classinfo[i].classid!=0;i++){if(classinfo[i].classid==lpEntry->nID){cout<<lpEntry->nID<<" ";cout<<classinfo[i].classname<<endl;break;}}}void main(){CWinApp* pApp=AfxGetApp();pApp->InitApplication();pApp->InitInstance();pApp->Run();cout<<endl<<endl;CMyDoc* pMyDoc=new CMyDoc;CMyView* pMyView=new CMyView;CFrameWnd* pMyFrame=(CFrameWnd*)pApp->m_pMainWnd;pMyFrame->m_pViewAxtive=pMyView;pMyView->m_pDocument=pMyDoc;cout<<endl<<"pMyFrame received a WM_CREATE,routing path:"<<endl;AfxWndProc(0,WM_CREATE,0,0,pMyFrame);cout<<endl<<"pMyView received a WM_PAINT,routing path:"<<endl;AfxWndProc(0,WM_PAINT,0,0,pMyView);cout<<endl<<"pMyView received a WM_COMMMAND,routing path:"<<endl;AfxWndProc(0,WM_COMMAND,0,0,pMyView);cout<<endl<<"pMyFrame received a WM_COMMAND,routing path:"<<endl;AfxWndProc(0,WM_COMMAND,0,0,pMyFrame);}。
谈谈MFC中的消息映射

谈谈MFC中的消息映射作者:未知文章来源:网络引言:众所周知,windows是基于消息驱动的,作好消息处理是WINDOWS编程的关键任务之一,用VC制作WINDOWS程式同样离不开消息的处理。
虽然VC++6的类向导可以完成绝大部分工作,但不幸的是,它并不能完成所有的工作。
这就要求我们对 VC中消息的处理有一个比较清淅的认识。
只有这样才可能在必要的时候亲自动手完成一些复杂的消息映射处理。
在MFC中消息是通过一种所谓的消息映射机制来处理的。
其实质是一张消息及其处理函数的一一对应表以及分析处理这张表的应用框架内部的一些程序代码.这样的好处是可以避免像早期的SDK编程一样需要罗列一大堆的CASE语句来处理各种消息.由于不同种类的消息其处理方法是不同的,所以我们有必要先弄清楚 WINDOWS消息的种类。
背景:WINDOWS 消息的种类WINDOWS中消息主要有以下三种类型:1、标准的WINDOWS消息:这类消息是以WM_为前缀,不过WM_COMMAND例外。
例如: WM_MOVE、WM_QUIT等.2、命令消息:命令消息以WM_COMMAND为消息名.在消息中含有命令的标志符ID,以区分具体的命令.由菜单,工具栏等命令接口对象产生.3、控件通知消息:控件通知消息也是以WM_COMMAND为消息名.由编辑框,列表框,子窗口发送给父窗口的通知消息.在消息中包含控件通知码.以区分具体控件的通知消息.其中标准的WINDOWS消息及控件通知消息主要由窗口类即直接或间接由CWND类派生类处理.相对标准WINDOWS消息及控件通知消息而言,命令消息的处理对象范围就广得多.它不仅可以由窗口类处理,还可以由文档类,文档模板类及应用类所处理。
方法:不同种类消息的映射方法。
在以上三种消息中,标准的WINDOWS消息映射是相当简单的。
可直接通过类向导完成不同消息的映射处理,所以不在本文讨论之列。
凡是从CcmdTarget类派生的类都可以有消息映射.消息映射包括如下两方面的内容:在类的定义文件中(.H)中加上一条宏调用:DECLARE_MESSAGE_MAP()通常这条语句中类定义的最后.在类的实现文件(.CPP)中加上消息映射表:BEGIN_MESSAGE_MAP(类名,父类名)………..消息映射入口项.……….END_MESSAGE_MAP( )幸运的是除了某些类(如没有基类的类或直接从CobjectO类派生的类)外.其它许多类均可由类向导生成.尽管生成的类只是一个框架,需要我们补充内容.但消息映射表已经为我们加好了.只是入口项有待我们加入.命令消息映射入口项是一个ON_COMMAND的宏.比如文件菜单下的"打开…"菜单(ID 值为ID_FILE_OPEN)对应的消息映射入口项为:ON_COMMAND(ID_FILE_NEW,OnFileOpen)加入消息映射入口项之后需要完成消息处理函数.在类中消息处理函数都是类的成员函数,要响应一个消息,就必须定义一个该消息的处理函数.定义一个消息处理函数包括以下三方面的内容.1.在类定义中加入消息处理函数的函数原型(函数声明)2.在类的消息映射表中加入相应的消息映射入口项.3.在类的实现中加入消息处理函数的函数体.需要说明的是消息处理函数的原型一定要以afx_msg打头.比如:afx_msg OnFileOpen();// 函数原型作为约定.消息处理函数一般以On打头但有时我们可能想用一个消息处理函数来处理一批消息。
MFC消息映射机制过程

MFC消息映射机制过程1:windows OS事件驱动策略基于3种消息。
标准消息、通告消息、命令消息。
2:“事件”就是“消息”,事件是有形形象的,是站在⼈类能理解的⾓度来定义的。
消息是⽆形抽象的,是站在OS能理解的⾓度来定义的。
3:我把按下⿏标左键这⼀事件转换成WM_LBUTOONDOWN消息来告诉OS我做了按下⿏标左键这了件事情。
现在OS知道了我做了按下⿏标左键这了件事情了,那么OS怎么处理呢?3.1:消息响应函数原型//{{AFX_MSG(CMyView)afx_msg void OnLButtonDown(UINT nFlags,CPoint point);//}}AFX_MSGDECLARE_MESSAGE_MAP()3.2:ON_WM_LBUTTONDOWN消息映射宏BEGIN_MESSAGE_MAP(CMyView, CView)//{{AFX_MSG_MAP(CMyView)ON_WM_LBUTTONDOWN()//}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)END_MESSAGE_MAP()3.3:消息响应函数的定义void CMyView::OnLButtonDown(UINT nFlags, CPoint point){// TODO: Add your message handler code here and/or call defaultMessageBox("WM_LBUTTONDOWN");CView::OnLButtonDown(nFlags, point);}4:⾄此,我们从按下⿏标左键到看到如下图的效果,OS完成了对事件做出的反应。
第3Windows消息映射

• 本节是MFC编程的第一节,主要介绍Windows程序设计不同于MS-DOS编程模 式的界面问题。
• 视图实际上就是一个“窗口”,它具有Windows应用程序窗口的一般特性, 即用户可以对其缩放、打开或关闭、移动、最小化和最大化等操作。实际 上,MFC程序中的视图就是MFC类库中的CView或CView的派生类创建的一个 对象,前文提到过,类的对象的属性是由它的数据成员决定的,而它的行 为是由其成员函数决定的,对此,视图对象也不例外。
• MM_TEXT映射模式是一种逻辑坐标映射模式,逻辑坐标是在 逻辑上定义的坐标,如可以在x和y轴方向上无限延伸,而 基于设备的坐标,则取决于分辨率,而且左上角和右下角 的坐标在特定分辨率情况下是固定的。如有滚动条的视图, 有个点的逻辑坐标是(0,0),如果该滚动条向下滚动, 则该逻辑点就会变得不可见,虽然该应用程序的左上角设 备坐标没有变化,但它映射的逻辑坐标已经改变了。
•第7页/共13页
3.5.3 固定比例映射模式
• 固定比例映射模式顾名思义就是将模式的逻辑单 位固定下来,主要有5种:
• MM_LOENGLISH:该模式的逻辑单位是0.01英寸。 • MM_HIENGLISH:该模式的逻辑单位是0.001英寸。 • MM_LOMETRIC:该模式的逻辑单位是0.1毫米。 • MM_HIMETRIC:该模式的逻辑单位是0.01毫米。 • MM_TWIPS:该模式的逻辑单位是1/1440英寸。
• MM_ANISOTROPIC:该模式下的横纵坐标可以单独 变化,如将横坐标扩大10倍,则原来的视图上的 圆则变成椭圆了。
•第9页/共13页
3.5.5 坐标转换
• 设置了映射模式后,开发人员可以很方便地使用逻辑坐标 作为参数来进行程序设计,但从Windows的鼠标消息所获得 的鼠标单击的坐标值却是设备的坐标值,因此坐标转换直 接关系到使用应用软件的用户和程序间进行正常的通信。
MFC中的消息映射机制及其在程序设计中的应用 (1)

_T<9]V)T;;7<TV)78N+9#?4."0+3X’’J +_X’4+3X’’5 EEAA7*\V);<V)78N+9#?4."0+3X’’5 ‘]V+‘))7]MN9MVTM9KV+‘8^J‘#T("0+%HY5
((
EEOO7*\V);<V)78 T]MV)T;;7<TV)78N5
这里主要进行消息映射的实现 " 把它和 消 息 处 理 函 数 联 系 在 一起 % 其中出现三个宏 " 第一个宏是 _T<9]V)T;;7<TV)78 有两 个参数" 分别是拥有消息表格的类及其父类% 第二个宏是 ‘]V+‘))7]M " 指定命令消息的处理函数名称 " 把各种各样的消 ! 下转第 "#$ 页 %
" #$%&’() 的消息循环概述
!"#(%&’ 系 统 为 每 一 个 激 活 的 !"#(%&’ 程 序 实 例 创 建 和 管 理各自的消息队列 ! 当键盘或鼠标事件发生时 "!"#(%&’ 系统将这
些事件转换为消息并放人应用程序实例对应的消 息 队 列 中 " 按 要 求 的 消 息 结 构 # 即 );< 消 息 记 录 结 构 $ 打 包 成 相 关 的 消 息 " 然 后 把它发给相应的窗口过程处理 " 指导它自己的窗 口 函 数 完 成 相 应 任务 % 6"#$%&’ 程序 以 6"#)2"# 作 为 程 序 的 入 口 点 " 以 下 是 一 个 简 化的 6"#=> 程序的主体 " 通过 &?"34 语句实现消息循环 &
消息映射声明_C++语言程序设计_[共2页]
![消息映射声明_C++语言程序设计_[共2页]](https://img.taocdn.com/s3/m/367adcda4a7302768f993961.png)
};
对应地,BEGIN_MESSAGE_MAP 定义了两个版本,分别用于静态或者动态链接到 MFC DLL
的情形。END_MESSAGE_MAP 相对简单,只有一种定义。
const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = \ {\
#else #define BEGIN_MESSAGE_MAP(theClass, baseClass) \ const AFX_MSGMAP* theClass::GetMessageMap() const \ { return &theClass::messageMap; } \ AFX_DATADEF const AFX_MSGMAP theClass::messageMap = \ { &baseClass::messageMap, &theClass::_messageEntries[0] }; \ const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = \ {\
息映射条目。一个消息映射条目可以用 AFX_MSGMAP_ENTRY 结构来描述。
AFX_MSGMAP_ENTRY 结构的定义如下。
struct AFX_MSGMAP_ENTRY { //Windows 消息 ID UINT nMessage;
246
const AFX_MSGMAP* theClass::GetMessageMap() const \ { return &theClass::messageMap; } \
消息映射

Windows消息的产生:1用户按键或者鼠标操作可以产生消息,如WM_KEYDOWN,WM_LBUTTONDOWN等;2系统可以自己产生消息,如,创建窗口的时候会产生WM_CREATE,WM_TIMER等;3应用程序间可以定义自己的消息,在应用程序间进行消息通讯;Windows消息的分类:Windows消息的分类1.标准消息(除WM_COMMAND 外的WM_消息)从CWnd派生的类可接收该消息2.命令消息(以WM_COMMAND 形式出现)菜单,快捷键,工具条按钮消息,从CCmdTarget派生的可以接收3.通告消息: 控件产生的消息(按钮等),从CCmdTarget派生的可以接收从CWnd派生的类可接收3种消息,从CCmdTarget派生接收2,34. 用户自定义消息:为了跟系统消息区分,系统专门划分一段消息编号区间来让用户定义自己的消息。
#define MY_MESSAGE WM_USER + 1 // 用户自定义消息菜单命令路由:消息传递:1框架2视类消息处理:1视类2视类传给文档类3文档类传回视类,再传给框架4应用程序类Windows32消息的结构:MSG 结构的定义如下:typedef struct tagMSG{HWND hwnd; //接收消息的窗口句柄UINT message; //消息标识(ID)WPARAM wParam; //第一个消息参数LPARAM lParam; //第二个消息参数DWORD time; //消息产生的时间POINT pt; //消息产生时鼠标的位置} MSG;回忆窗口处理函数首部,主消息循环相关重要代码。
MFC消息处理机制:所谓消息映射,简单地讲,就是让程序员指定要某个MFC类(有消息处理能力的类)处理某个消息。
MFC提供了工具ClassWizard来帮助实现消息映射,在处理消息的类中添加一些有关消息映射的内容和处理消息的成员函数。
程序员将完成消息处理函数,实现所希望的消息处理能力。
基于mfc的实验报告

基于mfc的实验报告摘要本实验旨在通过使用MFC(Microsoft Foundation Classes)开发框架,实现一个简单的图形化界面程序。
通过这次实验,我深入理解了MFC框架的基本原理和开发流程,并成功完成了一个简单的图形化界面程序。
1. 引言MFC是微软公司开发的一套C++类库,用于创建Windows平台上的应用程序。
它建立在Windows API之上,简化了Windows操作系统的编程方式。
MFC 提供了一系列的类和函数,包括窗口(Window)、对话框(Dialog)、消息映射(Message Map)等,极大地简化了Windows应用程序的开发过程。
2. 实验目的本实验主要目的是熟悉MFC框架的基本原理和开发流程,实现一个简单的图形化界面程序。
通过本实验,能够掌握MFC框架中的窗口创建、消息处理、界面设计等基本概念和操作。
3. 实验过程3.1 环境配置首先,需要在计算机上安装Visual Studio和MFC组件。
打开Visual Studio,创建一个新的MFC应用程序项目,并选择对话框类型作为项目的基础结构。
3.2 窗口创建在MFC应用程序中,窗口是最基本的界面单位。
通过菜单选择“添加类”的方式,创建一个新的对话框类,并继承自CDialog类。
在新建的对话框类中,可以定义与界面相关的成员变量和控件。
3.3 控件添加在对话框设计界面中,可以通过拖拽和调整控件的方式,向对话框中添加各种控件,如按钮、文本框、列表框等。
每个控件都有自己的属性和事件响应函数。
3.4 消息映射消息映射是MFC框架的核心概念之一。
通过消息映射,可以将用户的操作(如点击按钮)与特定的函数关联起来。
在对话框类中,可以通过DECLARE_MESSAGE_MAP和BEGIN_MESSAGE_MAP宏定义来实现消息映射关系的建立。
3.5 编译和运行完成界面设计和消息映射后,即可对程序进行编译和运行。
在编译过程中,MFC 会自动将资源文件编译成可执行的文件。
MFC教程(4)-- 消息映射的实现

MFC教程(4)-- 消息映射的实现(1)消息映射的实现Windows消息概述Windows应用程序的输入由Windows系统以消息的形式发送给应用程序的窗口。
这些窗口通过窗口过程来接收和处理消息,然后把控制返还给Windows。
消息的分类队列消息和非队列消息从消息的发送途径上看,消息分两种:队列消息和非队列消息。
队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。
这里,对消息队列阐述如下:Windows维护一个系统消息队列(System message queue),每个GUI线程有一个线程消息队列(Thread message queue)。
鼠标、键盘事件由鼠标或键盘驱动程序转换成输入消息并把消息放进系统消息队列,例如WM_MOUSEMOVE、WM_LBUTTONUP、WM_KEYDOWN、WM_CHAR等等。
Windows每次从系统消息队列移走一个消息,确定它是送给哪个窗口的和这个窗口是由哪个线程创建的,然后,把它放进窗口创建线程的线程消息队列。
线程消息队列接收送给该线程所创建窗口的消息。
线程从消息队列取出消息,通过Windows把它送给适当的窗口过程来处理。
除了键盘、鼠标消息以外,队列消息还有WM_PAINT、WM_TIMER和WM_QUIT。
这些队列消息以外的绝大多数消息是非队列消息。
系统消息和应用程序消息从消息的来源来看,可以分为:系统定义的消息和应用程序定义的消息。
系统消息ID的范围是从0到WM_USER-1,或0X80000到0XBFFFF;应用程序消息从WM_USER(0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到0X7FFF 范围的消息由应用程序自己使用;0XC000到0XFFFF范围的消息用来和其他应用程序通信,为了ID的唯一性,使用::RegisterWindowMessage来得到该范围的消息ID。
但是在当前例子中,当前对象的类CTview没有覆盖该函数,所以CWnd的WindowProc被调用。
MFC消息映射机制详解

MFC消息映射机制详解分类: MFC2010-04-18 02:22 3322人阅读评论(0) 收藏举报Windows程序和MFC程序是靠消息驱动的,他们对于消息的处理本质上是相同的。
只是Windows程序对于消息处理的过程十分清晰明了,MFC程序则掩盖了消息处理的过程,以消息映射的方式呈现在开发者面前,使得开发消息的处理十分简单。
用多了mfc就想对它的消息映射机制有一个本质的了解,下面将对消息映射做详细的分析。
当然,在分析MFC消息映射之前首先对Windows程序的消息处理过程进行一个简单的描述。
1、Windows应用程序消息处理Windows程序都维护有自己的消息队列,保存了队列消息(当然也有非队列消息,它们直接发给窗口),并用过消息循环对消息进行处理。
消息循环首先通过GetMessage取得消息并从队列中移走,对于加速键会调用TranslateAccelerator函数,对其进行翻译和处理,如果处理成功就不在调用TranslateMessage。
如果不是加速键,就进行消息的转换和派发,让目的窗口的窗口过程来处理消息。
示例代码:[cpp] view plaincopyprint?1.// 主消息循环:2.while (GetMessage(&msg, NULL, 0, 0))3.{4.if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))5.{6.TranslateMessage(&msg);7.DispatchMessage(&msg);8.}9.}真正处理消息的是所谓的窗口过程(LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)),这个函数的参数记录了过程对应的窗口、消息的ID以及参数,在其内部开发者可以实现自己需要的消息处理功能。
中国石油大学(华东)VC 实验报告实验三_MFC消息映射编程实验

END_MESSAGE_MAP()
······
2.在类声明中声明成员函数;
DECLARE_MESSAGE_MAP()
3.在类的实现部分实现成员函数;
四、鼠标绘图功能的实现代码
1.头文件
#include "afxwin.h"
class CDemoWnd:public CFrameWnd
ON_MESSAGE(WM_PAINT,OnPaint)
ON_MESSAGE(WM_LBUTTONDOWN,OnLButtonDown)
ON_MESSAGE(WM_MOUSEMOVE,OnMouseMove)
END_MESSAGE_MAP()
LRESULT CDemoWnd::OnPaint(WPARAM wParam,LPARAM lParam)
2.源文件
#include "Demo.h"
CDemoWnd::CDemoWnd()// 构造函数
{
m_nX0 = 0;
m_nY0 = 0;
m_nX1 = 0;
m_nY1 = 0;
}
CDemoWnd::~CDemoWnd()// 析构函数
{
}
BEGIN_MESSAGE_MAP(CDemoWnd,CFrameWnd)
{
CClientDC dc(this);
dc.SelectStockObject(WHITE_PEN);// 利用白色的画笔擦除原有图形
if(wParam & MK_CONTROL && wParam & MK_LBUTTON)
消息映射宏_C++语言程序设计_[共2页]
![消息映射宏_C++语言程序设计_[共2页]](https://img.taocdn.com/s3/m/dea657bea45177232e60a260.png)
24811.4.7 消息映射实现消息映射的具体实现是通过初始化声明中定义的静态成员函数_messageEntries和messageMap,实现所声明的静态或虚拟函数GetMessageMap、_GetBaseMessageMap的。
这样,在进入WinMain函数之前,每个可以响应消息的MFC类都生成了一个消息映射表,程序运行时通过查询该表判断是否需要响应某条消息。
1.消息映射入口表(消息映射数组)初始化消息映射数组的元素是消息映射条目,条目的格式符合结构AFX_MESSAGE_ENTRY的描述。
因为,要初始化消息映射数组,就必须使用符合该格式的数据来填充:如果指定当前类处理某个消息,则把和该消息有关的信息和消息处理函数的地址及原型组合成为一个消息映射条目,并加入到消息映射数组中。
MFC根据消息的不同和消息处理方式的不同,把消息映射划分成若干类别,每一类的消息映射至少有一个共性:消息处理函数的原型相同。
对每一类消息映射,MFC定义了一个宏来简化初始化消息数组的工作。
例如,前文提到的ON_COMMAND宏用来映射命令消息,只要指定命令ID和消息处理函数即可,对这类命令消息映射条目,其他四个属性都是固定的。
ON_COMMAND 宏的初始化内容如下。
{WM_COMMAND,CN_COMMAND,(WORD)ID_APP_ABOUT,(WORD)ID_APP_ABOUT,AfxSig_vv,(AFX_PMSG)OnAppAbout}这个消息映射条目的含义是:消息ID是ID_APP_ABOUT,OnAppAbout被转换成AFX_PMSG 指针类型,AfxSig_vv是MFC预定义的枚举变量,用来标识OnAppAbout的函数类型为参数空(V oid)、返回空(V oid)。
在消息映射数组的最后,是宏END_MESSAGE_MAP的内容,它标识消息处理类的消息映射条目的终止。
2.messageMap的初始化messageMap的类型是AFX_MESSMAP。
VC消息映射

VC消息映射假如代码⽣成⼀个菜单项。
如下:cMenu.AppendMenu(MF_POPUP,300,_T("⽂件"));怎样让这个菜单项响应事件呢?⾸先在.h中声明:afx_msg void Hi();//声明⼀个消息处理函数Hi();然后消息映射表⾥添加映射:BEGIN_MESSAGE_MAP(CUseControlDlg, CDialog)ON_COMMAND(300, &CUseControlDlg::Hi)//第⼀个参数是控件的IDEND_MESSAGE_MAP()最后是函数体:void CUseControlDlg::Hi(){// TODO: 在此添加命令处理程序代码AfxMessageBox(_T("hi"));}这⾥⼀个知识点:Resource.h打开,可以看到你即使给控件使⽤了字母ID也是对应到⼀个宏。
对应数字。
#define IDC_BUTTON_OK 1001视类增加⼀个消息相应函数后,在源⽂件中都会增加三处代码。
1 消息相应函数原型。
在CDrawView中会有这样的代码:⼤⽓象// Generated message map functionsprotected://{{AFX_MSG(CMainFrame)afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);afx_msg void OnLButtonDown(UINT nFlags, CPoint point);//}}AFX_MSGDECLARE_MESSAGE_MAP()在DECLARE_MESSAGE_MAP()宏上有两个AFX_MSG注释宏,在这两个注释宏之间有⼀个函数原型OnLButtonDown,因为她位于两个注释宏之间,所以是以灰⾊显⽰,还函数声明的前部有⼀个afx_msg限定符,这也是⼀个宏。
该宏表明这个函数是⼀个消息响应函数的声明。
Visual C++:消息映射、消息路由原理

本文作者:黄邦勇帅(原名:黄勇)本文不会对C++语法进行讲解(只会对不常用语法进行分析讲解),本文假设读者已经很熟悉C++语法了,若读者对C++语法不熟悉,请参阅本人所编著C++语法系列专题文章。
本文是VC++中的难点内容,本文对MFC中的消息映射原理,从最基础的整体设计架构开始进行讲解,并以最简单的映射开始进行模仿,然后逐步对其原理加深讲解,并以完整的可运行的程序代码进行验证,每个程序代码验证一个原理。
对复杂的消息路由原理,本文使用单独的C++程序对其内部核心原理作了深入的分析,从而避开了复杂的MFC源代码(特别是长长的标识符名称)的庞大结构及各种迂回调用,并以完整的可运行的示例代码进行模仿演示,并对其运行原理作了详尽的示例图分析,最后对MFC实现消息路由的源代码作了分析,结合模仿程序再加上对源代码的分析,让读者彻底弄明白MFC的消息是怎样进行映射,是怎样进行路由的,本文主要讲解MFC的消息映射内部原理,对于消息映射的使用是比较简单的,本文也作了示例讲解。
读完本文,读者会对MFC的消息映射内部原理有一个完全的清晰的认识,会让MFC消息映射原理变得不再那么复杂,那么难,而是简单易懂。
本文内容由浅入深,内容较为全面,本文使用VS2005、VS2010、VS2015编译器进行讲解,其中的源代码摘自VC++2005。
本文内容完全属于个人见解与参考文献的作者无关,限于水平有限,其中难免有误解之处,望指出更正。
声明:禁止抄袭、复印、转载本文,本文作者拥有完全版权。
主要参考文献:1、深入浅出MFC(第2版) 侯俊杰著华中科技大学出版社出版日期不祥2、VC++深入详解孙鑫余安萍编著电子工业出版社2006年6月3、windows程序设计(第5版珍藏版) [美]Charles Petzold著方敏张胜梁路平赵勇等译清华大学出版社2010年9月4、Visual C++2013入门经典(第7版) [美] Ivor Horton著李周芳江凌译清华大学出版社2015年1月第3部分MFC消息映射及内部原理专题1、为讲解方便,本文不使用宽字符。
关于MFC的消息映射

关于MFC的消息映射转自:/article/200501/54449.html近来学习MFC,对其中的消息映射机制一直一知半解,从网上搜了些资料,不是讲解的太表面化,就是过于详细,让人不禁头大。
脑子正处于迷糊状态中,无意搜到了上面链接处的一点资料,其对用于消息映射的宏定义进行了简单注释,我将这些资料进行了整理,力求能给其他朋友一点帮助。
所谓的消息映射,就是说对于每一条消息,都对应有一个处理函数对该消息进行响应。
例如,将按下鼠标左键看做一条消息,当鼠标左键按下时,弹出一个对话框,则这里的消息映射:按下鼠标左键(消息)——弹出一个对话框(消息处理函数)。
要理解MFC的消息映射机制需要理解几个关键的宏定义:DECLARE_MESSAGE_MAP、BEGIN_MESSAGE_MAP、END_MESSAGE_MAP以及向类中添加类自身所要处理的消息的宏(这里以ON_COMMAND为例)。
1、DECLARE_MESSAGE_MAP一般,MFC中的消息处理函数大都是某一个类的成员函数,在定义类的头文件中,我们在类定义中加入DECLARE_MESSAGE_MAP就表示该类支持消息映射。
#define DECLARE_MESSAGE_MAP() \private: \static const AFX_MSGMAP_ENTRY _messageEntries[]; \protected: \static AFX_DATA const AFX_MSGMAP messageMap; \static const AFX_MSGMAP* PASCAL _GetBaseMessageMap(); \virtual const AFX_MSGMAP* GetMessageMap() const; \DECLARE_MESSAGE_MAP()这个宏的作用有3:⑴在类中插入一个静态成员_messageEntries,这是用来存放类要处理的消息的数组(即类本身的消息映射表);⑵另一个静态成员massageMap用来指向基类的消息映射表;⑶安插一个虚函数,其内容有待实现。
实验3消息映射

宁夏师范学院数学与计算机科学学院
《面向对象程序设计》实验报告
实验序号:实验项目名称:消息映射
学号姓名陈萃专业班级级电子科学与技术实验地点文科楼指导教师马学梅时间
一、实验目的及要求
、理解应用程序运行的机制;
、利用为应用程序添加消息;
、编写自定义消息应用程序;
、掌握中的程序调试方法;
二、实验设备(环境)及要求
硬件:(以上,以上内存)、因特网接入;
软件:操作系统、、。
三、实验内容与步骤
说明:对下述实验内容给出实验结果并分析总结。
1、对照教材完成例题,例题和例题中的相关内容。
【例】
实验结果:
分析总结:利用[]创建一个单文档应用程序框架的步骤。
【例】
实验结果:
分析总结:利用消息映射来处理消息。
添加消息处理函数,并观察对消息映射函数进行声明所使用的映射宏。
【例】
实验结果:
1.自定义消息鼠标右键被按下。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
MFC 消息映射编程实验实验报告姓名:杨培培班级:电气12级3班12053307【预备知识】1、消息映射消息映射本质上就是一个数组,MFC 使用消息映射建立消息和类的成员函数的对应关系。
消息映射数组中存储的信息(1) 所处理的消息;(2) 消息应用的控件ID,或者ID 范围;(3) 消息所传递的参数;(4) 消息所期望的返回值。
2、消息映射宏下面介绍常用的两个消息映射宏:(1)ON_MESSAGE:处理任意消息语法规则:ON_MESSAGE(ID,func)LRESULT func(WPARAM wParam, LPARAM lParam);举例:映射鼠标左键按下消息ON_MESSAGE(WM_LBUTTONDOWN, OnLButtonDown)LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam);(2)ON_COMMAND:处理WM_COMMAND 消息语法规则:ON_COMMAND(ID,func)void func( );举例:映射菜单项命令消息ON_COMMAND(ID_OPER_TEST, OnOperTest)void OnOperTest ( );3、消息映射步骤MFC 中手工添加消息映射按照如下步骤进行:(1)在BEGIN_MESSAGE_MAP 和END_MESSAGE_MAP 之间添加消息映射宏;BEGIN_MESSAGE_MAP(CDemoView, CView)ON_MESSAGE(WM_KEYDOWN, OnKeyDown)ON_COMMAND(ID_OPER_TEST, OnOperTest)END_MESSAGE_MAP( )(2) 在类声明中声明成员函数;(3) 在类的实现部分实现成员函数。
【实验目的】(1) 熟悉Visual Studio 开发环境;(2) 掌握消息映射机制的基本原理和手工添加消息映射的方法;(3) 熟练掌握在Visual Studio 开发环境调试程序的方法。
【实验内容】设计 MFC 应用程序,手工添加消息映射,实现下面的功能:(1) 按下CTRL 键,拖动鼠标绘制矩形;(2) 按下SHIFT 键,拖动鼠标绘制椭圆。
【实验报告】(1) 总结手工添加消息映射的基本步骤;①在BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间添加消息映射宏;BEGIN_MESSAGE_MAP(CDemoView, CView)ON_MESSAGE(WM_LBUTTONDOWN, OnLButtonDown)ON_COMMAND(ID_OPER_TEST, OnOperTest)END_MESSAGE_MAP( )②在类声明中声明成员函数;③在类的实现部分实现成员函数。
(2) 列出鼠标绘图功能的实现代码;源文件 Demo.cpp 代码#include "Demo.h"BEGIN_MESSAGE_MAP(CDemoWnd, CFrameWnd)ON_MESSAGE(WM_LBUTTONDOWN,OnLButtonDown)ON_MESSAGE(WM_MOUSEMOVE,OnMouseMove)ON_MESSAGE(WM_LBUTTONUP,OnLButtonUp)ON_MESSAGE(WM_TIMER,OnTimer)END_MESSAGE_MAP()LRESULT CDemoWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam){m_X0 = m_X1 = LOWORD(lParam);m_Y0 = m_Y1 = HIWORD(lParam);return 0;}LRESULT CDemoWnd::OnMouseMove(WPARAM wParam, LPARAM lParam){/*CClientDCdc(this);dc.SelectStockObject(WHITE_PEN);if((wParam& MK_LBUTTON) && (wParam& MK_CONTROL)){dc.Ellipse(m_X0,m_Y0,m_X1,m_Y1);}if((wParam& MK_LBUTTON) && (wParam& MK_SHIFT)){dc.Rectangle(m_X0,m_Y0,m_X1,m_Y1);}m_X1 = LOWORD(lParam);m_Y1 = HIWORD(lParam);dc.SelectStockObject(BLACK_PEN);if((wParam& MK_LBUTTON) && (wParam& MK_CONTROL)){dc.Ellipse(m_X0,m_Y0,m_X1,m_Y1);}if((wParam& MK_LBUTTON) && (wParam& MK_SHIFT)){dc.Rectangle(m_X0,m_Y0,m_X1,m_Y1);}return 0; */CClientDC dc(this);CPen hp,*pOldPen,hp1;hp.CreatePen(PS_SOLID,3,RGB(255,0,0));pOldPen=dc.SelectObject(&hp);CPoint point [3];point [0] = CPoint(m_X0,(m_Y0+m_Y1)/2);point [1] = CPoint(m_X0,m_Y0);point [2] = CPoint((m_X0+m_X1)/2, m_Y0);if((wParam & MK_CONTROL) && (wParam & MK_LBUTTON)) //按下ctrl键,拖动鼠标绘制矩形{dc.Rectangle(m_X0,m_Y0,m_X1,m_Y1);}if((wParam & MK_SHIFT) && (wParam & MK_LBUTTON))//按下shift键,拖动鼠标绘制椭圆{dc.Rectangle(m_X0,m_Y0,(m_X0+m_X1)/2,(m_Y0+m_Y1)/2);hp1.CreatePen(PS_SOLID,3,RGB(255,255,255));pOldPen=dc.SelectObject(&hp1);dc.Polyline(point, 3);dc.SelectObject(pOldPen);dc.Ellipse(m_X0,m_Y0,m_X1,m_Y1);}m_X1= LOWORD(lParam);m_Y1 = HIWORD(lParam);return 0;}LRESULT CDemoWnd::OnLButtonUp(WPARAM wParam, LPARAM lParam){/* CClientDCdc(this);dc.SelectStockObject(WHITE_PEN);if((wParam& MK_LBUTTON) && (wParam& MK_CONTROL)){dc.Ellipse(m_X0,m_Y0,m_X1,m_Y1);}if((wParam& MK_LBUTTON) && (wParam& MK_SHIFT)){dc.Rectangle(m_X0,m_Y0,m_X1,m_Y1);}m_X1 = LOWORD(lParam);m_Y1 = HIWORD(lParam);dc.SelectStockObject(BLACK_PEN);if(wParam& MK_CONTROL){dc.Ellipse(m_X0,m_Y0,m_X1,m_Y1);}if(wParam& MK_SHIFT){dc.Rectangle(m_X0,m_Y0,m_X1,m_Y1);}return 0; */m_X0=m_X1= LOWORD(lParam);m_Y0=m_Y1= HIWORD(lParam);return 0;}LRESULT CDemoWnd::OnLButton(WPARAM wParam, LPARAM lParam) {return 0;}BOOL CDemoApp::InitInstance(){CDemoWnd *pFrame = new CDemoWnd();pFrame->Create(0,_T("鼠标绘图程序"));pFrame->ShowWindow(m_nCmdShow);this->m_pMainWnd = pFrame;return TRUE;}头文件 Demo.h 代码#include <afxwin.h>class CDemoWnd: public CFrameWnd{public:int m_X0;int m_Y0;int m_X1;int m_Y1;protected:LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam);LRESULT OnMouseMove(WPARAM wParam, LPARAM lParam);LRESULT OnLButtonUp(WPARAM wParam, LPARAM lParam);LRESULT OnLButton(WPARAM wParam, LPARAM lParam);DECLARE_MESSAGE_MAP()};class CDemoApp: public CWinApp{public:BOOL InitInstance();};CDemoApp ThisApp; // 全局应用程序对象【实验结果】(3) 总结实验的心得体会,实验中遇到的困难以及解决的方法等。
在上课时,老师的上机演示,让我对MFC消息映射有了初步的了解,也让我对编程产生了兴趣。
本次实验考查了MFC消息映射编程,我熟悉了Visual Studio的开发环境,同时也掌握了消息映射机制的基本原理和手工添加消息映射的方法。
在实验过程中也遇到了一些困难,通过询问同学,和查阅资料,让我对MFC编程也有了进一步的认知,同时也使我完成了本次实验。