MFC应用程序框架剖析.ppt

上传人:小飞机 文档编号:6512444 上传时间:2023-11-08 格式:PPT 页数:52 大小:221.49KB
返回 下载 相关 举报
MFC应用程序框架剖析.ppt_第1页
第1页 / 共52页
MFC应用程序框架剖析.ppt_第2页
第2页 / 共52页
MFC应用程序框架剖析.ppt_第3页
第3页 / 共52页
MFC应用程序框架剖析.ppt_第4页
第4页 / 共52页
MFC应用程序框架剖析.ppt_第5页
第5页 / 共52页
点击查看更多>>
资源描述

《MFC应用程序框架剖析.ppt》由会员分享,可在线阅读,更多相关《MFC应用程序框架剖析.ppt(52页珍藏版)》请在三一办公上搜索。

1、第3章 MFC 应用程序框架剖析,贾澎涛,MFC的类组成了“应用程序框架”,“应用程序框架”定义应用程序的框架并提供基本的通用功能,程序开发者只须另外添加自己需要的功能即可。,3.1最简单的应用程序,实例1:“Hello World!”(1)使用AppWizard生成一个Win32 Application工程(2)加入Hello.cpp文件(3)运行MFC应用程序至少要有两个对象:应用对象(CHelloApp)和主框架类对象(CHelloFrame)。类CHelloApp的对象就代表着一个应用程序对象。在MFC应用程序中需要定义一个单独的全局应用对象。,#include class CHell

2、oFrame:public CFrameWndpublic:CHelloFrame()Create(NULL,Hello World!,WS_OVERLAPPEDWINDOW,rectDefault);class CHelloApp:public CWinApppublic:virtual BOOL InitInstance()m_pMainWnd=new CHelloFrame();m_pMainWnd-ShowWindow(m_nCmdShow);m_pMainWnd-UpdateWindow();return TRUE;CHelloApp HelloApp;/定义一个全局CHelloAp

3、p对象,3.2 带文档视图结构的MFC程序基本框架类和文件组成,上面的例子用应用对象和框架窗口对象构造了最简单的MFC应用程序框架,而大多数的MFC应用程序都要比他复杂的多。在这类应用中除了要包含应用对象和框架窗口对象外,还要包含文档类和视图类。采用文档视图结构最大的优点在于将程序数据本身与数据的操作与维护分离开来。微软提供了一个相当灵活的结构,用户几乎可以采用这种结构创建任何类型的Windows程序。一个文档可以对应多个视图,比如,用户在一个图表中查看由数据生成的图表的同时,可以在另一个表单中查看产生该图表的原始数据。下面我们就对文档视图结构做详细分析。,在前面我们已经建立了一个名字为Dra

4、w的工程,事实上这个框架程序已经可以编译运行了。在BUILD菜单中选择REBUILD ALL菜单项,系统开始编译由APPWIZARD自动生成的程序框架中所有文件中的源代码,并且链接生成可执行的应用程序。在BUILD菜单中选择EXECUTE菜单项,应用程序就开始运行了,虽然我们没有编写一行代码,但是可以看出由系统自动生成的应用程序的界面已经有了一个标准WINDOWS应用程序所需的几个组成部分,我们要做的事情是往这个应用程序添加必要的代码以完成我们所需要的功能。,接下来将要对WINDOWS自动生成的这个应用程序框架作详细的介绍,让你对MFC方式的WINDOWS应用程序的工作原理有全面的认识,只有这

5、样你才会知道应该如何往程序框架当中添加需要的代码。,通过对应用程序Draw进行分析,可以知道普通的MFC应用程序包含以下四个主要的类:文档类、视图类、主框架窗口类、应用类。程序的主要任务在这四个类中分配,AppWizard为每个类的实现产生了各自的源文件。C+类在文件组织上一般分为两个部分:头文件(.h)和实现文件(.cpp)。头文件是.h文件,一般用来存放类、结构等的定义代码,通过include宏插入到实现文件中。实现文件是通常的.cpp文件,用来存放类的成员函数的实际代码。,文档类,应用程序Draw的文档类的名称是CDrawDoc,这是AppWizard根据项目名称默认所取的名称,它是由M

