MFC消息映射机制
mfc的原理、机制与开发实例

mfc的原理、机制与开发实例MFC(Microsoft Foundation Class)是微软公司开发的一套面向对象的应用程序框架,用于简化Windows操作系统上的图形用户界面(GUI)应用程序的开发。
MFC提供了一系列的类和函数,使开发者能够更加方便地创建、管理和操作窗口、对话框、控件等GUI元素。
MFC的原理和机制主要基于C++语言和Windows操作系统的API (Application Programming Interface)。
MFC的核心类是CObject类,所有的MFC类都是从CObject类派生而来的。
MFC使用了一种称为消息映射(Message Mapping)的机制来处理用户界面的事件和消息。
当用户进行操作时,例如点击按钮、输入文本等,Windows操作系统会生成相应的消息,并将其发送给应用程序。
MFC通过消息映射将这些消息与相应的处理函数关联起来,从而实现对用户操作的响应。
MFC的开发实例可以通过一个简单的计算器程序来说明。
首先,我们需要创建一个对话框,用于显示计算器的界面。
在MFC中,可以使用CDialog类来创建对话框。
然后,我们需要在对话框中添加一些控件,例如按钮、文本框等,用于用户输入和显示计算结果。
在MFC中,可以使用CButton、CEdit等类来创建这些控件。
接下来,我们需要处理用户的操作。
例如,当用户点击按钮时,我们需要执行相应的计算操作。
在MFC中,可以通过消息映射来实现。
首先,我们需要在对话框类中添加一个消息映射函数,用于处理按钮的点击事件。
然后,我们需要在消息映射函数中编写相应的代码,例如获取用户输入的数字、进行计算等。
最后,我们需要将消息映射函数与按钮关联起来,以便在用户点击按钮时调用相应的函数。
除了处理用户的操作,MFC还提供了许多其他功能,例如文件操作、数据库访问、图形绘制等。
开发者可以根据自己的需求选择相应的MFC类和函数来实现这些功能。
mfc消息机制原理

MFC(Microsoft Foundation Classes)是一种用于开发Windows应用程序的C++类库,它建立在Win32 API之上,并提供了更高层次的抽象和封装。
在MFC中,消息机制是实现应用程序与用户交互和事件处理的基础。
MFC消息机制的原理如下:1.消息映射表:在MFC应用程序中,每个窗口类(如对话框类、视图类等)通常都有一个消息映射表(message map),用于将消息与相应的处理函数关联起来。
消息映射表是一个静态数据结构,通过DECLARE_MESSAGE_MAP宏进行声明,并在类的实现文件中使用BEGIN_MESSAGE_MAP和END_MESSAGE_MAP宏定义映射表的内容。
2.消息处理函数:每个消息映射表项将消息的ID(或者命令ID)与相应的消息处理函数绑定在一起。
消息处理函数是成员函数,由开发人员根据需要自行定义。
当相应的消息被触发时,系统会自动调用与该消息对应的处理函数。
3.消息循环:MFC应用程序在运行时通过消息循环(message loop)不断接收和分发消息。
消息循环负责从操作系统获取消息,并将消息派发给目标窗口的消息处理函数进行处理。
消息循环可以使用Run函数或AfxGetApp()->Run函数启动。
4.分发消息:当系统从消息队列中获取到一个消息后,会根据消息的目标窗口通过HWND来查找对应的CWnd对象,并调用该窗口的响应函数(如PreTranslateMessage、OnCmdMsg等)进行消息处理。
如果消息在目标窗口的消息映射表中找到了对应的处理函数,则将该消息转发给对应的处理函数进行处理。
5.消息处理:消息处理函数执行相应的逻辑,可以进行界面更新、控件操作、数据处理等操作。
处理函数的返回值通常是布尔型,表示是否终止消息的传递。
通过这种消息机制,MFC应用程序可以实现用户交互和事件处理的功能,使开发人员可以方便地处理窗口消息,响应用户操作,以及完成界面和数据之间的交互。
mfc 消息机制

mfc消息机制
MFC(Microsoft Foundation Class)是微软开发的一种面向对象的C++框架,用于Windows操作系统的应用程序开发。
MFC消息机制是MFC框架的核心之一,其基本原理是在窗口、控件等对象之间传递消息,以便处理事件和交互。
具体而言,MFC消息机制包括以下几个方面:1.消息循环:MFC使用一个消息循环来接受和处理Windows操作系统发送的Windows消息,处理完消息后将处理结果反馈给Windows操作系统。
2.消息映射:MFC中的控件和窗口都有一个关联的消息映射表,用于将Windows消息映射到应用程序代码中的相应处理函数上。
当某个控件或窗口收到消息后,根据消息类型在相应的消息映射表中查找对应的消息处理函数,并调用相应的处理函数处理消息。
3.消息类型:MFC处理的Windows消息类型包括键盘和鼠标消息、定时器消息、系统负载消息、窗口大小变化消息等等,具体的消息类型可以在MFC框架的文档中查找。
4.消息处理函数:MFC中的消息处理函数是C++成员函数,定义为afx_msg 修饰的函数,Windows消息处理函数命名时需要遵循一定的命名规则,例如OnPaint()函数用于处理绘图事件。
需要注意的是,MFC消息机制是针对Windows操作系统设计的,其他操作系统可能具有不同的消息机制。
此外,MFC框架已经不是微软推荐的最先进的应用程序开发框架,已经逐渐被其他框架和技术所取代,例如.NET Framework,WPF,UWP等。
MFC原理结构说明

