第九章 MFC基础知识  
 
  在VC++的编程中,从前面的章节内容,大家可能已经看到,利用Windows API函数进行编程时,大量的代码需要用户自己编写,及其户编程的工作量较大,从本章开始,我们将讨论VC++的另一种编程方法,利用MFC和向导(Wizard)来编写Windows应用程序,即首先使用Class Wizard来生成Windows应用程序的基本框架,然后用ClassWizard来建立应用程序的类、消息处理、数据处理函数或定义控件的属性、事件和方法,最后把各应用程序所要求的功能添加到类中。

  9.1 MFC概述

  MFC1.0 & MS C/C++7.0 应用程序中非图形部分的类、GDI功能的Windows相关类
  MFC2.0 & MS VC++1.0在1.0基础上增添了一些应用程序
  MFC2.0 & MS VC++1.5 添加了ODBC类,并且还支持OLE的性能
  MFC3.0 & VC++2.0增添了对开发32位应用程序的支持
  MFC4.0包含了在Win95和NT中大多数新的公共控件和DAO、MAPI
  MFC4.21增强了对数据库应用程序的支持
  利用DAO类通过编程语言来访问、操纵和管理数据库
  对Internet也提供了强有力的支持
  MFC是用来编写Windows应用程序的C++类集,该类集以层次结构组织起来,其中封装了大部分Windows API函数和Windows控件,它所包含的功能涉及到整个Windows操作系统。MFC不仅为用户提供了 Windows图形环境下应用程序的框架,而且还提供了创建应用程序的组件。使用MFC类库和Visual C++提供的高度可视的应用程序开发工具,可使应用程序开发变得更简单,开发周期极大地缩短,提高代码的可靠性和可重用性。
  代码重用是C++长期寻求的目标。对于C++程序员而言,重用通常是指从先前已有的基类派生新的C++类的技术。MFC正好提供了大量的基类供程序员根据不同的应用环境进行扩充。
  MFC提供的类库对程序设计的高度抽象,使得程序员的主要精力不用放在程序设计的细节实现上,而放在程序的功能拓展上面,它同时允许在编程过程中自定义和扩展应用程序中的类,MFC同时还允许对Windows API进行存取,从而使应用程序能以最小的规模实现最丰富的功能,而且能提供高效率的运行代码。
  MFC是C++语言中的一个安全子集,它大大简化使用C++开发基于Windows的应用程序的工作,MFC精心设计的类库结构,以一种直观的软件包的形式把进行Windows应用开发这一过程所需的各种程序模块有机地组织起来,经验丰富的C++开发人员可以使用MFC实现C++中的高级功能。
  MFC被设计成可移植于众多的平台,允许其应用程序适用于多种不同平台。对于多种编译器,MFC也是可以移植的,而且有许多软件开发公司已经把它作为一种基于Windows开发标准的应用程序构架。
  MFC之所以得名为微软基础类库,是因为它代表着正在不断带给Windows操纵系统中开发人员以最好支持的基本类结构。它所包含的类分层结构和功能可伸缩性的,它的这种可伸缩性使得MFC始终能跟踪上软件发展的潮流,而且在功能扩展的同时,MFC还很好地保持了程序的向下兼容性。
  1992年4月,第一个MFC(Microsoft Foundation Class)版本即MFC1.0,伴随着Microsoft C/C++ 7.0版一起发布。当时的MFC1.0中主要包括两种类型的类:一种是用于应用程序中非图形部分的类和用于应用程序的图形用户界面(Graphics Device Interface 缩写为GDI)功能的Windows相关类。
  1993年2月,MFC2.0伴随着Visual C++1.0版一起发布。其被扩展后的核心功能在原有的基础上又增添了一些新的构造类,这些构造类有助于组织和构造应用程序,以及对Windows应用程序中部分界面元素的高层抽象,这些高层抽象有助于程序员优化界面,使得应用程序更易操作。
  1993年12月,MFC与Visual C++ 1.5一起发布。这一版本的MFC添加了与数据库进行连接的ODBC数据库类,ODBC数据库类允许应用程序访问具有ODBC驱动程序的数据库中的数据,程序员可以通过ODBC(Open Database Connection,开放数据库互联,简称ODBC)对某些数据源进行存取,并且这一版本的MFC还全面支持OLE的众多性能,不过这一版本的MFC是基于16位的应用程序而开发的。
  1994年9月,MFC3.0作为Visual C++2.0的一部分公开发布,这个版本的MFC增添了对开发32位应用程序的支持,具有更丰富的用户界面风格,以及对Win32 API和OLEControl扩展的更多支持。MFC3.0将MFC的影响扩展到大多数基于Win32应用程序的核心底层结构。随后的两个版本中有添加了对Windows公共控件和 Sockets等的支持。
  1995年10月推出的MFC4.0中包含了在Windows95和Windows NT操作系统中大多数新的Windows公共控件,它能进一步支持OLE的扩展功能,使得开发人员可以建立、使用并且可以和其他开发人员共享OLE控件。MFC4.0除了继续扩大对ODBC的支持外,还提供了一种新的数据存取对象(Data Access Object 简称DAO)类,通过DAO类,程序员可以直接存取Miscrosoft Jet数据库引擎,它是一种和Microsoft Access for Windows 98和Miscrosoft Visual Basic中的引擎完全相同的引擎。DAO类包含了Jet数据库引擎的OLE COM接口,开发人员不必亲自编写SQL程序就可以实现对数据库的操作,当使用DAO类时,程序员可以有计划地访问和操纵数据库内的数据,并管理数据库、数据库对象及数据库结构;MFC中还引进了线程同步对象的概念,为了管理线程的同步操作,MFC提供了一个新的基类――CSyncObject,以及代表公用同步技术的几个派生对象。MFC还提供了对Windows 的消息应用程序接口(Message Application Programming Interface 简称MAPI)的支持,通过MFC的这一扩展,程序员可以很容易开发出用于建立、处理、转送以及存储邮件消息的应用程序。MFC还进一步增强了对Windows Sockets的支持,通过MFC可以较容易地实现在Windows 操作系统环境下的网络通信程序而编写的。
  目前使用的MFC4.21增强了对数据库应用程序的支持,可以使用ODBC类和高性能的ODBC驱动程序来访问提供ODBC支持的数据库中的数据;可以通过数据访问对象(DAO)类通过编程语言来访问和操纵数据库中的数据并管理数据库、数据库对象与结构,同时MFC4.21对Internet也提供了强有力的支持。

  9.2 MFC类的组织结构及主要的类的简介

  9.2.1 MFC类的组织结构

  目前的MFC版本中包含了100多个类,不同的类实现不同的功能,类之间既有区别又有联系。MFC同时还是一个应用程序框架,它帮助定义应用程序的结构,以及为应用程序处理许多杂务,事实上,MFC封装了一个程序操作的每一个方面。在MFC程序中,程序员很少需要直接调用Windows API函数,而是通过定义MFC类的对象并通过调用对象的成员函数来实现相应的功能。
  MFC类库中类是以层次结构的方式组织起来的,几乎每个子层次结构都与一具体的Windows实体相对应,一些主要的接口类管理了难以掌握的Windows接口。这些接口包括:窗口类、GDI类、对象连接和嵌入类(OLE)、文件类、对象I/O类、异常处理类、集合类等。
  MFC库中的类按层次关系划分可分为如下若干类:
  (1)根类:CObject
  (2)应用程序体系结构类
   · 应用程序和线程支持类
   · 命令相关类
   · 文档类
   · 视类(体系结构)
   · 框架窗口(体系结构)
   · 文档模板类
  (3)窗口、对话框和控件类
   · 框架窗口类(窗口)
   · 视类(窗口)
   · 对话框类
   · 控件类
   · 控件条类
  (4)绘图和打印类
   · 输出(设备相关)类
   · 绘图工具类
  (5)简单数据类型类
  (6)数组、列表和映射类
   · 数组类
   · 列表类
   · 映像类
  (7)文件和数据库类
   · 文件I/O类
   · DAO类
   · ODBC类
  (8)Internet和网络工作类
   · LSAPI类
   · Windows Socket类
   · Win32 Internet类
  (9)OLE类
   · OLE容器类
   · OLE服务器类
   · OLE拖放和数据传输类
   · OLE普通对话框类
   · OLE动画类
   · OLE控件类
   · 活动文档类
   · 其他文档类
  (10)调试和异常类
   · 调试支持类
   · 异常类
  下面简单介绍一下MFC 中一些主要的类和某些子层次结构。

  9.2.2 根类

  CObject类是MFC的抽象基类,是MFC中多数类和用户自定义子类的根类,它为程序员提供了许多编程所需的公共操作。这些操作包括:对象的建立和删除、串行化支持、对象诊断输出、运行时信息以及集合类的兼容等。
  串行化是对象本身往返于存储介质的一个存储过程。串行化的结果是使数据"固定"在存储介质上。CObject类定义两个在串行化操作中起重要作用的成员函数:Serialize和IsSerializable。程序可以调用一个由CObject派生的对象的IsSerializable函数来确定该对象是否支持串行化操作。建立一个支持串行化的类的步骤之一是重载继承自CObject类的Serialize函数,并提供串行化数据成员的派生类的专用代码。
  CObject的派生类同时还支持运行时类型信息。运行时的类型信息机制就允许程序检索对象的类名及其他信息。CObject提供两个成员函数来支持运行时类型信息:IsKindOf和GetRuntimeClass。函数IsKindOf指示一个对象是否属于规定的类或者是从规定的类中派生出来的。CRuntimeClass类对象中包含了一个类的运行时信息,包括这个类的类名、基类名等信息。通过它就可以很容易获得一个指定类的运行时刻信息。

  9.2.3 应用程序体系结构类

  该类用于构造应用程序框架的结构,它能提供多数应用程序公用的功能。编写程序的任务是填充框架,添加应用程序专用的功能。应用程序体系结构类主要有与命令相关的类、窗口应用程序类、文档/视类和线程基类等。
  1.命令相关类:CCmdTarget类
  该类是CObject的子类,它是MFC库中所有具有消息映射属性的基类。消息映射规定了当一对象接收到消息命令时,应调用哪一个函数对该消息进行处理。程序员很少需要从CCmdTarget 类中派生出新类如窗口类(CWnd)、应用程序类(CWinApp)、文档模板类(CDocTemplate)、文档类(CDocument)、视类(CView)及框架窗口类(CFrameWnd)等。
  2.窗口应用程序类:CWinApp类
  每个应用程有且只有一个应用程序对象,在运行程序中该对象与其它对象相互协调,该对象从CWinApp类中派生出来。CWinApp类封装了初始化、运行、终止应用程序的代码。
  3.文档/视类
  文档对象由文档模板对象创建,管理应用程序的数据。视对象表示一个窗口的客户区,显示文档数据并允许用户与之交互。这些模板及基类有:
  · CDocTemplate:文档模板基类。文档模板是协调文档、视和框架窗口的创建
  · CSingleDocTemplate:单文档界面(SDI)的文档模板
  · CMultiDocTemplate:多文档界面(MDI)的文档模板
  · CDocument:应用程序专用文档的基类
  · CView:显示文档数据的应用程序专有视的基类
  4.线程基类:CWinThread类
  所有线程的基类,可直接使用。CWinApp类就是从CWinThread类中派生出来的。

  9.2.4 可视对象类

  1.窗口类:CWnd类
   该类提供了MFC中所有窗口类的基本功能。它是CCmdTarget类的子类,创建Windows窗口要分两步进行:首先引入构造函数,构造一个CWnd对象,然后调用Create建立Windows窗口并将它连到CWnd对象上。MFC中还从CWnd类派生出了进一步的窗口类型以完成更具体的窗口创建工作,这些派生类有:
  · CFrameWnd:框架窗口类,SDI应用程序主框架窗口的基类
  · CMIDFrameWnd:多文档框架窗口类,MDI应用程序主框架窗口的基类
  · CMDIChildWnd:多文档框架窗口类,MDI应用程序文档框架窗口的基类
  2.视类:CView类
  该类表示框架窗口的客户区和显示文档数据并接收输入的客户区,其派生类主要有如下几种:
  · CScrollView:具有滚动功能的视的基类
  · CFormView:其布局在对话资源中定义的滚动视
  · CEditView:具有文本编辑、查找、替换和滚动功能的视
  3.菜单类:CMenu类
  该类是CObject类的子类,用于管理菜单。它是一个Windows HMenu的封装,提供了与窗口有关的菜单资源建立、修改、跟踪及删除的成员函数。
  4.对话框类:CDialog类
  由于对话框是一个特殊的窗口,所以该类是从CWnd类中派生出来的。对话框子层次结构包括通用对话框类CDialog以及支持文件选择、颜色选择、字体选择、打印、替换文本的公共对话框子类。这些子类包括:
  · CFileDialog:提供打开或保存一个文件的标准对话框
  · CColorDialog:提供选择一种颜色的标准对话框
  · CFontDialog:提供选择一种字体的标准对话框
  · CPrintDialog:提供打印一个文件的标准对话框
  · CFindReplaceDialog:提供一次查找并替换操作的标准对话框
  · CDialog:该类可用于建立模式对话框和无模式对话框模型,是该子层次结构的根
  5.控件类
  控件子层次结构包括若干类,使用这些类可建立静态文本、命令按钮、位图按钮、列表框、组合框、滚动条、编辑框等。这些直观控件为Windows应用程序提供了各种输入和显示界面。主要的控件类如下:
  · CStatic:静态文本控件窗口。常用于标注、分隔对话框或窗口中的其它控件
  · CButton:按钮控件窗口。该类为对话框或窗口中的按钮、检查框或单选按钮提供一个总的接口
  · CEdit:编辑控件窗口。编辑控件用于接收用户的文字输入
  · CRichEditCtrl:多信息编辑控件。除了编辑控件的功能外,还支持字符和图形格式,以及OLE对象
  · CScrollBar:滚动条控件窗口。该类提供控件条的功能,用做对话框或窗口中的一个控件,用户可通过它在某一范围内定位
  · CProgressCtrl:进度指示控件窗口。用于指示一个操作的进度
  · CSliderCtrl:游标控件窗口。包括一个可移动的游标,用户可移动游标选择一个值或一个范围
  · CListBox:列表框控件窗口。列表框用于显示一个组列表项,用户可以进行观察和选择
  · CComboBox:组合框控件窗口。组合框由一个编辑控件加一个列表框组成
  · CBitmapButton:带有位图而非文字标题的按钮
  · CSpinButtonCtrl:带有一个双向箭头按钮,单击某个箭头按钮增大或减小值
  · CAnimateCrtl:动画显示控件窗口,显示一个简单的video图象
  · CToolTipCtrl:一个小的弹出式窗口,显示一行文本,描述应用程序中一个工具的作用
  · CHotKeyCtrl:热键控件窗口,使用户可以创建一个"热键",快速地执行某项操作
  6.控件条类:CControlBar类
  控件条子层次结构为工具条、状态条、对话条和分割窗口建立模型。该类是CToolBar、CStatusBar、CDialogBar的基类,负责管理工具条、状态条、对话条的一些成员函数。控件条指的是连接在主窗口框架的顶部或底部的小窗口,它据有如下基类:
  · CStatusBar:状态条控件窗口的基类
  · CToolbgar:包含非基于HWND的位图式命令按钮的工具条控件窗口
  · CDialogBar:控件条形式的非模式对话框
  7.绘画对象类:CGdiObject类
  图形绘画对象子层次结构以CGidObject类为根类,可用于建立绘画对象模型,如画笔、刷子、字体、位图、调色板等。这些子类有:
  · CBitmap:封装一个GDI位图,提供一个操作位图的接口
  · CBrush:封装一个GDI画刷,可被选择为设备描述表的当前画刷
  · CFront:封装一种GDI字体,可被选择为设备描述表的当前字体
  · CPalette:封装一个GDI调色板,用作应用程序和一彩色输出设备如显示器之间的接口
  · CPen:封装一种GDI画笔,可被选择为设备描述表的当前画笔
  · CRgn:封装一GDI域,用于操作窗口内的椭圆域或多边形域 。该类与CDC类的裁剪成员函数一起使用
  8.设备描述表类:CDC类
  该类及其子类支持设备描述表对象,是CObject类的子类。CDC类是一个较大的类,包括许多成员函数,如映射函数、绘画工具函数、区域函数等,通过CDC对象的成员函数可以完成所有的绘画工作,它具有如下的子类:
  · CPaintDC:显示描述表,用于窗口的OnPaint成员函数和视的OnDraw成员函数中,自动调用BeginPaint进行构造,调用EndPaint进行析构
  · CClientDC:窗口客户的显示描述表。例如,用于在快速响应鼠标事件时进行绘画
  · CWindowDC:整个窗口的显示描述表,包括客户区和框架区
  · CMetaFileDC:Windows元文件的设备描述表。Windows元文件包含一个图形设备接口(GDI)命令序列,该序列可被重新执行而创建一幅图象。对CMetaFileDC的成员函数的调用记录在一个元文件中

  9.2.5 通用类

  此分类中的类提供了许多通用服务,例如文件I/O、诊断和异常处理等,此外还包括如数组和列表等存放数据集的类。
   1.文件类:CFile类和CArchive类
   如果想编写自己的输入/输出处理函数,可以使用CFile类和CArchive类,一般不必再从这些类中派生新类。如果使用程序框架,则只需提供关于文档如何将其内容串行化的详细信息,File菜单上的Open和Save命令的缺省实现将会处理文件I/O(使用类CArchive),如下是部分文件类:
  · CFile类:提供访问二进制磁盘文件的总接口
  · CMemFile类:提供访问驻内存文件的总接口
  · CStdioFile类:提供访问缓存磁盘文件的总接口,通常采用文本方式
  · CArchive类:与CFile对象一起通过串行化实现对象的永久存储
  2.异常类:CException类
  该类是所有异常情况的基类。不能直接建立CException对象,程序员只能建立派生类的对象。可以使用派生类来捕获指定的异常情况,CException的派生类如下。
  · CArchiveException类:归档异常
  · CFileException类:有关文件的异常
  · CMemoryException类:内存不够异常
  · CNotSupportedException类:使用未支持特征产生的异常
  · CResourceException类:装载Windows资源失败产生的异常
  · CUseException类:用于停止用户启动的操作异常
  3.模板收集类
  这些类可以将多种对象存放到数组、列表和"映射"中。但这些收集类是模板,它们的参数确定了存放在集合中的对象类型。CArray、CMap和CList类使用全局帮助函数,帮助函数通常必须定制。类型指针类是类库中其它类的包装类,利用这些包装类,应用程序可借助于编译器的类型检查以避免出错,下列是一部分模板收集类:。
  · CArray类:将元素存储在数组中
  · CMap类:将键映射到值
  · CList类:将元素存储在一链表中
  · CTypedPtrList类:将对象指针存储在一链表中类型
  · CTypedPtrArray类:将对象指针存储在一数组中的类型
  · CTypedPtrMap类:将链映射到值的类型,键和值都为指针

  9.2.6 OLE类

  对象连接与嵌入(OLE)子层次结构为支持OLE提供了9个类,这9个类分为三大类:普通类、客户类和服务器类。其中COleDocuemnt、COleItem、COleException为支持OLE的普通类,COleClientDoc、COleClientItem为支持OLE的客户类,COleServer、COleTemplate、COleServerDoc、COleServerItem为支持OLE的服务类。这些类提供了支持OLE的所有功能。

  9.2.7 ODBC数据库类

  开放数据库连接子层次结构提供了一些类来支持ODBC特征,即通过这些类可开发数据库应用程序来访问多个数据库文件。该层次结构中主要包括的类有:
  · CDataBase:封装对一数据源的连接,通过此连接应用程序可在该数据源上进行操作
  · CRecordset:封装从一数据源选出的一组记录
  · CRecordView:提供直接连接一记录集对象的格式视
  · CFieldExchange:提供上下文信息,支持记录字段交换,即在字段数据成员、记录对象的参数数据成员及数据源上的对应列表之间进行数据交换
  · CLongBinary:封装一存储句柄,用于存储二进制大对象,例如位图等
  · CDBException:对数据存取处理过程中的失败产生的异常

  9.3 MFC中全局函数与全局变量

  在MFC中提供的所有函数及成员变量中,以Afx开头的函数除数据库类函数和DDX(Dialog Data Exchange)函数外,在目前的版本中,都表示是一个全局函数。而以Afx为前缀的变量,都是全局变量。这些函数与变量可以在任何地方、在任何MFC应用程序中调用。  
函数名 功能简介
AfxAbort 无条件终止一个应用程序
AfxBeginThread 创建一个新线程并执行它
AfxEndThread 终止当前正在执行的线程
AfxFormatString 格式化字符串
AfxMessageBox 显示一个Windows消息框
AfxGetApp 返回当前应用程序对象的指针
AfxGetInstanceHandle 返回标识当前应用程序对象的句柄
AfxRegisterWndClass 登记用于创建Windows窗口的窗口类

  9.4 应用程序向导及其应用步骤
    
            图示一
    
           图示二
  应用程序向导为程序员提供了一个基于MFC的应用程序框架,程序员可以在此基础上添加实现特定功能的代码即可
    
           图示三
    
           图示四
    
           图示五
    
           图示六
    
           图示七
    
           图示八
    
           图示九
    
           图示十
    
           图示十一
    
           图示十二
    
           图示十三
    
           图示十四
    
           图示十五
    
           图示十六
    
          图示十七
    
           图示十八
    
           图示十九
    
          图示二十