MFC运行机制和消息响应机制图文小学教育_第1页
MFC运行机制和消息响应机制图文小学教育_第2页
MFC运行机制和消息响应机制图文小学教育_第3页
MFC运行机制和消息响应机制图文小学教育_第4页
MFC运行机制和消息响应机制图文小学教育_第5页
已阅读5页,还剩5页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1/1MFC运行机制和消息响应机制-图文-小学教育

MFC的类层次结构与运行机制MFC的类层次结构

如图所示(子类指向父类):

其中:

CObject:是MFC供应的绝大多数类的基类。该类完成动态空间的安排与回收,支持一般的诊断、出错信息处理和文档序列化等。

CCmdTarget:主要负责将系统大事(消息)和窗口大事(消息)发送给响应这些大事的对象,完成消息发送、等待和派遣调度等工作,实现应用程序的对象之间的协调运行。

CWinApp:是应用程序的主线程类,它是从CWinThread类派生而来的。CWinThread类用来完成对线程的掌握,包括线程的创建、运行、终止和挂起等。

CDocument:是文档类,包含了应用程序在运行期间所用到的数据。

CWnd:是一个通用的窗口类,用来供应Windows中的全部通用特性、对话框和控件。CFrameWnd是从CWnd类继承来的,并实现了标准的框架应用程序。CDialog类用来掌握对话框窗口。CView:用于让用户通过窗口来访问文档。

CMDIFrameWnd和CMDIChildWnd:分别用于多文档应用程序的主框架窗口和文档子窗口的显示和管理。CMiniFrameWnd类是一种简化的框架窗口,它没有最大化和最小化窗口按钮,也没有窗口系统菜单,一般很少用到它。

MFC运行机制

在程序中,当定义一个类对象时,它会自动调用相应的构造函数。所谓\类对象\,就是用该类定义的\变量\,这个\变量\又称为类的一个实例。例如,theApp就是类CSimpApp的一个对象。

MFC正是利用类的这种\自动调用相应的构造函数\特性,使得WinMain函数的调用变成了应用程序框架内部的调用,所以我们在代码中看不到每个Windows程序所必需有的WinMain函数。

当应用程序运行到\theApp;\时,系统就会先调用基类CWinApp构造函数,进行一系列的内部初始化操作,然后自动调用CSimpApp的虚函数InitInstance,该函数会进一步调用相应的函数来完成主窗口的构造和显示工作。下面来看看上述程序中InitInstance的执行过程。首先执行的是:

m_pMainWnd=newCMainFrame;

该语句用来创建从CFrameWnd类派生而来的用户框架窗口CMainFrame类对象,继而调用该类的构造函数,使得Create函数被调用,完成了窗口创建工作。

然后执行后面两句:

m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow;用作窗口的显示和更新。接下来调用:

