
一个优秀的编程工具往往匹配一个功能强大的类库,类库封装了大量Windows编程需要使用的函数和数据结构。与Visual C++捆绑在一起的MFC(Microsoft Foundation Class)微软基础类就是这样一个由Microsoft公司设计的类库。采用MFC方式编程提高了Windows应用程序的开发效率,但由于MFC应用程序结构的复杂性和透明性,要想完全掌握MFC应用程序的内部机制需要付出很大的努力。
利用Windows API开发程序的用户有这样的体会,即使开发一个简单的Windows应用程序也需要对Windows的编程原理有很深刻的认识,需要手工编写冗长的代码。由于程序的出错率是随着代码长度的增加呈几何级数增长的,而且当程序长度逐渐膨胀时,调试程序会变得越来越困难。因此,传统的Windows应用程序设计需要程序员有极大的耐心和丰富的编程经验。
Visual C++捆绑了微软的基础类MFC,编程时程序员就可以利用类的可重用性和可扩充性,大大降低Windows应用程序设计的难度和工作量。
9.5.1 MFC概述
类库是一个可以在应用程序中使用的相互关联的C++类的集合。MFC作为一个Windows编程类库,它包含了200多个类,封装了Windows的大部分编程对象以及与它们有关的操作。
虽然程序在功能上千差万别,但从本质上看,都可以分为用户界面设计、文件操作、数据库访问及多媒体使用等几部分,这些都可以通过一些类来实现。MFC提供了一个标准化的程序结构,使开发人员不必从头设计一个Windows应用程序。
MFC实际上是一个庞大的文件库,它由几百个执行文件和源代码文件(如H文件)组成。
关于API和SDK:
Windows API(Application Programming Interface)是Windows操作系统与应用程序之间的标准接口,它提供了上千个标准函数、宏和数据结构的定义。
在使用Visual C++、Visual Basic和Delphi编程时都可以调用Windows API函数,Windows应用程序可通过调用标准Windows API函数使用系统提供的功能。
Windows API函数定义在一些DLL动态链接库中,其中最主要的DLL是User32.dll、Gdi32.dll和Kernel32.dll三个库文件。
传统SDK编程:程序员通过调用API函数,自己动手、按部就班地实现程序各部分的功能。SDK应用程序的结构比较清晰,但程序员必须编写所有的功能代码。
利用Visual C++编写一个类SDK应用程序:首先利用Win32 Application向导建立一个Windows应用程序框架,然后根据需要可以向程序项目中添加一些头文件、实现源文件和资源文件,并编写具体的程序代码。
采用MFC编程的优点:
1、使用标准化的程序代码结构,有利于程序员之间的交流。
2、Visual C++为MFC提供了大量的工具支持,提高了编程效率。如利用MFC AppWizard创建MFC应用程序框架,利用ClassWizard方便地对Windows消息进行管理。
3、MFC应用程序的效率较高,只比传统的Windows C程序低5%左右。并且,在MFC应用程序中还允许混合使用传统的Windows API函数。
其它优势:完全支持Windows所有的函数、控件、消息、菜单及对话框;具有良好的稳定性和可移植性,更符合微软的风格等。
9.5.2 MFC体系结构
MFC主要组成部分:类、宏和全局函数。
类是MFC中最主要的内容。MFC类是以层次结构方式组织起来的。MFC中的类分成两部分,除了一些辅助类,大多数的MFC类是直接或间接从根类CObject派生而来。
几乎每一个派生层次都与一具体的Windows实例相对应,如文档类、窗口类和视图类等。
MFC宏主要功能:消息映射、运行时对象类型服务、诊断服务、异常处理。
MFC约定:全局函数以“Afx”为前缀,全局变量以“afx”为前缀。
9.5.3 学习MFC的方法
首先要对Windows编程概念和API函数有一定的了解,如Windows API有哪些功能和哪些常用的数据结构等。
学会抽象地把握问题,不求甚解,不要一开始学习Visual C++就试图了解整个MFC类库。从理解和使用两个方面学习MFC,理解MFC应用程序的框架结构。
先大体上了解MFC的概念、组成和基本约定,从简单的类入手,结合程序设计,由浅入深,循序渐进、日积月累。
编程时如果MFC某个类能完成所需要的功能,可以直接调用已有类的方法(成员函数)。否则,可以利用面向对象技术中的“继承”方法对MFC类的行为进行扩充和修改,从MFC中已有的类派生出自己需要的类。
学习MFC,另一点就是不要过分依赖于向导(Wizard)工具。向导能做许多工作,但同时掩饰了太多的细节。
10.5 MFC应用程序框架
10.5.1 应用程序框架中的对象
MFC应用程序框架提供了构建应用程序所需要的类,在程序运行时能够生成运行时类的对象,如代表应用程序对象、文档对象、视图对象和框架窗口对象。应用程序对象theApp是一个唯一的全局变量,它的主要功能是通过调用WinMain()主函数启动程序的运行。
MFC应用程序框架也有一个作为程序入口点的WinMain()主函数,但在源程序中看不见该函数,它在MFC中已定义好并同应用程序相链接。
MFC应用程序框架对象之间的关系如下图所示:
10.5.2 MFC应用程序的生与死
在MFC应用程序的CWinApp派生类对象theApp是一个全局变量,代表了应用程序运行的主线程。它在程序整个运行期间都存在,它的销毁意味着运行程序的消亡。
MFC应用程序启动时,首先创建应用程序对象theApp,这时将自动调用应用程序类的构造函数初始化对象theApp,然后由应用程序框架调用MFC提供的AfxWinMain()主函数。
AfxWinMain()主函数首先通过调用全局函数AfxGetApp()获取应用程序对象theApp的指针pApp,然后通过pApp调用应用程序对象的有关成员函数,完成程序的初始化和启动工作,最后调用成员函数Run(),进入消息循环。
程序运行后将收到WM_PAINT消息,调用OnPaint()函数绘制客户区窗口。如果Run()收到WM_QUIT消息,则结束消息循环,然后调用函数ExitInstance(),结束程序运行。
MFC应用程序运行后各函数的调用关系如下所示:
InitInstance()函数是派生类唯一需要重载的函数,它负责应用程序的初始化,如初始化数据、创建文档模板、处理命令行以及显示应用程序主窗口。
10.5.3 常用的MFC文件和库文件
| 文 件 名 称 | 说 明 |
| afxwin.h | 声明MFC核心类 |
| afxext.h | MFC扩展文件,声明工具栏、状态栏、拆分窗口等类 |
| afxdisp.h | 声明OLE类 |
| afxdtctl.h | 声明支持IE 4公用控件的MFC类,如CImageList等 |
| afxcmn.h | 声明Windows公共控件类 |
| Mfc42.lib Mfc42D.lib | MFCxx.DLL的导入函数库(Release版) MFCxx.DLL的导入函数库(Debug版) |
| MfcS42.lib | MFCSxx.DLL的导入函数库(Static Release版) |
| MfcS42D.lib | MFCSxxD.DLL的导入函数库(Static Debug版) |
| Mfc42U.lib | MFCxxU.DLL的导入函数库(Unicode Release版) |
| Mfc42UD.lib | MFCxxUD.DLL的导入函数库(Unicode Debug版) |
| MfcO42D.lib | MFCOxxD.DLL的导入函数库(OLE Debug版) |
| MfcD42D.lib | MFCDxxD.DLL的导入函数库(Database Debug版) |
| Nafxcw.lib | MFC静态链接库(Release版) |
| NafxcwD.lib | MFC静态链接库(Debug版) |
| gdi32.lib | GDI32.DLL的导入函数库 |
| user32.lib | USER32.DLL的导入函数库 |
| kernel32.lib | KERNEL32.DLL的导入函数库 |
| msvcrt.lib | MSVCRT.DLL(C运行函数库)的导入函数库 |
| msvcrtd.lib | MSVCRTD.DLL(Debug版C运行函数库)的导入函数库 |
| libcmt.lib | C运行函数静态链接库(多线程) |
| libc.lib | C运行函数静态链接库(单线程) |
MFC消息管理是MFC编程的一个重要内容,也是编写MFC应用程序的基础。
MFC应用程序消息处理的方式与SDK应用程序有所不同。MFC应用程序框架截取了Windows向应用程序发出的消息,再确定将消息发送给哪一个对象,可以根据需要利用函数重载对消息进行处理,但不需要处理的消息将由应用程序框架自动处理。
消息管理包括消息的发送和处理。对于消息发送,MFC提供了类似于API函数功能的消息发送函数,而MFC消息处理的内部机制则相对复杂一些。从编程的角度出发,只需了解其大致的原理。