MFC原理结构说明MFC(Microsoft Foundation Classes)是一种在Windows平台上开发图形用户界面(GUI)的框架。
MFC提供了一组类、函数和宏,用于简化Windows应用程序开发过程。
本文将对MFC的原理和结构进行详细说明。
一、MFC的原理1. 类与对象:MFC使用面向对象的编程模型,所有的窗口、控件、消息处理程序等都是通过类来定义和创建的。
每个MFC应用程序都包含一个CWinApp类的对象,这个对象是整个应用程序的入口点。
2. 消息映射机制:在MFC中,消息是Windows事件的一种表示。
MFC使用消息映射机制来处理这些消息。
消息映射机制是程序员在类中定义的一种技术,它将特定消息与对应的消息处理函数关联起来。
当收到消息时,MFC会自动调用相应的消息处理函数进行处理。
3. 消息与事件:在MFC中,消息是Windows事件的抽象表示,而事件是用户界面中的交互行为。
MFC提供了一系列预定义的消息类型,如鼠标点击、按键、窗口关闭等,程序员只需要在类中覆盖对应的消息处理函数,就可以处理这些消息。
4. 窗口类和控件类:在MFC中,窗口类和控件类是界面元素的基础。
MFC提供了一组窗口类(如CWnd、CFrameWnd)和控件类(如CButton、CEdit),程序员可以通过继承这些类来创建自定义的窗口和控件。
5. 文档视图模型:MFC中引入了文档视图模型(Document-View Model)的概念,用于实现应用程序的数据和界面的分离。
文档类(CDocument)管理应用程序的数据,视图类(CView)用于显示数据,而框架窗口类(CFrameWnd)则用于协调文档和视图之间的交互。
二、MFC的结构1. 应用程序类(CWinApp):应用程序类是MFC应用程序的入口点,它派生自CWinApp类。
应用程序类负责初始化应用程序的环境,包括注册窗口类、创建主窗口、加载并运行消息循环等。
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完成了对事件做出的反应。
mfc 信息机制

mfc 信息机制MFC信息机制MFC(Microsoft Foundation Class)是微软公司推出的一套用于Windows操作系统的C++类库,它为开发者提供了丰富的工具和组件,用于快速构建Windows应用程序。
在MFC中,信息机制是其重要特性之一,它提供了一种方便的方式来管理和传递应用程序中的消息。
一、消息机制的基本概念在MFC中,消息是指应用程序中发生的各种事件,比如鼠标点击、键盘输入、窗口关闭等。
消息机制是指MFC框架中的一套机制,用于处理和分发这些消息。
消息的处理过程包括两个关键组件:消息映射和消息处理函数。
1. 消息映射消息映射是指将消息和消息处理函数进行关联的过程。
通过在类的消息映射表中添加相应的消息和处理函数的映射关系,可以告诉MFC框架在收到某个消息时应该调用哪个函数进行处理。
消息映射表一般定义在类的声明中,使用宏来声明消息映射表的内容。
2. 消息处理函数消息处理函数是指用于处理特定消息的函数。
当MFC框架收到某个消息时,会根据消息映射表中的映射关系调用相应的消息处理函数。
消息处理函数可以是类的成员函数,也可以是全局函数,具体取决于消息映射表中的声明方式。
二、消息机制的应用场景消息机制在MFC中广泛应用于用户界面的交互和事件响应。
通过消息机制,开发者可以方便地处理用户的操作和系统的事件,实现各种功能和交互效果。
1. UI事件响应在MFC应用程序中,用户通过与界面上的控件进行交互来触发各种事件,比如按钮点击、菜单选择等。
通过消息机制,我们可以将这些事件与相应的处理函数进行关联,当用户触发某个事件时,可以执行相应的处理逻辑。
2. 窗口消息处理MFC中的窗口是指用户界面上的各种窗口元素,比如对话框、窗口、视图等。
窗口消息是指与窗口相关的各种事件,比如窗口创建、大小改变、关闭等。
通过消息机制,我们可以对窗口消息进行处理,实现窗口的初始化、布局、关闭等功能。
3. 自定义消息除了系统定义的消息类型,MFC还支持自定义消息。
MFC 消息映射机制详解

真正处理消息的是所谓的窗口过程(LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)),这个函数的参数记录了过程对应的窗口、消息的ID以及参数,在其内部开发者可以实现自己需要的消息处理功能。那消息分发是如何发送给窗口过程的呢?我们知道窗口创建过程中有一个注册窗口类的步骤,如下:
// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WINDOWSP);
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
原文出处: Ocean2006
Windows程序和MFC程序是靠消息驱动的,他们对于消息的处理本质上是相同的。只是Windows程序对于消息处理的过程十分清晰明了,MFC程序则掩盖了消息处理的过程,以消息映射的方式呈现在开发者面前,使得开发消息的处理十分简单。用多了mfc就想对它的消息映射机制有一个本质的了解,下面将对消息映射做详细的分析。当然,在分析MFC消息映射之前首先对Windows程序的消息处理过程进行一个简单的描述。
MFC的消息机制的实现原理和消息处理的过程