6、FC的基类CDocument派生的。CDrawDoc类的头文件是drawdoc.h,实现文件是drawdoc.cpp。头文件中存放的是类的定义代码,实现文件中存放的是类的各个成员函数的实现代码。文档类负责存放程序数据并读取磁盘文件数据,或将磁盘文件数据写入磁盘文件中。再建立一个应用项目时,在文档类中对应用程序所需要的数据资料进行管理。,视图类,应用程序Draw中视图类的名称是CDrawView,它是由MFC的Cview类派生的。CdrawView类的头文件是drawview.h,实现文件是drawview.cpp。视图类负责显示文档类中的数据,可以显示在屏幕上,也可以输出到打印机上或其它设备上

7、。视图类也负责处理用户的输入。,框架类,在使用AppWizard生成的应用程序Draw时,选择的是一个多文档选项(在MFC AppWizardStep 1,选择的是Multiple documents选项),所以应用程序Draw中包含两个框架类:主框架类CMainFrame和子框架类CChildFrame。,主框架类CMainFrame是由MFC的CMDIFrameWnd类派生的,其头文件是mainfrm.h,实现文件是mainfrm.cpp。CMainFrame类提供了管理一个多文档界面(MDI)的主窗口的所有功能及管理窗口中的子窗口,用来显示一个标题、一个菜单条、窗口最大化和最小化键、边框

8、、一个系统菜单、工具条以及状态条等。,子框架类CChildFrame是由MFC的CMDIChildWnd类派生的,其头文件是childfrm.h,实现文件是childfrm.cpp,子框架类的功能是用来管理子窗口。一个子窗口非常像主窗口,但子窗口仅能在主窗口内显示,而不在Windows桌面上,在窗口没有自己的菜单条,但他分享主窗口的菜单条,程序自动将框架窗口菜单作为当前子窗口的菜单。,应用类,应用程序Draw的应用类是CDrawApp,它是由MFC的CWinApp类派生的。其头文件是draw.h,实现文件是draw.cpp。应用类管理程序的总体,它完成不属于任何其他三类的一般工作,例如初始化程

9、序以及进行最后的程序清除工作。每个MFC应用程序必须正确的生成由CWinApp派生类的一个实例(对象)。,应用程序主要源文件组成,在组成应用程序Draw的源文件中,除了五个主要类的源文件外(10个文件),还有其它一些文件,对他们简述如下:draw.rc:资源定义文件,包含程序资源的定义(菜单、对话框、字串、键盘加速键、和图标等)。一般情况下,这个文件是由AppStudio进行可视化编辑维护,一般不用手工修改这个文件。draw.dsw:工作平台信息文件,存储着一个工作平台的组成情况(如包含哪些程序项目、程序项目的依赖关系等),用来存储和打开一个工作平台。,draw.clw:ClassWizard

10、信息存储文件,存储ClassWizard编辑存在的类和新增加类的信息,文件也包含了ClassWizard建立和编辑各种消息处理函数和映射变量等的信息。draw.dsp:程序项目工程文件,存储着一个应用程序项目所包含的具体信息,在打开项目时用。makehelp.ybat:批处理文件用来建立应用程序的帮助文件hlpdraw.hlp。hlpdraw.hpj:被帮助文件编译器用来建立系统的帮助文件时使用的工程文件。,hlp*.bmp:被用来作为MFC标准命令帮助主题的位图文件。hlp*.rtf:帮助主题文件,包含MFC标准命令的帮助主题。resdraw.rc2:资源定义文件,包含着不用AppStudi