m_pMainWnd->MessageBox(\你好,欢迎进入MFC世界!\最终返回TRUE,表示窗口创建胜利。

由于应用程序类CWinApp是用来调用WinMain以及实例的初始化,因此每一个MFC应用程序有且只能一个这样的应用程序类,且需要一个全局的对象实例,如上述程序中的theApp,当然也可换一个对象名。InitInstance完成初始化工作之后,接下来就是调用基类CWinApp的成员函数Run,执行应用程序的消息循环,即重复执行接收消息并转发消息的工作。当Run检查到消息队列为空时,将调用基类CWinApp的成员函数OnIdle进行空闲时的后台处理工作。若消息队列为空且又没有后台工作要处理时,则应用程序始终处于等待状态,始终等到有消息为止。

当程序结束后,调用基类CWinApp的成员函数ExitInstance,完成终止应用程序的收尾工作。这就是MFC应用程序的运行机制。

MFC消息响应机制分析

MFC是Windows下程序设计的最流行的一个类库,但是该类库比较庞杂,尤其是它的消息映射机制,更是涉及到许多低层的东西,我们在这里,对它的整个消息映射机制进行了系统的分析,可以关心程序开发人员对MFC的消息映射机制有一个比较透彻的了解。1.引言

VC++的MFC类库实际上是Windows下C++编程的一套最为流行的类库。MFC的框架结构大大便利了程序员的编程工作,但是为了更加有效、敏捷的使用MFC编程,了解MFC的体系结构往往可以使编程工作事半功倍。它合理的封装了WIN32API函数,并设计了一套便利的消息映射机制。但这套机制本身比较浩大和简单,对它的分析和了解无疑有助于我们写出更为合理的高效的程序。这里我们简洁的分析MFC的消息响应机制,以了解MFC是如何对Windows的消息加以封装,便利用户的开发。2.SDK下的消息机制实现

这里简洁的回顾一下SDK下我们是如何进行Windows的程序开发的。一般来说,Windows的消息都是和线程相对应的。即Windows会把消息发送给和该消息相对应的线程。在SDK的模式下,程序是通过GetMessage函数从和某个线程相对应的消息队列里面把消息取出来并放到一个特别的结构里面,一个消息的结构是一个如下的STRUCTURE。typedefstructtagMSG{HWNDhwnd;UINTmessage;WPARAMwParam;LPARAMlParam;DWORDtime;POINTpt;}MSG;

其中hwnd表示和窗口过程相关的窗口的句柄,message表示消息的ID号,wParam和lParam表示和消息相关的参数,time表示消息发送的时间,pt表示消息发送时的鼠标的位置。

然后TranslateMessage函数用来把虚键消息翻译成字符消息并放到响应的消息队列里面,最终DispatchMessage函数把消息分发到相关的窗口过程。然后窗口过程依据消息的类型对不同的消息进行相关的处理。在SDK编程过程中,用户需要在窗口过程中分析消息的类型和跟消息一起的参数的含义,做不同的处理,相对比较麻烦,而MFC把消息调用的过程给封装起来,使用户能够通过ClassWizard便利的使用和处理Windows的各种消息。3.MFC的消息实现机制

我们可以看到,在MFC的框架结构下,可以进行消息处理的类的头文件里面都会含有

DECLARE_MESSAGE_MAP宏,这里主要进行消息映射和消息处理函数的声明。可以进行消息处理的类的实现文件里一般都含有如下的结构。

BEGIN_MESSAGE_MAP(CInheritClass,CBaseClass)//{{AFX_MSG_MAP(CInheritClass)//}}AFX_MSG_MAPEND_MESSAGE_MAP

这里主要进行消息映射的实现和消息处理函数的实现。

全部能够进行消息处理的类都是基于CCmdTarget类的,也就是说CCmdTarget类是全部可以进行消息处理类的父类。CCmdTarget类是MFC处理命令消息的基础和核心。同时MFC定义了下面的两个主要结构:

AFX_MSGMAP_ENTRYstructAFX_MSGMAP_ENTRY{

UINTnMessage;//windowsmessage

UINTnCode;//controlcodeorWM_NOTIFYcodeUINTnID;

//controlID(or0forwindowsmessages)UINTnLastID;

//usedforentriesspecifyingarangeofcontrolid'sUINTnSig;

//signaturetype(action)orpointertomessage#AFX_PMSGpfn;//routinetocall(orspecialvalue)};

和AFX_MSGMAPstructAFX_MSGMAP{

#ifdef_AFXDLL

constAFX_MSGMAP*(PASCAL*pfnGetBaseMap);#else

constAFX_MSGMAP*pBaseMap;#endif

constAFX_MSGMAP_ENTRY*lpEntries;};

其中AFX_MSGMAP_ENTRY结构包含了一个消息的全部相关信息,其中nMessage为Windows消息的ID号nCode为掌握消息的通知码nID为Windows掌握消息的ID

nLastID表示假如是一个指定范围的消息被映射的话,nLastID用来表示它的范围。nSig表示消息的动作标识

AFX_PMSGpfn它实际上是一个指向和该消息相应的执行函数的指针。

而AFX_MSGMAP主要作用是两个,一:用来得到基类的消息映射入口地址。二:得到本身的消息映射入口地址。

实际上,MFC把全部的消息一条条填入到AFX_MSGMAP_ENTRY结构中去,形成一个数组,该数组存放了全部的消息和与它们相关的参数。同时通过AFX_MSGMAP能得到该数组的首地址,同时得到基类的消息映射入口地址,这是为了当本身对该消息不响应的时候,就调用其基类的消息响应。

现在我们来分析MFC是如何让窗口过程来处理消息的,实际上全部MFC的窗口类都通过钩子函数_AfxCbtFilterHook截获消息,并且在钩子函数_AfxCbtFilterHook中把窗口过程设定为AfxWndProc。原来的窗口过程保存在成员变量m_pfnSuper中。

所以在MFC框架下,一般一个消息的处理过程是这样的。函数AfxWndProc接收Windows操作系统发送的消息。

函数AfxWndProc调用函数AfxCallWndProc进行消息处理,这里一个进步是把对句柄的操作转换成对CWnd对象的操作。

函数AfxCallWndProc调用CWnd类的方法WindowProc进行消息处理。留意AfxWndProc和AfxCallWndProc都是AFX的API函数。而WindowProc已经是CWnd的一个方法。所以可以留意到在WindowProc中已经没有关于句柄或者是CWnd的参数了。

方法WindowProc调用方法OnWndMsg进行正式的消息处理,即把消息派送到相关的方法中去处理。消息是如何派送的呢?实际上在CWnd类中都保存了一个AFX_MSGMAP的结构,而在AFX_MSGMAP结构中保存有全部我们用ClassWizard生成的消息的数组的入口,我们把传给OnWndMsg的message和数组中的全部的message进行比较,找到匹配的那一个消息。实际上系统是通过函数AfxFindMessageEntry来实现的。找到了那个message,实际上我们就得到一个AFX_MSGMAP_ENTRY结构,而我们在上面已经提到

AFX_MSGMAP_ENTRY保存了和该消息相关的全部信息,其中主要的是消息的动作标识和跟消息相关的执行函数。然后我们就可以依据消息的动作标识调用相关的执行函数,而这个执行函数实际上就是通过ClassWizard在类实现中定义的一个方法。这样就把消息的处理转化到类中的一个方法的实现上。举一个简洁的例子,比如在View中对WM_LButtonDown消息的处理就转化成对如下一个方法的操作。voidCInheritView::OnLButtonDown(UINTnFlags,CPointpoint){

//TODO:Addyourmessage

handlercodehereand/orcalldefaultCView::OnLButtonDown(nFlags,point);}

留意这里CView::OnLButtonDown(nFlags,point)实际上就是调用CWnd的Default方法。而Default方法所做的工作就是调用DefWindowProc对消息进行处理。这实际上是调用原来的窗口过程进行缺省的消息处理。

假如OnWndMsg方法没有对消息进行处理的话,就调用DefWindowProc对消息进行处理。这是实际上是调用原来的窗口过程进行缺省的消息处理。

所以假如正常的消息处理的话,MFC窗口类是完全脱离了原来的窗口过程,用自己的一套体系结构实现消息的映射和处理。即先调用MFC窗口类挂上去的窗口过程,再调用原先的窗口过程。并且用户面对和消息相关的参数不再是死板的wParam和lParam,而是和消息类型详细相关的参数。比如和消息WM_LbuttonDown相对应的方法OnLButtonDown的两个参数是nFlags和point。nFlags表示在按下鼠标左键的时候是否有其他虚键按下,point更简洁,就是表示鼠标的位置。

同时MFC窗口类消息传递中还供应了两个函数,分别为WalkPreTranslateTree和

PreTranslateMessage。我们知道利用MFC框架生成的程序,都是从CWinApp开头执行的,而CWinapp实际继承了CWinThread类。在CWinThread的运行过

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论