下面几节将分析MFC的消息机制的实现原理和消息处理的过程。
为此,首先要分析ClassWizard实现消息映射的内幕,然后讨论MFC 的窗口过程,分析MFC窗口过程是如何实现消息处理的。
1.消息映射的定义和实现1.MFC处理的三类消息根据处理函数和处理过程的不同,MFC主要处理三类消息:∙Windows消息,前缀以“WM_”打头,WM_COMMAND例外。
Windows消息直接送给MFC窗口过程处理,窗口过程调用对应的消息处理函数。
一般,由窗口对象来处理这类消息,也就是说,这类消息处理函数一般是MFC窗口类的成员函数。
∙控制通知消息,是控制子窗口送给父窗口的WM_COMMAND通知消息。
窗口过程调用对应的消息处理函数。
一般,由窗口对象来处理这类消息,也就是说,这类消息处理函数一般是MFC 窗口类的成员函数。
需要指出的是,Win32使用新的WM_NOFITY来处理复杂的通知消息。
WM_COMMAND类型的通知消息仅仅能传递一个控制窗口句柄(lparam)、控制窗ID和通知代码(wparam)。
WM_NOTIFY能传递任意复杂的信息。
∙命令消息,这是来自菜单、工具条按钮、加速键等用户接口对象的WM_COMMAND通知消息,属于应用程序自己定义的消息。
通过消息映射机制,MFC框架把命令按一定的路径分发给多种类型的对象(具备消息处理能力)处理,如文档、窗口、应用程序、文档模板等对象。
能处理消息映射的类必须从CCmdTarget类派生。
在讨论了消息的分类之后,应该是讨论各类消息如何处理的时候了。
但是,要知道怎么处理消息,首先要知道如何映射消息。
1.MFC消息映射的实现方法MFC使用ClassWizard帮助实现消息映射,它在源码中添加一些消息映射的内容,并声明和实现消息处理函数。
现在来分析这些被添加的内容。
在类的定义(头文件)里,它增加了消息处理函数声明,并添加一行声明消息映射的宏DECLARE_MESSAGE_MAP。
MFC六大核心机制

MFC六大核心机制1.消息映射机制:MFC使用明确的消息映射机制来处理用户界面和系统事件。
应用程序通过重写消息映射函数来处理不同的消息事件,如鼠标点击、按键操作等。
消息映射机制使得开发者可以方便地响应和处理不同的用户交互动作。
2. 文档视图(Doc/View)体系:MFC采用了文档视图体系,将应用程序数据(文档)和用户界面(视图)分离。
文档表示应用程序的数据,视图代表用户界面,通过文档视图模式可以实现多视图的显示和操作。
开发者可以自定义文档类和视图类,通过它们来管理和展示数据。
3.对象序列化机制:对象序列化是指将对象的状态转换为可以存储或传输的格式,以便于在不同的环境中恢复对象的状态。
MFC提供了强大的对象序列化支持,可以方便地对应用程序的数据进行存储和加载。
开发者只需将需要序列化的成员变量标记为可序列化,并实现相关的序列化函数即可实现数据的持久化。
4.多线程支持:MFC提供了多线程支持,使得应用程序可以在多个线程中同时执行任务。
开发者可以使用MFC提供的线程类来创建和管理线程,并通过消息机制进行线程间的通信。
多线程支持有助于提高应用程序的性能和响应能力。
MFC的运行时类是一组用于封装常用功能的类,包括字符串操作、容器类、文件I/O等。
这些类提供了方便、高效的操作接口,减少了开发者对底层操作的依赖。
开发者可以直接使用MFC提供的运行时类来简化开发过程。
6.扩展性:MFC提供了丰富的扩展性机制,包括自定义控件、自定义对话框、自定义视图等。
开发者可以通过派生已有的MFC类来创建自定义的控件或界面,以满足特定的应用程序需求。
扩展性机制使得开发者可以充分发挥自己的创造力和想象力,实现更加个性化的应用程序。
总结:MFC六大核心机制为开发者提供了丰富的类和功能,使得开发Windows图形界面应用程序更加简单和高效。
通过消息映射机制、文档视图体系、对象序列化机制、多线程支持、运行时类和扩展性机制,开发者可以轻松地实现各种应用程序的需求,并提供更好的用户体验。
mfc工作原理

mfc工作原理MFC(Microsoft Foundation Classes)是微软公司开发的一套用于Windows操作系统的应用程序框架,它在C++语言的基础上封装了一些常用的图形用户界面(GUI)功能,简化了Windows应用程序的开发过程。
本文将围绕MFC的工作原理展开阐述。
MFC的工作原理主要包括以下几个方面:1. 类库结构:MFC是一个面向对象的类库,它由一系列C++类组成。
这些类封装了Windows API的功能,提供了一种更加便捷的方式来创建和管理Windows应用程序。
MFC的类库结构包含了一些基本的类,如CObject、CWnd和CFrameWnd等,以及一些用于界面设计的类,如CButton、CEdit和CListBox等。
2. 消息映射机制:在MFC中,窗口类派生自CWnd类,通过消息映射机制来处理用户输入、系统消息等事件。
当用户操作窗口时,例如点击按钮、拖动滚动条等,系统会生成相应的消息,MFC会将这些消息映射到窗口类的成员函数上进行处理。
开发者只需重载对应的成员函数,就可以实现自定义的响应逻辑。
3. 对话框和控件:MFC提供了对话框和控件的封装,使得开发者可以方便地创建和管理用户界面。
对话框是一个独立的窗口,可以包含各种控件,如按钮、文本框、列表框等。
开发者可以使用MFC 提供的类来创建和设置对话框及其控件,通过消息映射机制来处理用户操作。
4. 文档视图模型(Document-View模式):MFC采用了文档视图模型来处理应用程序的数据和界面显示。
开发者可以通过MFC提供的类来创建文档类和视图类,文档类用于管理应用程序的数据,视图类用于显示和编辑数据。
MFC会自动处理文档和视图之间的关联,使得数据的修改能够实时反映到界面上。
5. 消息循环:MFC应用程序在启动后会进入一个消息循环,不断地接收和处理消息。
消息循环负责分发消息,并将消息传递给对应的窗口类进行处理。
MFC提供了一个消息映射表,用于将消息和相应的处理函数关联起来。
消息映射及MFC入门