11、o编辑的程序资源定义。当手工(而不是AppStudio)定义程序资源,可以将资源定义在这个文件中。这个文件被插入(#include)在文件draw.rc中。,resdraw.ico:应用程序的图标。最初,这个文件包含标准的“AFX”图标。可以用AppStidio对图表进行修改。restoolbar.bmp:工具条的位图文件。stdafx.cpp和stdafx.h:预编译文件,用于生成预编译信息。resource.h:资源ID号定义文件,这个文件与draw.rc相对应,包含程序资源中ID号的常量定义。一般也是由AppStudio自动进行维护的。,draw.def:它提供Microsoft LIN

12、K程序进行连接时,用于准备可执行的应用程序文件的有关信息。一般不必编辑这个文件,因为它包含适合于大多数MFC Windows程序的值。readme.txt:包含对所有该程序的源文件的解释信息。,注意,文档视图结构并不是在任何情况下都是适合的,在使用时应注意以下几种情况:(1)用户要移植一个用C编写的Windows程序,用户可能希望在添加文档视图结构之前完成移植。(2)如果用户在编写一个小工具,可能会发现不采用文档视图也是可以的,并且程序会更简单。(3)如果源代码已经将数据管理和数据视图有效结合在一起,采用文档视图结构是多余的。,WINDOWS应用程序一定要有WinMain函数,该函数用来完成一

13、些特殊的任务,象创建程序的主窗口,主窗口用来处理消息的代码。MFC将WinMain隐藏在框架中,不象写SDK(Software Development Kit)程序时可以很容易的找到它。WINDOWS采用的消息处理机制也交给了程序框架,我们不必担心如何使这些消息和代码联系起来。并且WINDOWS定义好了一些消息,当窗口被创建时系统就会发送WM_CREATE消息,当点击鼠标左键时便系统会发送WM_LBUTTONDOWN消息,当用户按下键盘时系统会发送WM_CHAR消息,当用户关闭窗口时系统会发送WM_CLOSE消息,当用户进行菜单项选择或单击按钮时系统回发送WM_COMMAND消息,什么都不做系

14、统还会发送WM_TIMER消息。,说明,3.3 MFC应用程序的执行步骤,前面介绍了Draw应用程序的文件,那么你们可能要问,Draw程序从哪里开始执行的?从哪里吸收控制?以下是一般MFC应用程序运行的主要步骤:调用CWinApp类构造函数。程序入口函数WinMain接收控制。WinMain调用程序的InitInstance函数。WinMain进入消息循环。WinMain退出,程序终止。,(1)调用CWinApp类构造函数,MFC应用程序必须定义有且只有一个应用类对象。在实现文件draw.cpp中可以找到其定义:CDrawApp theApp;由于应用类对象theApp是全局对象,因此在入口函

15、数WinMain接收控制前,先调用应用类的构造函数。CDrawApp:CDrawApp()/TODO:add construction code here,/Place all significant initialization in InitInstance将应用类对象theAPP定义成全局的,是为了在MFC中能够对CWinApp的成员函数进行调用,(2)WinMain接受控制,定义全局应用类对象theApp后,程序入口函数WinMain()接受控制。这个函数已经在MFC中做了定义,在建立执行文件时能够链接到应用程序Draw。,(3)调用函数InitInstance进行初始化,在实现文件d

16、raw.cpp中可以找到InitInstance的实现代码。这个函数完成最主要任务如下:定义并初始化了一个多文档模板对象pDocTemplate完成多文档模板的定义后,程序产生了一个主框架窗口,创建主框架窗口时采用的是IDRMAINFRAME资源。创建主框架窗口后,程序将处理命令行信息。命令行信息是跟随在命令后的参数。如可以用以下的语句启动应用程序Draw:Draw draw1.dat/启动应用程序Draw,并在启动后自动打开draw1.dat 文件最后,程序显示并更新主框架窗口。,(4)WinMain处理消息,完成初始化任务后,WinMain进入消息循环。通过Run()函数把消息从消息队列中

17、取出,并发送到别的窗口。大多数命令消息被发送到应用程序主窗口,其中的函数WindowProc()得到消息,再根据消息的类别送到适当的对象,激活并运行对象中的消息处理函数。,(5)WinMain退出,程序终止,在应用程序Draw中,运行“文件”菜单下的“退出”,或运行系统菜单的“关闭”,或单击主框架窗口的Close框时,应用程序删除程序窗口,并调用Win32 API函数:PostQuit Message,使消息循环退出,然后WinMain函数返回,程序终止。,3.4 使用ClassWizard,Windows应用程序是通过消息来控制流程的,MFC ClassWizard生成的应用程序为通过消息设

18、计程序提供了很好的框架。程序设计者甚至不必知道也不必参与控制消息传递的实际流程,而只需要掌握简单的使用方法就可以达到程序设计的目的。MFC ClassWizard为管理消息处理函数提供了一个强大的工具。,1.Windows消息,Windows应用程序一般是由消息驱动的(message_driven)。为处理诸如击鼠标键、窗口移动或改变大小、键盘输入等情况,Windows会向特定的窗口发送消息。在VC+中,一般的消息处理被包含在MFC中,用户特定的消息由程序设计者自己处理。应用类CWinApp中的Run()函数从Windows消息队列中获取消息,并在消息循环中把消息发送到适当的窗口。Window

19、s程序中的消息主要有三种类型:窗口消息、控件 的通知消息和命令消息。,窗口消息,窗口消息包括WM_开头的消息(除WM_COMMAND消息外),一般由窗口对象或视图对象处理。窗口消息往往带有参数,它是在窗口创建、改变大小、删除过程中,以及在受到操作(如受鼠标操作)时产生的,如WM_LBUTTONDOWN消息是在窗口中单击鼠标左键时产生的,WM_SIZE消息是在窗口大小改变时产生的。窗口消息是由窗口对象接收并处理的。窗口对象指的是从CWnd中派生出的类的对象,如从CWnd,CFrameWnd,CMDIFrameWnd,CMDIChildWnd,CView。CDialog等MFC类或这些类的派生类定

20、义的对象(这些类都是由窗口类CWnd直接或间接派生的)。,控件的通知消息,控件是一个小的子窗口,属于其他窗口(如对话框),能够接受操作并向父窗口(通常是对话框)发送消息。常见的控件有:按钮(Button)、列表框(ListBox)、编辑框(Edit)、复合框(ComboList)、滚动条(ScrollBar)等。从CCmdTarget派生的类,都可以接收这类消息。,命令消息,命令消息主要包括由用户交互对象发送的WM_COMMAND消息,用户交互对象指的是程序操作界面上的菜单、工具条、快捷键等。从CCmdTarget派生的类,都可以接收这类消息。命令消息可被多个对象接收,一个对象接收到命令消息后

21、,如果不处理,就把命令消息传递到其它的对象,直到被某个对象接收了。当某个命令消息在多于一个对象中有处理函数时,只有传递顺序在前面的窗口能够接收并处理消息。命令消息在各个对象中的传递顺序如下:,View-Doc-DocTemp-Frame-App 首先由框架类接收到该消息,框架类将该消息递交给其子窗口View,如果View没有对该消息进行响应,则由View递交给Doc,如果Doc也没有对该消息进行响应,那么它回再次将该消息回交给View,View再回交给Frame框架,框架检查自己是否对该消息有相应的处理函数,如果没有则递交给App,如果App也没有则由Windows系统自己处理。,2.消息处理

22、函数,消息处理函数指的是与某个消息对应的函数。消息处理函数的执行是由其对应的消息引发的,这个机制构成了Windows程序控制流程的基础。某个类对象中的消息处理函数是与这个类对象能够得到的一个消息对应的,当这个消息发生时,这个函数就被执行。消息处理函数的定义和使用方法与一般的成员函数不同。一般的成员函数包括两部分:函数的定义和函数的实现部分。定义一个一般成员函数时,在类中定义函数的原型(一般在头文件中),在实现文件中实现函数的实现代码。而消息处理函数除了这两部分以外,还有第三部分:消息映射部分,通过消息映射在消息处理和引发它的消息之间建立联系。,3.ClassWizard的启动,运行VC+开发平

23、台中“View”菜单下的“Class Wizard”菜单项,或者使用快捷键CTRLW在VC+工作平台的文件编辑窗口中单击鼠标右键,选择快捷菜单中的菜单项“Class Wizard”,MFC ClassWizard对话框的组成,Message Maps选项卡Member Variables选项卡Automation选项卡ActiveX Events选项卡Class Info选项卡,4.ClassWizard管理消息处理函数,管理窗口消息处理函数 实例:在视图窗口中跟踪鼠标的当前位置。(1)建立一个工程Example,激活ClassWizard,选中Message Maps选项卡(2)从Objec

24、t IDs列表框选择CExampleView(3)从Messages列表框中选择消息WM_MOUSEMOVE,此时Add Function按钮增亮,单击Add Function按钮(4)单击OK完成设定。(5)在OnMouseMove函数中增加以下代码:,char buff10;/字符型缓冲区CClientDC dc(this);/当前设备为CClientDC的对象sprintf(buff,%03d,%03d,point.x,point.y);/把鼠标点拷贝到缓冲区dc.TextOut(20,20,buff,strlen(buff);/在(20,20)显示鼠标点值/The sprintf fu

25、nction formats and stores a series of characters and values in buffer./The CDC:TextOut function writes a character string at the specified location,using the currently selected font,background color,and text color.,几点说明,ClassWizard通过固定的代码来识别窗口消息处理函数,通过以下两行代码来标识消息处理函数的定义:/AFX_MSG(CEx06View)/ClassWiza

26、rd 标示消息处理函数定义的起始代码Afx_msg void OnMouseMove(UINT nFlags,Cpoint point);/AFX_MSG/ClassWizard 标示消息处理函数定义的结束代码消息处理函数与普通函数的定义格式略有不同,需要在函数定义前加标示符afx_msg。,在实现文件中,消息映射机制写在如下的两行代码间而被ClassWizard识别:/AFX_MSG_MAP(CEx06View)/ClassWizard标识消息处理函数映射机制的起始代码ON_WM_MOUSEMOVE()/AFX_MSG_MAP/ClassWizard标识消息处理函数映射机制的结束代码只有当一

27、个消息处理函数的消息映射机制写在以上两行代码间时,才能被ClassWizard识别和处理。,命令消息处理函数实例:为菜单项增加命令消息处理函数(1)建立工程Draw,增加“绘制直线”菜单项(ID定为ID_DRAW_LINE)(2)进入ClassWizard,在“Class Name”列表框中选择CDrawView,在“Object Ids”列表框中选择ID_DRAW_LINE。(3)在Messages列表框中选择COMMAND消息,单击“Add Function”按钮,在弹出的对话框中输入消息处理函数的名称。可接受默认值。,添加如下代码CClientDC dc(this);dc.MoveTo(

28、20,20);dc.MoveT0(100,100);,几点说明,以上操作,在相应的源程序文件中进行了如下修改:(1)在视图类CDrawView中,增加了消息处理函数的定义代码(2)在类CDrawView的实现文件drawview.cpp中,增加了函数的实现代码(3)在实现文件drawview.cpp中,增加了消息映射。,控件消息处理函数控件消息处理函数是对应于VC+中各种控件消息的处理函数,多数存在于基于对话框的类中。对话框存在着用户定义的很多控件(如编辑框、列表框、复合框、滚动条等),这些控件在建立或被操作时会产生各种不同的控制消息。ClassWizard能够对这些控件消息的处理函数实行管理

29、。ClassWizard管理控件消息处理函数的操作方法与管理命令消息时是相同的。,5.ClassWizard管理重载虚函数,MFC程序框架中具有很多标准操作功能。例如,运行应用程序Draw“文件”菜单下的“打开”菜单项时,就会弹出文件选择对话框选择需要打开的文档,然后进行文档的打开工作。以上这过程在MFC中实现,它是由一系列函数组成的。为了让程序开发者对这个过程进行修改和控制,在以上这个操作过程中,应用了很多虚函数,在应用程序的当前类中,可以对基类中的这些虚函数进行重载,通过多态性而使MFC实现的标准操作过程执行当前类的虚函数。从而达到控制和修改MFC中已经实现的标准操作过程的目的。MFC C

30、lasswizard可以用来管理这些可以被重载的虚函数。,重载虚函数,实例:在应用程序Draw的类CDrawDoc中重载一个虚函数OnOpenDocument。这个虚函数在打开文档操作时被MFC应用程序框架调用,通常是作为FileOpen命令操作的一部分。默认情况下,这个虚函数用来打开指定的文件,调用DeleteContents虚函数清空文档,调用虚函数Serialize读取文件的内容。现在我们用ClassWizard在当前文档类CDrawDoc中重载这个虚函数,使得程序在打开文档文件操作的同时,打开一个与当前文件名称相同、而后缀不同的文件,做为应用程序Draw运行时的临时文件。,(1)打开C

31、lassWizard操作界面,在“Class Name”列表框中选择类CDrawDoc,在“Object Ids”列表框中选择CDrawDoc项。(2)在“Message”列表框列出的是类CDrawDoc能够得到的各种窗口消息和可重载的虚函数。从“Message”列表框选择虚函数OnOpenDocument。(3)单击“Add Function”按钮,按“Edit Code”进行代码添加。(4)在重载的OnOpenDocument函数中添加如下代码后,编译运行。,FilePath=lpszPathName;/得到当前文档的名称int n=FilePath.Find(.);/得到文件名中.的位置

32、if(n0)/如果当前的文档名称有后缀,去掉后缀FileName=FilePath.Left(n);else/如果文档名称中没有后缀FileName=FilePath;FileName+=.tmp;/增加一个.tmp后缀/以二进制方式打开一个可读写的文件,文件不存在就新建一个Fundo.Open(FileName,CFile:modeCreate|CFile:modeReadWrite|CFile:typeBinary);并在文档类CDrawDoc中定义如下变量:CFile Fundo;CString FilePath,FileName;,几点说明:(1)ClassWizard对文档类CDra

33、wDoc所作的修改定义部分/AFX_VIRTUAL(CDrawDoc)public:virtual BOOL OnNewDocument();virtual void Serialize(CArchive,(2)ClassWizard识别和处理重载虚函数所需要的标识ClassWizard能够识别定义在以下两行代码间的虚函数/AFX_VIRTUAL(CDrawDoc)/识别虚函数定义的开始代码/AFX_VIRTUAL/识别虚函数定义的结束代码第一行代码括号内为重载虚函数的类的名称。,必须在真正掌握程序的框架构造基础上使用工具初学者应先花费大量的精力弄懂MFC程序框架的组成结构,而后才能游刃有余的

34、控制程序。最不可取的是不懂框架结构和工具本质作用而盲目使用它。使用这些工具的目的,只是为了提高书写代码的效率,提高编程的速度,而不是用来代替程序设计。正确把握程序设计的要点程序设计的能力主要体现在对数据的组织和控制、流程的控制等方面。不同的计算机语言虽各有特点,但几乎所有的计算机语言其设计思想是内在相通的,程序设计能力的高低与采用哪种语言没有必然的联系。所以我们的课程重在培养实际能力,掌握计算机语言的实质。,必须在真正掌握程序的框架构造基础上使用工具初学者应先花费大量的精力弄懂MFC程序框架的组成结构,而后才能游刃有余的控制程序。最不可取的是不懂框架结构和工具本质作用而盲目使用它。使用这些工具的目的,只是为了提高书写代码的效率,提高编程的速度,而不是用来代替程序设计。正确把握程序设计的要点程序设计的能力主要体现在对数据的组织和控制、流程的控制等方面。不同的计算机语言虽各有特点,但几乎所有的计算机语言其设计思想是内在相通的,程序设计能力的高低与采用哪种语言没有必然的联系。所以我们的课程重在培养实际能力,掌握计算机语言的实质。,两点建议,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号