VC内部培训资料第4章MFC应用程序框架剖析.docx
- 文档编号:3807998
- 上传时间:2022-11-25
- 格式:DOCX
- 页数:39
- 大小:602.95KB
VC内部培训资料第4章MFC应用程序框架剖析.docx
《VC内部培训资料第4章MFC应用程序框架剖析.docx》由会员分享,可在线阅读,更多相关《VC内部培训资料第4章MFC应用程序框架剖析.docx(39页珍藏版)》请在冰豆网上搜索。
VC内部培训资料第4章MFC应用程序框架剖析
第4章MFC应用程序框架剖析
在进行一个Windows应用程序开发之前,首先需要选择一个开发环境。
假定我们现在只给出两种选择:
一种是使用Win32应用程序编程接口的C语言程序;另一种是使用MFC应用程序框架的C++语言程序。
在这里,笔者并不想阐述这两种选择哪个更好,而是想通过这两种开发环境的比较让读者更好的理解本章将要讲述的重点——MFC。
4.1什么是MFC以及MFC的特点
只要使用过传统的windows编程方法开发应用程序的读者都深刻地体会到,即使是开发一个简单的windows应用程序也需要对windows的内部编程原理有很深刻的认识,同时也要手工编写很多的代码。
用C直接编写WindowsAPI应用程序,代码量是非常大的,因为你所要照顾的细节太多了,更令人头疼的是,随着代码行数的增多,程序的可读性、可维护性也大大的降低,因此,传统的windows编程是需要极大的耐心和丰富的编程经验的。
近几年来,面向对象技术无论是在理论还是实践上都在飞速地发展。
面向对象技术中最重要的就是“对象”的概念,它把现实世界中的人、机器等客观实体抽象成程序中的“对象”。
这种“对象”具有一定的属性和方法,这里的属性指对象本身的各种特性参数。
如人的体重,机器的体积等,而方法是指对象本身所能执行的功能,如人能行走,机器能运作等。
一个具体的对象可以有许多的属性和方法,面向对象技术的重要特点就是对象的封装性,对于外界而言,并不需要知道对象有哪些属性,也不需要知道对象本身的方法是如何实现的,而只需要知道如何调用对象所提供的方法来完成特定的功能。
从这里我们可以看出,当把面向对象技术应用到程序设计中时,程序员只是在编写对象方法时才需要关心对象本身的细节问题,大部分的时间是放在对对象的方法的调用上,组织这些对象进行协同工作。
MFC的英文全称是MicrosoftFundationClasses,即微软的基本类库,它位于任何WindowsAPI之上,在这个类库中包含了一百多个程序开发过程中最常用到的对象。
它减少了大量在建立Windows程序时必须编写的代码。
同时它还提供了所有一般C++编程的优点,例如继承和封装。
正是由于MFC编程方法充分利用了面向对象技术的优点,它使得我们在编程时极少需要关心对象方法的实现细节,而只需要简单地调用已有对象的方法就可以了。
即使类库中的那些对象的方法不能满足我们的需要时,我们还可以利用面向对象技术中很重要的“继承”方法从类库中的已有对象派生出我们自己的对象,这时派生出来的对象除了具有类库中的对象的特性和功能之外,还可以由我们自己根据需要加上所需的特性和方法,产生一个更专门的,功能更为强大的对象。
这使得应用程序中程序员所需要编写的代码大为减少,有力地保证了程序的良好的可调试性。
MFC不仅给用户提供了Windows图形环境下应用程序的框架,而且还提供了创建应用程序的组件。
下面,我们将会通过一个实例来验证MFC的特点。
还记得我们在第二章中讲过的那个创建窗口的程序(EX02-00)吗?
创建一个窗口然后在该窗口的顶端打印一条语句并响应鼠标键盘消息,读者大概不会忘了,为了实现这个功能所要做的那些烦琐的步骤,包括创建一个窗口类、注册类、创建窗口、刷新窗口、消息循环等等。
下面,我们将利用MFC类库功能模仿AppWizard建立一个这样的程序,看看它是怎么实现的。
请看清单4-00中的代码。
如果你是第一次看到这类程序,也许比较难理解,这没关系,我们后面会详细介绍。
现在你只要用VisualC++环境中建立、编译和运行它就可以了。
建立一个Win32程序(实际上本节的这个程序并非一个真正W32程序,只是采用W32编程环境,利用MFC类库来实现)的过程忘了吗?
步骤同第二章所讲述的一样,只不过代码不同。
启动VisualC++,打开NewWizard对话框,选择Project选项卡,在左边的窗口中选择Win32Application,在右边输入工程名,OK就可以了,然后从Project菜单中选择AddtoProject|New,再次打开NewWizard对话框,在左边窗口选择C++Sourcefile,在右边输入和工程名相同的文件名就可以了,最后在代码编辑区中输入下面清单中的语句就可以编译运行了。
完整的例程请参见光盘中的例子代码EX04-00。
清单4-00模仿MFC应用程序框架生成一个窗口
//*****************************************************
//MyApp.h
//*****************************************************
#include"afxwin.h"
classCMyApp:
publicCWinApp
{
public:
virtualBOOLInitInstance();
};
classCMyFrame:
publicCFrameWnd
{
public:
CMyFrame();
protected:
afx_msgvoidOnPaint();
DECLARE_MESSAGE_MAP()
};
//*****************************************************
//MyApp.cpp
//*****************************************************
CMyApptheApp;//建立一个CMyAPP对象
BOOLCMyApp:
:
InitInstance()
{
m_pMainWnd=newCMyFrame();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
returnTRUE;
}
BEGIN_MESSAGE_MAP(CMyFrame,CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
CMyFrame:
:
CMyFrame()
{
Create(NULL,"MYAPPApplication");
}
voidCMyFrame:
:
OnPaint()
{
CPaintDCdc(this);
dc.TextOut(0,0,"HelloWorld!
");
}
编译上面的程序,报错!
!
为什么呢?
原来还没有添加MFC的支持,从Project菜单选定Setting对话框,选择General属性页,在MicrosoftFoundationClasses标题下选择UseMFCinaStaticLibrary一项就可以了。
上面的程序只是模仿MFC应用程序框架生成的一个程序,实际上,若是真正用MFC应用程序框架来生成该程序,用户只需要键入清单中黑体的那一条语句,而其他那些语句,在用AppWizard应用程序向导生成框架时AppWizard已经自动为我们添加了。
我们所要做的工作,只是找到OnDraw()或OnPaint()成员函数,键入pDC->TextOut(0,0,"HelloWorld!
");或dc.TextOut(0,0,"HelloWorld!
");一条代码就可以了。
看出来了吧,使用MFC进行Windows编程时是一件多么容易的过程。
综上所述,MFC的优点可归结为以下几点:
●MFC是C++的MicrosoftWindows应用程序编程接口。
●MFC开发的应用程序使用了标准化的结构。
●使用MFC开发的应用程序不仅小,而且运行快。
●VisualC++工具降低了编码的复杂性。
●MFC库功能丰富(具体功能请参见相关书籍)。
4.2什么是MFC应用程序框架
什么是应用程序框架(ApplicationFrame)?
大概有的读者还不了解。
说白了,就是一个集合,而这个集合可以提供一般应用程序所需的全部面向对象软件组件。
一个应用程序框架是一个类库的超级集合。
一般的库是设计集成到任何程序类的集合,但是一个应用程序框架不同于单纯的类的集合,它自己定义了程序的结构。
上面空洞的语句大概并不能使我们很好的了解到底什么是应用程序框架,那么,我们将通过使用AppWizard应用程序向导生成的一个最简单的程序来使大家理解到底什么是应用程序框架。
1.首先启动VisualC++,在“File”菜单中选择“New”选项,打开NewWizard,如图4-00所示,在该窗体中选择Projects标签,然后在左侧窗口选择MFCAppWizard(exe),在右侧的ProjectName(项目名)文本框中,为新建的项目输入一个名称,如Test。
2.单击OK按钮弹出MFCAppWizard—Step1对话框,如图4-01所示。
该对话框中要求用户选择生成哪种类型的应用程序:
单文档(Singledocument)、多文档(Multipledocumens)还是基于对话框(Dialogbased)的应用程序。
我们选择Singledocument,其他的按默认设置。
需要用户了解的是如果我们选择Singledocument,那么应用程序会给我们生成一个单文档-视图应用程序框架;如果我们选择的是Multipledocumens,那么应用程序会给我们生成一个多文档-视图应用程序框架
图4-00NewWizard
图4-01MFCAppWizard—Step1对话框
3.单击NEXT按钮弹出MFCAppWizard—Step2of6对话框,如图4-02所示。
询问用户应用程序是否支持数据库:
不支持数据库(None)、仅支持头文件(Headerfilesonly)、没有支持文件的数据库视图(Databaseviewwithoutfilesupport)、带文件支持的数据库视图(Databaseviewwithfilesupport)。
我们选择None。
图4-02MFCAppWizard—Step2of6对话框
4.单击NEXT按钮弹出MFCAppWizard—Step3of6对话框,如图4-03所示。
询问用户应用程序支持何种复合文档:
不支持复合文档(None)、容器(Container)、能够创建管理复合文档但Mini-server应用程序不能单独运行(Mini-server)、能够创建管理复合文档并且能单独运行(Full-server)、用户应用程序既是容器又是服务器(Bothcontainerandserver)。
我们选择None,其他设置按默认。
图4-03MFCAppWizard—Step3of6对话框
图4-04MFCAppWizard—Step4of6对话框
5.单击NEXT按钮弹出MFCAppWizard—Step4of6对话框,如图4-04所示。
询问用户生成何种特征的应用程序:
增加一个工具栏(Dockingtoolbar),增加一个状态栏(Initialstatusbar),生成打印和预览命令的代码(Printingandprintpreview),生成支持上下文相关帮助的帮助文件(Context-sensitiveHelp),支持三维效果(3Dcontrols),使应用程序能够创建、操作、传输和存储邮件消息(MAPIMessagingAPI),支持WindowsSockets(WindowsSockets)。
这里所有设置我们都采用默认的。
6.单击NEXT按钮弹出MFCAppWizard—Step5of6对话框,如图4-05所示。
询问工程的样式、是否生成源文件注释及怎样使用MFC类库。
一切按默认设置。
图4-05MFCAppWizard—Step5of6对话框
图4-06MFCAppWizard—Step6of6对话框
7.单击NEXT按钮弹出MFCAppWizard—Step6of6对话框,如图4-06所示。
对话框中的默认设置确定了类的名称及其所在文件的名称,用户可以改变名称,但我们建议您使用向导自动生成的名称。
在VisualC++中,AppWizard允许你选用MFC类库中其他视图类作为应用程序视图类的基类,不一定非得是默认的CView类,您可以改成CEditView类。
这里,我们全部采用默认设置。
8.单击FINISH按钮弹出NewProjectInformation对话框,如图4-07所示。
这个对话框主要显示创建的文件的清单。
最后单击OK按钮,大功告成!
不管您相不相信,我们已经生成了一个使用MFC基本类库的应用程序基本框架(单文档-视图体系结构的应用程序框架)。
而且马上就可以运行。
运行之后,您会发现这个应用程序框架具备WINDOWS程序的所有特性,菜单、工具条、状态栏、图标甚至还有关于对话框、打印预览.....全了,这就是AppWizard通过MFC动态创建的一个应用程序框架。
从这个小例子可以看出用VC/MFC设计WINDOWS程序是多么方便的了吧。
也许读者对此很不理解,为什么没有编写一句代码就出来个应用程序框架,而且WinMain函数和WndProc回调函数都不见了?
其实,WinMain函数和WndProc回调函数并没有不见,也不是Window程序结构发生了变化,这全都是MFC的功劳,我们这个应用程序框架的底层仍然采用的是WinMain函数和WndProc回调函数,只是它们被MFC封装在各个类里了,然后MFC通过应用程序向导为我们生成了这些类,我们所要做的就是往这个类里添加一些内容,如重载函数、消息处理等等。
就好比MFC程序框架是一座大楼的主梁,主梁都有了,剩下程序员所要做的就是添砖加瓦。
而在Win32程序中,甚至主梁都要程序员自己搭建,是不是很累啊。
图4-07NewProjectInformation对话框
现在,读者可以验证一下上一节中提到的只需要键入一条代码就可以在屏幕上显示出“HelloWorld!
”。
在工作台中,在ClassView选择CTestView类的OnDraw()成员函数双击,填入如下一条代码:
pDC->TextOut(0,0,"HelloWorld!
");运行一下,怎么样,是不是也显示出了HelloWorld字样,很简单吧,完整例程请参见光盘中的例子代码EX04-01。
这就是MFC应用程序框架的好处。
4.3应用程序框架说明
本节将对AppWizard向导自动生成的应用程序框架的内容做一个详细的介绍。
让您对MFC方式的WINDOWS应用程序的工作原理有全面的认识,只有这样你才会知道应该如何往程序框架当中添加需要的代码。
我们将从两方面做介绍:
一个是文件;另一个是类。
4.3.1文件说明
在使用VisualC++开发应用程序的过程中,系统为我们生成了大量的各种类型的文件,在本节中将要详细介绍VisualC++中这些不同类型的文件分别起到什么样的作用,在此基础上对VisualC++如何管理应用程序所用到的各种文件有一个全面的认识。
首先要介绍的是扩展名为dsw的文件类型,这种类型的文件在VC中是级别最高的,称为Workspace文件。
在VC中,应用程序是以Project的形式存在的,Project文件以.dsp扩展名,在Workspace文件中可以包含多个项目,由Workspace文件对它们进行统一的协调和管理。
与dsw类型的Workspace文件相配合的一个重要的文件类型是以opt为扩展名的文件,这个文件中包含的是在Workspace文件中要用到的本地计算机的有关配置信息,所以这个文件不能在不同的计算机上共享,当我们打开一个Workspace文件时,如果系统找不到需要的opt类型文件,就会自动地创建一个与之配合的包含本地计算机信息的opt文件。
上面提到Project文件的扩展名是dsp,这个文件中存放的是一个特定的工程,也就是特定的应用程序的有关信息,每个工程都对应有一个dsp类型的文件。
以clw为扩展名的文件是用来存放应用程序中用到的类和资源的信息的,这些信息是VC中的ClassWizard工具管理和使用类的信息来源。
对应每个应用程序有一个readme.txt文件,这个文件中列出了应用程序中用到的所有的文件的信息,打开并查看其中的内容就可以对应用程序的文件结构有一个基本的认识。
在应用程序中大量应用的是以h和cpp为扩展名的文件,以h为扩展名的文件称为头文件。
以cpp为扩展名的文件称为实现文件,一般说来h为扩展名的文件与cpp为扩展名的文件是一一对应配合使用的,在h为扩展名的文件中包含的主要是类的定义,而在cpp为扩展名的文件中包含的主要是类成员函数的实现代码。
在应用程序中经常要使用一些位图、菜单之类的资源,VC中以rc为扩展名的文件称为资源文件,其中包含了应用程序中用到的所有的windows资源,要指出的一点是rc文件可以直接在VC集成环境中以可视化的方法进行编辑和修改。
最后要介绍的是以rc2为扩展名的文件,它也是资源文件,但这个文件中的资源不能在VC的集成环境下直接进行编辑和修改,而是由我们自己根据需要手工地编辑这个文件。
对于以ico,bmp等为扩展名的文件是具体的资源,产生这种资源的途径很多。
使用rc资源文件的目的就是为了对程序中用到的大量的资源进行统一的管理。
图4-08工作台ClassView
4.3.1类的说明
打开工作台,我们可以看到系统在生成应用程序框架的过程中,自动为我们生成了这么几个类:
CTestApp、CMainFrame、CTestView、CTestDoc。
这些类名字中的test并不是固定的类名,而是我们起的工程的名字。
如我们建立的工程名为abc,那么系统为我们生成的类名分别为CabcApp、CMainFrame、CabctView、CabcDoc。
如图4-08所示。
前面我们已经提到过,在应用程序中有一个重要的函数WINMAIN(),这个函数是应用程序的基础,用户的操作所产生的消息正是经过这个函数的处理派送到对应的对象中进行处理。
在MFC方式的WINDOWS应用程序中,用来处理消息的是系统自动生成的MFC中的类CWINAPP的派生类CTestAPP,下面就从这个类开始介绍应用程序的框架。
也请读者参照下面的讲解来自行分析一下清单4-00的代码。
●类CTestApp(基类为CWinApp)
若想创建MFC应用程序,首先要使用CWinApp类,因为CWinApp类不仅代表了程序中运行的主线程,而且代表了应用程序本身,在任何MFC应用程序中只有一个CWinApp对象,它用于控制应用程序的初始化、启动应用程序、运行主消息循环、终止应用程序。
当用AppWizard向导创建一个应用程序框架之后,应用程序框架自动生成了唯一的应用程序对象theApp。
从表面上看它仅是某个类的一个实例,实际上它内部隐藏了许多细节,如隐藏了程序最开始执行的WinMain函数。
CWinApp类有三个重要的成员函数分别为InitInstance()、Run()、ExitInstance(),其中InitInstance()成员函数是必须被重载的成员函数,AppWizard向导为我们生成的应用程序框架中的类CTestApp便重载了该函数,它负责进行特定应用程序的初始化,包括装入MRU列表。
Run()函数是用来处理消息循环的,我们不建议用户去重载它,该函数在后面讲述消息的章节中会有详细的介绍。
ExitInstance()函数是做收尾工作的,应用程序通过调用该函数来结束运行,用户可以重载该函数以完成特殊的清除要求,如释放内存。
我们讲过InitInstance()成员函数是必须被重载的成员函数,因为CTestAPP就是由MFC中的类CWINAPP派生来的,因此CTestAPP不仅是AppWizard向导为我们自动生成的应用程序运行的基础,而且,在这个类中除了具有一般类都有的构造函数之外,还有一个重要的成员函数就是InitInstance,我们知道,在WINDOWS环境下面可以运行同一程序的多个实例,函数InitInstance的作用就是在生成的一个新的实例的时候,完成一些初始化的工作。
当生成一个CTestApp类型的对象的时候,系统会主动调用InitInstance函数完成一些必要的初始化工作。
应用程序类的另一个主要的功能就是通过文档模板CDocTemplate将框架窗口类、文档类及视图类联系起来。
文档模板类是抽象类,因而不能直接使用,但可以使用它的两个派生类:
针对于单文档的CSingleDocTemplate类和针对于多文档的CMultiDocTemplate类。
此功能也是由应用程序类的InitInstance函数实现。
下面研究InitInstance函数所做的事情,注意下面这一段代码,
CSingleDocTemplate*pDocTemplate;
pDocTemplate=newCSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CTestDoc),
RUNTIME_CLASS(CMainFrame),//mainSDIframewindow
RUNTIME_CLASS(CTestView));
AddDocTemplate(pDocTemplate);
它定义了一个文档模板对象指针PDocTemplate,通过New操作符,系统动态生成了这个文档模板对象,然后使用AddDocTemplate函数把这个文档模板对象加入到应用程序所维护的文档模板链表当中,这个文档模板pDocTemplate的作用就是把程序用到的框架窗口,CMainFrame,文档CTestDoc,视窗CTestView与应用对象CTestApp联系起来。
CTestApp类提供了用户与WINDOWS应用程序之间进行交流的界面。
在生成这个类的对象后,这个对象自动地把自身与WINDOWS系统建立联系,接收WINDOWS传送的消息,并交给程序中相应的对象去处理,这就免去了程序员许多的工作,使得开发C++的WINDOWS程序变得简单方便。
●类CMainFrame(基类为CFrameWnd)
类CMainFrame是由MFC中的CFRAMEWND派生来的,所以它也是一个框架窗口。
主框架窗口类负责标题栏、菜单栏工具栏及状态栏的生成。
事实上,这些子窗口是可以按照用户的意图自定义的,这只需要修改主框架窗口的实现文件即可。
CMainFrame是CTestView的父类,也就是说视窗VIEW显示在主框窗口MAINFRAME的客户区中。
在类CMainFrame中,系统已经从类CFrameWnd那里继承了处理窗口的一般事件的WINDOWS消息,比如改变窗口的大小,窗口最小化等等的成员函数,因此编程的时候程序员不需要再关心此类消息的处理,从而减轻了程序员的负担。
当然,如果确实需要重新编写处理此类消息的成员函数,则需要对原有的成员函数进行重载。
在MFC程序中,由于CTestView类是覆盖在CMainFrame类窗口之上的,因此我们并不需要经常对CMainFrame类进行操作,更多的是对视窗类进行操作,达到对程序中的数据进行编辑和修改的目的。
最后要指出的是,在MFC方式的程序中,当程序的一个实例被运行的时候,系统根据前面在CTestApp类中介绍的文档模板对象自动生成类CMainFrame,CTestView,CTestDoc的对象,而不需要程序员主动地去创建这些类的对象。
另外,应用程序框架通过主框架窗口与视图对象、文档对象利
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VC内部培训资料第4章 MFC应用程序框架剖析 VC 内部 培训资料 MFC 应用程序 框架 剖析