MFC消息映射及MFC入门一、MFC消息映射机制在前面Win32Class工程中,我们进行了Win32环境下的“消息映射”。
其实,通过前面的过程,我们已经不知不觉的接触到了MFC消息映射的核心。
MFC环境下的消息映射,其原理和我们讲解过的Win32下的消息映射是类似的。
简单地讲,就是让程序员指定要某个MFC类(有消息处理能力的类)处理某个消息。
MFC提供了工具ClassWizard来帮助实现消息映射,在处理消息的类中添加一些有关消息映射的内容和处理消息的成员函数。
程序员负责编写消息处理函数的代码,实现所希望的功能。
可以通过如下的3个重要的宏来实现MFC消息映射,这些宏功能强大,其实现相对也比较复杂。
这里只要求我们会用就可以。
稍后我们会用其实际代码替换这些宏,就能理解了。
●DECLARE_MESSAGE_MAP:初始化消息映射表,实际上是给所在类添加几个用于消息处理的静态成员变量和静态或虚拟函数。
●BEGIN_MESSAE_MAP:开始消息映射。
●END_MESSAE_MAP:结束消息映射。
其他常见的、用于实现MFC消息的宏还有:●前缀为“ON_WM_”的宏:用于Windows消息的宏(不带参数)如:ON_WM_PAINT()把消息WM_PAINT映射到OnPaint函数。
●ON_COMMAND宏:通过参数指定命令ID和消息处理函数。
如ON_COMMAND(ID_EDIT_PASTE, OnEditPaste),其中第二个参数OnEditPaste 的原型说明为:void CView::OnEditPaste()。
●ON_UPDA TE_COMMAND_UI宏:用于更新菜单的状态。
●前缀为”ON_”控件通知消息宏:这类宏可能带有三个参数,如ON_CONTROL,就需要指定控制窗口ID,通知码和消息处理函数;也可能带有两个参数,如具体处理特定通知消息的宏ON_BN_CLICKED、ON_LBN_DBLCLK、ON_CBN_EDITCHANGE等,需要指定控制窗口ID和消息处理函数。
VS2010和MFC编程入门之5(MFC消息映射机制概述)

VS2010/MFC编程入门之五(MFC消息映射机制概述)这里是关于MFC消息映射机制的内容。
Windows应用程序是消息驱动的。
在MFC软件开发中,界面操作或者线程之间通信都会经常用到消息,通过对消息的处理实现相应的操作。
比较典型的过程是,用户操作窗口,然后有消息产生,送给窗口的消息处理函数处理,对用户的操作做出响应。
什么是消息窗口消息一般由三个部分组成:1.一个无符号整数,是消息值;(2)消息附带的WPARAM类型的参数;(3)消息附带的LPARAM类型的参数。
其实我们一般所说的消息是狭义上的消息值,也就是一个无符号整数,经常被定义为宏。
什么是消息映射机制MFC使用一种消息映射机制来处理消息,在应用程序框架中的表现就是一个消息与消息处理函数一一对应的消息映射表,以及消息处理函数的声明和实现等代码。
当窗口接收到消息时,会到消息映射表中查找该消息对应的消息处理函数,然后由消息处理函数进行相应的处理。
SDK编程时需要在窗口过程中一一判断消息值进行相应的处理,相比之下MFC的消息映射机制要方便好用的多。
Windows消息分类先讲下Windows消息的分类。
Windows消息分为系统消息和用户自定义消息。
Windows系统消息有三种:1.标准Windows消息。
除WM_COMMAND外以WM_开头的消息是标准消息。
例如,WM_CREATE、WM_CLOSE。
2.命令消息。
消息名为WM_COMMAND,消息中附带了标识符ID来区分是来自哪个菜单、工具栏按钮或加速键的消息。
3.通知消息。
通知消息一般由列表框等子窗口发送给父窗口,消息名也是WM_COMMAND,其中附带了控件通知码来区分控件。
CWnd的派生类都可以接收到标准Windows消息、通知消息和命令消息。
命令消息还可以由文档类等接收。
用户自定义消息是实际上就是用户定义一个宏作为消息,此宏的值应该大于等于WM_USER,然后此宏就可以跟系统消息一样使用,窗口类中可以定义它的处理函数。
关于MFC消息映射机制剖析

关于MFC消息映射机制剖析软采用了所谓的消息映射机制,来完成不同对象之间消息的传递,本文就MFC9.0源码进行分析,大致讲解MFC的消息映射机制。
步入正题,在AfxWinMain() 函数中,当MFC框架初始化完成后,即pThread->InitInstance() 执行完成,就开始进行消息循环,入口函数是pThread->Run():[cpp]view plaincopy1.// Perform specific initializations2.if (!pThread->InitInstance())// MFC初始化框架3.{4.if (pThread->m_pMainWnd != NULL)5. {6. TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n");7. pThread->m_pMainWnd->DestroyWindow();8. }9. nReturnCode = pThread->ExitInstance();10.goto InitFailure;11.}12.nReturnCode = pThread->Run();// 进入消息循环执行CWinApp:: Run():[cpp]view plaincopy1.// Main running routine until application exits2.int CWinApp::Run()3.{4.if (m_pMainWnd == NULL && AfxOleGetUserCtrl())5. {6.// Not launched /Embedding or /Automation, but has no main window!7. TRACE(traceAppMsg, 0, "Warning: m_pMainWnd is NULL in CWinApp::Run -quitting application.\n");8. AfxPostQuitMessage(0);9. }10.return CWinThread::Run();11.}执行CWinThread::Run():[cpp]view plaincopy1.// main running routine until thread exits2.int CWinThread::Run()3.{4. ASSERT_VALID(this);5. _AFX_THREAD_STATE* pState = AfxGetThreadState();6.7.// for tracking the idle time state8.BOOL bIdle = TRUE;9.LONG lIdleCount = 0;10.11.// acquire and dispatch messages until a WM_QUIT message is received.12.GetMessage:从系统获取消息,将消息从系统中移除,属于阻塞函数。
mfc消息响应机制

mfc消息响应机制MFC消息响应机制MFC(Microsoft Foundation Class)是微软公司为开发Windows应用程序而提供的一组C++类库。
在MFC中,消息响应机制是一种重要的编程方式,用于处理用户与应用程序之间的交互。
本文将详细介绍MFC消息响应机制的原理和使用方法。
一、消息处理函数在MFC中,消息处理函数是用于响应消息的函数。
当用户与应用程序进行交互时,系统会产生相应的消息,然后通过消息映射表找到对应的消息处理函数进行处理。
消息处理函数是类成员函数,其原型通常为:afx_msg LRESULT OnMessage(WPARAM wParam, LPARAM lParam);其中,afx_msg是MFC宏定义,LRESULT是消息处理函数的返回值类型,OnMessage是函数名,WPARAM和LPARAM是消息参数,用于传递消息的附加信息。
二、消息映射表消息映射表是一个包含消息处理函数与消息ID之间对应关系的表格。
在MFC应用程序的消息映射表中,每个消息ID都与一个消息处理函数相对应。
当收到某个消息时,系统会根据消息ID查找对应的消息处理函数,并调用该函数进行处理。
消息映射表通常定义在类的声明中,格式如下:BEGIN_MESSAGE_MAP(CMyClass, CBaseClass)ON_MESSAGE(messageID, memberFxn)// more message mappings...END_MESSAGE_MAP()其中,CMyClass是消息处理类的名称,CBaseClass是消息处理类的基类,messageID是消息ID,memberFxn是与该消息ID对应的消息处理函数。
三、消息处理函数的实现消息处理函数的实现步骤如下:1. 在类的声明中定义消息处理函数的原型。
2. 在类的实现文件中,使用宏定义IMPLEMENT_DYNAMIC或IMPLEMENT_DYNCREATE来实现运行时类型信息。
MFC消息映射机制剖析

一,消息映射机制1,消息响应函数:(例:在CDrawView类响应鼠标左键按下消息)1)在头文件(DrawView.h)中声明消息响应函数原型。
//{{AFX_MSG(CDrawView) //注释宏afx_msg void OnLButtonDown(UINT nFlags, CPoint point);//}}AFX_MSG //注释宏说明:在注释宏之间的声明在VC中灰色显示。
afx_msg宏表示声明的是一个消息响应函数。
2)在源文件(DrawView.cpp)中进行消息映射。
BEGIN_MESSAGE_MAP(CDrawView, CView)//{{AFX_MSG_MAP(CDrawView)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()说明:在宏BEGIN_MESSAGE_MAP()与END_MESSAGE_MAP()之间进行消息映射。
宏ON_WM_LBUTTONDOWN()把消息WM_LBUTTONDOWN与它的响应函数OnLButtonDown ()相关联。
这样一旦有消息的产生,就会自动调用相关联的消息响应函数去处理。
宏ON_WM_LBUTTONDOWN()定义如下:#define ON_WM_LBUTTONDOWN() \{ WM_LBUTTONDOWN, 0, 0, 0, AfxSig_vwp, \(AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(UINT,CPoint))&OnLButtonDown },3)源文件中进行消息响应函数处理。
MFC消息映射机制

由于工作需要,这几天学了一点MFC,在AF X里看到很多熟悉的东西,如类型信息,序列化,窗口封装和消息分派。
几乎每个界面库都必须提供这些基础服务,但提供的手法却千差万别。
MFC大量地借用了宏,映射表来实现,而VCL则更多的在语言级别上给与支持。
这其实是很容易理解的,因为C++是一个标准,不会因某个应用而随便扩展语言;相反Delphi完全由一个公司掌握,因此每支持一项新技术,变化最大的往往是语言本身。
学习MFC的代码,再对照VC L的实现,这真是一个很有意思的过程,其中可以看到两个框架在一些设计思想上是殊途同归的,所不同的是表现手法,以及封装的程度。
我计划将这段时间阅读MFC的心得写成一系列文章,其中可能会穿插与VC L的对比,不管你熟悉VC L还是MFC,通过这些文章或许可从另一个角度来看待自己熟悉的框架。
这是第一篇:消息分派。
消息处理函数表MFC和VCL在对消息进行封装的时候,都没有使用虚函数机制。
原因是虚函数带来了不必要的空间开销。
那么它们用什么来代替虚函数,即可减少空间浪费,也可实现类似虚函数的多态呢?让我们从一个例子开始。
假设父类ParentWnd处理了100个消息,并且将这100个处理函数声明为虚函数;此时有一个子类ChildWnd它只需要处理2个消息,另外98个交由ParentWnd默认处理,但是ChildWnd的虚表仍然占有100个函数指针,其中2个指向自己的实现,另外98个指向父类的实现,情况大概像下面这样:指向父类实现的函数指针浪费了空间,当控件类非常多的时候,这种浪费就非常明显。
因此必须走另一条路,将不必要的函数指针去掉,如下图所示:ChildWnd去掉函数指针之后,当有一个消息需要Fun100处理时,ChildWnd就束手无策了。
需要一个方法让ChildWnd能够找到父类的表,我们再对这个数据结构进行改进如下:现在看来好多了,如果ChildWnd有一个消息需要Fun1处理,则查找ChildWnd的MsgHandlers,找到Fun1函数指针调用之;如果需要Fun100处理,发现ChildWnd的MsgHandlers没有Fun100,则通过ParentTable找到父类的MsgHandlers继续查找。
mfc消息映射机制

mfc消息映射机制MFC消息映射机制是MFC框架中的一个重要机制,它是实现消息响应的关键。
在MFC中,消息是指Windows操作系统中的消息,例如鼠标点击、键盘输入、窗口大小改变等。
MFC消息映射机制是将消息与相应的处理函数关联起来的过程,使得程序能够响应用户的操作。
MFC消息映射机制的实现依赖于消息映射表。
消息映射表是一个数组,其中每个元素都是一个消息映射结构体。
消息映射结构体包含了消息的类型、消息的ID、消息的处理函数等信息。
当程序接收到一个消息时,MFC会根据消息的类型和ID在消息映射表中查找相应的处理函数,并将消息传递给该函数进行处理。
MFC消息映射机制的优点在于它能够将消息处理函数与消息的类型和ID进行关联,使得程序的代码更加清晰、易于维护。
此外,MFC 还提供了一些宏定义,例如DECLARE_MESSAGE_MAP和BEGIN_MESSAGE_MAP,使得消息映射表的定义更加简洁、易于理解。
MFC消息映射机制的使用方法如下:1. 在类的头文件中声明消息映射表,使用DECLARE_MESSAGE_MAP宏定义。
2. 在类的实现文件中定义消息映射表,使用BEGIN_MESSAGE_MAP和END_MESSAGE_MAP宏定义。
3. 在消息映射表中添加消息映射结构体,使用ON_MESSAGE、ON_COMMAND等宏定义。
4. 在消息处理函数中编写相应的代码,处理消息。
例如,以下代码实现了一个响应鼠标点击消息的处理函数:afx_msg LRESULT CMyWnd::OnLButtonDown(WPARAM wParam, LPARAM lParam){// 处理鼠标点击消息return 0;}BEGIN_MESSAGE_MAP(CMyWnd, CWnd)ON_WM_LBUTTONDOWN()END_MESSAGE_MAP()在上述代码中,CMyWnd是一个继承自CWnd的窗口类,OnLButtonDown是处理鼠标点击消息的函数。
第四课:MFC画图-MFC消息映射机制的剖析

MFC消息映射机制的剖析,讲述如何运用ClassWizard,,理解发送给窗口的消息是如何被MFC框架通过窗口句柄映射表和消息映射表来用窗口类的函数进行响应的。
掌握设备描述表及其封装类CDC的使用,CDC是如何与具体的设备发生关联的,融合具体的画图程序进行分析。
如何设置封闭图形的填充刷子(位图画刷与透明画刷的使用)。
主要介绍一些绘图方面的知识。
程序实例:新建工程:->MFC AppWizard[exe] 文件面为Draw 选择单文档的应用程序完成之后编译运行。
画直线、画图、画刷画位图、空白画刷操作步骤●明确画图的思路:按下鼠标左键画图的原点,拖动鼠标到另外一个位置松开鼠标左键画图的终点。
●画图需要消息的捕获。
捕获的对象是鼠标左键按下WM_LBUTTONDOWN和抬起WM_LBUTTONUP的消息。
●这两消息的捕获、响应在窗口类中进行,可以在框架类Frame类中也可以在视类View类中。
●要对消息进行捕获我们需要设置一些额外的函数,这些函数MFC都有提供。
如我们在CMainFrame上点击右键选择增加windows消息处理Addwindows message handler……,选择WM_LBUTTONDOWN点击“AddHandler”添加而后点击“Edit Existing”退出。
CMainFrame message handlers 在CMainFrame最底下被创建。
具体内容详见下面程序代码。
(这段代码添加的位置是在implementation of the CMainFrame class中,文件名为CMainFrame.cpp)●为了简单说明每一步的作用这个程序做出的反应,在消息响应函数中添加一个MessageBox程序代码,这个MessageBox要比先前的WinApi中使用的少一个” HWND hWnd,”参数。
MessageBox在CWnd中是属于其中的一个成员函数,他不需要句柄因为有一个数据成员保存了和这个窗口相关的句柄。
MFC六大核心机制

MFC六大核心机制MFC(Microsoft Foundation Classes)是微软公司开发的一套基于C++语言的应用程序框架。
它提供了一系列类和函数库,方便开发人员构建Windows应用程序。
MFC框架包含了许多核心机制,下面将介绍其中的六大核心机制。
一、消息映射机制:消息映射机制是MFC框架的核心之一,它用于处理Windows消息。
Windows操作系统是事件驱动的,应用程序需要响应来自用户的输入或系统的消息。
通过消息映射机制,开发人员可以向MFC框架注册处理特定消息的函数,当该消息发生时,框架将自动调用相应的函数进行处理。
开发人员只需要在类的消息映射表中添加相应的消息与处理函数的映射关系,就可以实现消息的处理。
二、文档/视图机制:文档/视图机制是MFC框架中用来管理应用程序数据和图形界面显示的一种机制。
应用程序的数据和用户界面是相互独立的,通过文档/视图机制可以将二者进行分离。
开发人员可以创建一个或多个文档类来管理数据,同时可以创建一个或多个视图类来负责显示用户界面。
MFC框架会自动处理数据和界面之间的同步,例如当数据发生变化时,会自动更新界面;当用户修改界面时,会自动更新数据。
三、消息响应机制:消息响应机制是MFC框架中用来处理用户输入和系统消息的一种机制。
开发人员可以通过消息响应机制,将特定的消息与相应的处理函数进行关联,当该消息发生时,框架会自动调用相应的处理函数。
例如,开发人员可以通过响应鼠标点击消息来实现用户点击按钮的响应,或者通过响应键盘输入消息来实现用户输入的响应。
四、对象模型机制:对象模型机制是MFC框架中用来管理对象的一种机制。
MFC框架使用了一种轻量级的对象模型,对象之间的关系通过继承和组合来实现。
开发人员可以创建自己的类并继承自MFC提供的基类,以实现各种功能。
MFC框架提供了丰富的基类库,包括窗口类、对话框类、控件类等,开发人员可以通过继承这些基类来快速构建自己的应用程序。
MFC的消息映射机制与命令绕行

所有的消息在MFC 程序中都是暗潮汹涌,但是表面无波。
MFC 把消息分为三大类:
■ 命令消息(WM_COMMAND):命令消息意味着「使用者命令程序做某些动作」。
凡由UI 对象产生的消息都是这种命令消息,可能来自菜单或加速键或工具栏
按钮,并且都以WM_COMMAND 呈现。如何分辨来自各处的命令消息?SDK程序主要靠消息的wParam 辨识之,MFC 程序则主要靠菜单项目的识别码(menu ID)辨识之-- 两者其实是相同的。什么样的类别有资格接受命令消息?凡衍生自CCmdTarget 之类别,皆有资格。从command target 的字面意义可知,这是命令消息的目的地。也就是说,凡衍生自CCmdTarget 者,它的骨子里就有了一种特殊的机制。把整张MFC 类别阶层图摊开来看,几乎构造应用程序的最重要的几个类别都衍生自CCmdTarget,剩下的不能接收消息的,是像CFile、CArchive、CPoint、CDao(数据库)、Collection Classes(纯粹数据处理)、GDI 等等「非主流」类别。
三个奇怪的宏,一张巨大的网
试着思考这个问题:C++ 的继承与多态性质,使衍生类别与基础类别的成员函数之间有着特殊的关联。但这当中并没有牵扯到Windows 消息。的确,C++ 语言完全没有考虑Windows 消息这一回事(那当然)。如何让Windows 消息也能够在对象导向以及继承性质中扮演一个角色?既然语言没有支持,只好自求多福了。消息映射机制的三个相关宏就是MFC 自求多福的结果。
■ 标准消息- 除WM_COMMAND 之外,任何以WM_ 开头的都算是这一类。任何衍生自CWnd 之类别,均可接收此消息。
■ Control Notification - 这种消息由控制组件产生,为的是向其父窗口(通常是对话盒)通知某种情况。例如当你在ListBox 上选择其中一个项目,ListBox 就会产生LBN_SELCHANGE 传送给父窗口。这类消息也是以WM_COMMAND 形式呈现。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
由于工作需要,这几天学了一点MFC,在AFX里看到很多熟悉的东西,如类型信息,序列化,窗口封装和消息分派。
几乎每个界面库都必须提供这些基础服务,但提供的手法却千差万别。
MFC大量地借用了宏,映射表来实现,而VCL则更多的在语言级别上给与支持。
这其实是很容易理解的,因为C++是一个标准,不会因某个应用而随便扩展语言;相反Delphi完全由一个公司掌握,因此每支持一项新技术,变化最大的往往是语言本身。
学习MFC的代码,再对照VCL的实现,这真是一个很有意思的过程,其中可以看到两个框架在一些设计思想上是殊途同归的,所不同的是表现手法,以及封装的程度。
我计划将这段时间阅读MFC的心得写成一系列文章,其中可能会穿插与VCL的对比,不管你熟悉VCL还是MFC,通过这些文章或许可从另一个角度来看待自己熟悉的框架。
这是第一篇:消息分派。
消息处理函数表MFC和VCL在对消息进行封装的时候,都没有使用虚函数机制。
原因是虚函数带来了不必要的空间开销。
那么它们用什么来代替虚函数,即可减少空间浪费,也可实现类似虚函数的多态呢?让我们从一个例子开始。
假设父类ParentWnd处理了100个消息,并且将这100个处理函数声明为虚函数;此时有一个子类ChildWnd它只需要处理2个消息,另外98个交由ParentWnd默认处理,但是ChildWnd的虚表仍然占有100个函数指针,其中2个指向自己的实现,另外98个指向父类的实现,情况大概像下面这样:指向父类实现的函数指针浪费了空间,当控件类非常多的时候,这种浪费就非常明显。
因此必须走另一条路,将不必要的函数指针去掉,如下图所示:ChildWnd去掉函数指针之后,当有一个消息需要Fun100处理时,ChildWnd就束手无策了。
需要一个方法让ChildWnd能够找到父类的表,我们再对这个数据结构进行改进如下:现在看来好多了,如果ChildWnd有一个消息需要Fun1处理,则查找ChildWnd的MsgHandlers,找到Fun1函数指针调用之;如果需要Fun100处理,发现ChildWnd的MsgHandlers没有Fun100,则通过ParentTable找到父类的MsgHandlers继续查找。
如此一直查找,到最后再找不到,就调用DefWindowProc作默认处理。
MFC和VCL都是通过类似的方法实现消息分派的。
只是VCL有编译器的支持,直接将这个表放到VMT中,因此实现起来非常简单,只需在控件类里作如下声明:procedure WMMButtonDown(var Message: TWMMButtonDown); message WM_MBUTTONDOWN; TObject.Dispatch会将WM_MBUTTONDOWN正确分派到WMMButtonDown。
MFC就没有这么简单,它需要手工去构建这个表,如果一个类想处理消息,它必须声明一些结构和函数,代码类似这样:struct AFX_MSGMAP_ENTRY{UINT nMessage; // 消息AFX_PMSG pfn; // 消息处理函数};struct AFX_MSGMAP{const AFX_MSGMAP* pBaseMap; //指向基类的消息映射const AFX_MSGMAP_ENTRY* lpEntries; //消息映射表};class CMFCTestView : public CView{protected:void OnLButtonDown(UINT nFlags, CPoint point);private:static const AFX_MSGMAP_ENTRY _messageEntries[];protected:static const AFX_MSGMAP messageMap;virtual const AFX_MSGMAP* GetMessageMap() const;};仔细看_messageEntries和messageMap的声明,是不是和上面的图非常相似,接下来看看实现部分如何初始化这个表:const AFX_MSGMAP* CMFCTestView::GetMessageMap() const{ return & CMFCTestView::messageMap; }const AFX_MSGMAP CMFCTestView::messageMap ={ & CView::messageMap, & CMFCTestView::_messageEntries[0] };const AFX_MSGMAP_ENTRY CMFCTestView::_messageEntries[] ={{ WM_LBUTTONDOWN, (AFX_PMSG)&OnLButtonDown }{0, (AFX_PMSG)0 }};void CMFCTestView::OnLButtonDown(UINT nFlags, CPoint point){CView::OnLButtonDown(nFlags, point);}messageMap的第一个成员指向其父类的messageMap,即&CView::messageMap;第二个成员则指向下面的消息映射表;GetMessageMap是一个虚函数,显然是为了父类分派消息的时候能够找到正确的消息映射结构,后面会看到这一点。
_messageEntries数组为消息映射表,第一个元素处理WM_LBUTTONDOWN消息,其处理函数是OnLButtonDown,这个函数在CMFCTestView声明和实现;第二个元素标识了映射表的结尾。
现在,你想处理什么消息,都可以往_messageEntries里加新的元素并指定你的处理函数,只是如果每一个类都需要手工写这些代码,那将是很繁琐的事情;幸好C++有宏,可以用宏来作一些简化的代码,先将消息映射的声明用DECLARE_MESSAGE_MAP()表示,则类声明变成下面这样:class CMFCTestView : public CView{DECLARE_MESSAGE_MAP()};而实现部分,变成了下面这样:BEGIN_MESSAGE_MAP(CMFCTestView, CView)ON_WM_LBUTTONDOWN()END_MESSAGE_MAP()这就是MFC的消息映射宏,实际的代码和这里有一些出入,不过大体是差不多的,其核心作用就是构造消息处理函数表。
现在打开VC去看看那几个宏,是不是觉得其实很简单。
建好消息映射表后,接下来要看看消息如何流到指定的处理函数里。
消息流向我们可以认为消息的最初进入点是CWnd::WindowProc,在以后的文章会说明消息如何流到这个函数。
CWnd是所有窗口类的基类,CMFCTestView当然也是CWnd的子孙类。
WindowProc的代码很简单,调用OnWndMsg进行消息分派,如果没有处理函数,则调用DefWindowProc作默认处理:LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam){// OnWndMsg does most of the work, except for DefWindowProc callLRESULT lResult = 0;if (!OnWndMsg(message, wParam, lParam, &lResult))lResult = DefWindowProc(message, wParam, lParam);return lResult;}最重要的是OnWndMsg成员函数,我将里面的代码作了简化,去掉了命令通知消息和一些优化代码,最终的代码如下:BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) {LRESULT lResult = 0;const AFX_MSGMAP* pMessageMap;//取得消息映射结构,GetMessageMap为虚函数,所以实际取的是CMFCTestView的消息映射pMessageMap = GetMessageMap();// 查找对应的消息处理函数for (pMessageMap != NULL; pMessageMap = pMessageMap->pBaseMap)if (message < 0xC000)if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries, message, 0, 0)) != NULL)goto LDispatch;... ...LDispatch://通过联合来匹配正确的函数指针类型union MessageMapFunctions mmf;mmf.pfn = lpEntry->pfn;int nSig;nSig = lpEntry->nSig;//nSig代表函数指针的类型,通过一个大大的Case来匹配。
switch (nSig){case AfxSig_bD:lResult = (this->*mmf.pfn_bD)(CDC::FromHandle((HDC)wParam));break;... ...case AfxSig_vwp:{CPoint point((DWORD)lParam);(this->*mmf.pfn_vwp)(wParam, point);break;}}return TRUE;}在代码中看到GetMessageMap的调用,根据前面的分析已经知道这是一个虚函数,所以实际调用到的是CMFCTestView::GetMessageMap(),也就是这里取到了CMFCTestView的消息映射结构。
接下来根据当前的消息表寻找对应的消息处理函数,调用AfxFindMessageEntry查找消息映射表,如果找不到就继续到基类去找,这就是For循环做的事情。
AfxFindMessageEntry使用内嵌汇编来提高查找的效率, VCL也是这样做的。
如果找到处理函数,则调用goto LDispatch;跳到下面的Case语句,根据nSig判断函数指针的实际类型,最后转换并调用之,此时我们的OnLButtonDown函数就被调用到了。
我们看到了Goto语句的使用,也看到下面大大的Case,这都是OO设计的禁忌,特别是下面的Case,为什么要用Case呢?这是由消息映射宏的设计决定的。