面向对象是一种重要的程序设计方法,采用这一思想的C++是当今世界上应用最广泛的编程语言。Windows平台下的C++编程工具首推Microsoft的Visual C++。但是,编写Windows应用程序只熟悉C++的语法还是远远不够的,还必须掌握MFC(Microsoft Foundation Class,微软基础类库)。面向对象的编程是当前程序设计中的热门话题,这里将介绍使用Visual C++进行面向对象编程时所用到的一些关键概念,这些概念是进一步学习和应用Visual C++的基础。
面向对象的程序设计的最根本目的就是使程序员更好地理解和管理庞大而复杂的程序。为此,面向对象的程序设计围绕真实世界的概念来组织模型,它采用对象来描述问题空间实体。一般认为,对象是包含现实世界物体特征的抽象实体,它反映了系统为之保存信息和与它交互的能力,是一些属性和服务的封装体。在程序设计领域,可以用“对象=数据+作用于这些数据上的操作”这一公式来表达。对于面向对象的程序设计,一个对象具有“状态”、“行为”和“标识”。 对象的状态包括它的属性和这些属性的当前值。 对象的行为包括可以进行的操作以及伴随着的状态的变化。 对象的标识用来区别于其他对象。1.面向对象面向对象的核心概念就是通常所说的“抽象”、“封装”、“继承”和“多态”。(1)抽象抽象就是忽略一个主题中与当前目标无关的那些方面,以便将注意力更充分地放在与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分。抽象包括两个方面,一是过程抽象,二是数据抽象。过程抽象是指任何一个明确定义功能的操作都可被使用者简单地看做单个实体,该操作可能由一系列更低级的操作来完成。数据抽象定义了数据类型以及施加于该类型对象上的操作,并限定对象的值只能通过使用这些操作来查看和修改。(2)封装封装是面向对象的特征之一,是对象和类概念的主要特性。所谓封装是指隐藏类(class)为支持和实施抽象所做的内部工作的过程,把过程和数据包围起来,对数据的访问只能通过已定义的接口。类的接口是公有的,它定义了一个类所能完成的功能,而这些接口的实现是私有的或受保护的,它定义了类完成这些功能所做的具体操作。对于使用这些类的编程者来说,只需要知道类所能完成的功能,而不需要知道这些功能具体是如何实现的。封装保证了模块具有较好的独立性,使得程序维护修改较为容易。对应用程序的修改仅限于类的内部,因而可以将因应用程序修改带来的影响减小到最低限度。(3)继承对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类或者子类,而原始类称为新类的基类或者父类。派生类可以从它的基类那里继承方法和实例变量,并且它可以修改或增加新的方法使之更适合于特殊的需要。继承性很好地解决了软件的可重用性问题。比如,所有的Windows应用程序都有一个窗口,它们可以看做都是从一个窗口类派生出来的。但是有的应用程序用于文字处理,有的应用程序却用于绘图,这就是因为基类派生出了不同的子类,各个子类增加了各自不同的特性。下面,举一个使用VC编程的例子。考虑MFC中的CView类,它封装了Windows中的自定义视窗控件。如图2-1所示为CView类的继承结构。在图中,类CObject是所有的MFC类的根类,其功能有:串行化支持,运行库信息,对象诊断输出以及与集合类的兼容等。类CCmdTarget从类CObject直接派生,它是Microsoft基础类库的消息映射结构的基类,消息映射将命令和消息传递给所编写的处理成员函数。这里,命令指来自菜单项、命令按钮和加速键的信息。类CWnd提供了MFC中所有窗口类的基本功能,它封装了Windows中的窗口句柄hWnd。类CView从CWnd直接派生,它提供用户自定义视窗的能力,用于用户和应用程序间的信息交互。事实上,类CView本身仅提供了特定于编辑控件的32个成员函数,但是,用户可以通过类CView进行调用的成员函数却多达300多个。这300多个成员函数中的绝大部分由其基类提供,其中CWnd就为CView提供了多达304个成员函数。由于CView类继承了其他基类的数据和方法,因此,可以通过CView类调用CWnd类中提供的方法来实现对标准Windows窗口的操作。(4)多态性多态性是面向对象程序设计的重要特性之一。它与前面讲过的封装性和继承性构成了面向对象程序设计的三大特性。这三大特性是相互关联的。封装性是基础,继承性是关键,多态性是补充,并且多态性必须存在于继承的环境中。多态性是指允许不同类的对象对同一消息做出响应,发出同样的消息被不同类型的对象接收时导致完全不同的行为特性。这里所说的消息主要是指对类的成员函数的调用,而不同行为是指不同的实现。比如同样的加法,把两个时间加在一起和把两个整数加在一起是完全不同的。多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好地解决了应用程序中不同类间函数同名的问题。用户只需发送一般形式的消息,而将所有的实现交给接收消息的对象。对象根据接收到的消息进行相应的操作。2.类定义类是Visual C++中面向对象编程的一个具体实现方式。它集中体现了面向对象编程的各种特性。类的定义格式分为说明部分和实现部分。说明部分用来说明该类的成员,包括数据成员说明和成员函数说明。成员函数是用来对数据成员进行操作的。实现部分是对成员函数的定义。概括说来,说明部分将告诉用户“做什么”,而实现部分告诉用户“怎么做”。类的一般定义格式如代码2-1所示。代码2-1 类的定义格式
Class <类名> { private: <私有数据成员或成员函数的说明(默认为私有)> protected: <保护数据成员或成员函数的说明> public: <公共数据成员或成员函数的说明> }; <各个成员函数的实现>其中: public表示类的公有部分,是全局透明的。它的数据成员和成员函数是开放的,既可以由本类的成员函数访问,也可以由程序的其他部分直接访问。 private表示类的私有部分,是完全隐藏的。它只能由本类的成员函数访问,而不允许程序的其他部分直接访问。 protected表示类的保护部分,介于以上两者之间,是半透明的。它可以由本类的成员函数和派生类的成员函数直接访问。保护部分主要用于类的继承性。3.对象定义Class定义的是“类”类型,具有“类”类型的变量称为类的实例变量,即对象。因此,定义对象之前,一定要先定义好该对象的类。对象的声明和基本类型的声明一样。(1)对象定义对象定义的格式如下:<类名> <对象名表>其中,<类名>是特定对象所属的类的名字,即所定义的对象是属于该“类”类型的对象。<对象名表>中可以有一个或多个对象名,定义多个对象名时用逗号分隔。<对象名表>中可以是一般的对象名,也可以是指向对象的指针名,还可以是对象数组名。(2)对象成员的表示方法一个对象的成员就是该对象的类所定义的成员。对象成员有数据成员和成员函数,其表示方法如下:<对象名>.<成员名>或<对象指针名>-><成员名>4.构造函数和析构函数构造函数和析构函数是在类体中说明的两种特殊的成员函数。构造函数用于初始化类变量或者分配内存空间。构造函数的定义方法和其他成员函数相同,但是构造函数用类名作函数名,它不能指定返回类型和显示返回值。每当该类的对象被创建时,编译器都将自动调用构造函数初始化创建的对象。一个类可以有很多个构造函数,当然,这些构造函数的形参各不相同。析构函数与构造函数的功能正好相反,当对象要撤销时,系统将自动调用析构函数来清理对象所占的内存。
一个完整的Windows应用程序首先必须有用户界面、窗体、各种对话框、按钮、菜单等,开发者可以通过调用Windows的API函数来实现这一切。但是API采用的是C的标准,用它编写程序,很多C++的特性,比如继承、封装等就无从发挥。Microsoft也提供了C++库,它位于任何Windows API之上,能够使开发者更加高效和轻松地工作,它就是MFC。1.MFC的特点MFC是VC软件的一部分。MFC库中的所有类形成了建立应用程序的框架,利用这些类可以充分支持Windows应用程序的开发。MFC最主要的优势是它的效率高。MFC具有以下特点: MFC完整地封装了Windows的API函数,包括消息、控件、窗口函数、菜单、对话框、图形设备接口(GDI)、对象链接以及多文档界面(MDI)等。 MFC大大减少了在编写Windows程序时必须编写的代码。同时,MFC具有良好的通用性和可移植性,提供了所有C++编程的优点。 MFC借助Application Wizard使开发者摆脱了那些每次都必写的基本代码,借助Class Wizard和消息映射使开发者摆脱了定义消息处理时那种混乱和冗长的代码段。 MFC利用C++的封装功能使开发者摆脱了Windows中各种句柄的困扰,只需要面对C++中的对象。这样,使开发者更接近编程语言而远离系统。2.MFC的层次MFC是很庞大的,包含了大约200个不同的类。开发者利用它们可以完成各种标准的Windows编程任务。在设计思想上,MFC将面向对象方法和事件驱动结合得非常好。但在一般的应用程序中,不需要使用所有的类。事实上,开发者可能只需要使用十多个MFC中的类就可以建立一个非常漂亮的程序。下面着重介绍一下MFC中最常用的几种类。(1)文档类文档类用来构建应用程序的框架,它的根是CCmdTarget类。它为客户定义的文档提供了大量的操作,比如:Open、Close、Save等。文档类主要应用于文档数据的存储、调出以及修改。文档类包括CDocument、CDocItem、CDocTemplate,还有一些它们的子类,它使用户能对文档数据进行查询、编辑和修改。(2)视图类视图类由CView以及它的子类组成。CView类继承自CWnd。CView类是可以在窗口中创建的子窗口,它可以提供一个特殊的接收外来输入的结构窗口。CView类包含了常见的一些可视化编辑控件,如CScrollView、CCtrlView、CEditView、CTreeView、CListView。CView类广泛地应用于基于文档的应用程序中,它的许多操作都是和文档相关的,比如拖动滚动条时,实际上是看到文档或图像对应的部分在滚动。一个视图只能分配给一个文档,但是一个文档可以拥有多个视图。(3)框架窗口类框架窗口类为开发者提供创建应用窗体的方法,可以建立单文档(SDI)与多文档(MDI)两种窗体。SDI是单文档界面(Single Document Interface),就是同一时间只能打开一个文档;MDI则是多文档界面(Multiple Document Interface)。MFC为它们准备了CFrameWnd、CMDIFrameWnd、CMDIChildWnd等几个类。开发基于文档的应用程序时,框架窗口通过这些类来实现。(4)对话框类它主要用于创建及操作各种各样的模态和非模态对话框,包含了通用对话框类CDialog以及支持类,包括选择颜色、选择字体、打印、查找/替换等通用对话框。CDialog类也继承自CWnd类。(5)控件类控件类包括常见的Windows控件,这些控件包括静态文本、命令按钮、位图按钮、列表框、组合框、编辑控件等。(6)绘图类及绘图对象类Windows中所有图形化的输出都是绘制在被称为设备环境(Device Context,DC)的区域内。绘图类以及绘图对象类包括设备环境类(CDC)及它的一些派生类,提供了诸如字体、颜色、画线、画圆、填充等绘图操作,绘图对象中所包含的类用于模型化绘图对象,如画笔、刷子、字体、位图和调色板等。(7)文件服务类该类提供了各种用于处理文件的类。常用的文件服务类是CFile类及其派生类,它们控制普通文件的I/O操作,比如读/写文件、重命名及删除等。(8)其他类MFC还有异常处理、特殊结构(List、Array和Map)、网络服务(WinSock)、对象链接和嵌入(OLE)、数据库(ODBC、DAO)等一些专用类。为了建立一个MFC应用程序,开发者应该学会直接使用这些类,而且通常需要从这些类中继承新的类。在继承的类中,开发者可以建立新的成员函数,以适应开发的需要。
1.几种文件类型在VC中,应用程序是以Project(工程)的形式存在的,工程文件以dsp为扩展名。扩展名为dsw的文件称为Workspace(工作空间)文件。在Workspace文件中可包含多个Project,由Workspace文件对它们进行统一协调和管理。在应用程序中,大量应用的是以h和cpp为扩展名的文件。其中以h为扩展名的文件被称为头文件,主要包含的是类的定义。以cpp为扩展名的文件被称为实现文件,主要包含的是类成员函数的实现代码。在应用程序中经常要使用一些位图、菜单之类的资源,VC中以rc为扩展名的文件被称为资源文件,里面就包含了应用程序中要用的所有的Windows资源。2.应用程序框架Windows程序设计是一种完全不同于传统的DOS方式的程序设计方法,它是一种事件驱动方式的程序设计方式。在程序提供给用户的界面中有许多可操作的可视对象。用户从所有可能的操作中任意选择,被选择的操作会产生某些特定的事件,这些事件发生后的结果是向程序中的某些对象发消息,然后这些对象调用相应的消息处理函数来完成特定的操作。Windows应用程序的最大特点就是程序没有固定的流程,只是针对某个事件的处理有特定的子流程,Windows应用程序就是由许多这样的子流程构成的。从上面的讨论中可以看出,Windows应用程序在本质上是面向对象的。程序提供给用户界面的可视对象在程序的内部一般也是一个对象,用户对可视对象的操作通过事件驱动模式触发相应对象的可用方法。程序的运行过程就是用户的外部操作不断产生事件,这些事件又被相应的对象处理。Windows程序工作原理如图2-2所示。
我们所要建立的MFC应用程序毫无疑问是Windows操作系统环境下的应用程序,但是MFC应用程序又有自己的特点。因为MFC为应用程序做了大量的工作,而且MFC也为应用程序建立了大量的类,MFC应用程序框架,如图2-3所示。如图2-3所示为使用MFC方式的应用程序的4个主要类之间的关系。1)CMYAPP类:主要的作用是用来处理消息,它统一管理程序收到的所有消息,然后把消息分配到相应的对象。2)CMAINFRAME类:是CMYVIEW的父类,使各种视窗VIEW显示在主框窗MAINFRAME的客户区中。3)CMYVIEW类:作用是显示数据,数据的来源是类CMYDOC。在MFC程序中,程序的数据是放在文档当中的,而显示数据则是利用视窗方式。4)CMYDOC类:作用是管理数据,通过CMYVIEW类和用户进行交互并对所管理的数据进行操作。
使用过传统的Windows编程方法的人都知道,在应用程序中有一个重要的函数WINMAIN(),这个函数是应用程序的基础,用户的操作所产生的消息正是经过这个函数进行处理后,再派送到对应的对象中进行进一步处理的。然而,基于MFC开发的应用程序中,用来处理消息的是系统自动生成的MFC中的CWINAPP类的派生类CMYAPP,由这个类来完成WINMAIN()所完成的工作。CMYAPP执行窗口注册等标准服务,然后再调用应用程序对象中的成员函数来初始化和运行应用程序。在MFC应用程序设计中,我们所要做的工作主要就是设计自己需要的类,编写并处理相关的消息和事件,并将其添加到应用程序中去。3.文档、视图和框架文档/视图结构是Visual C++中使用MFC开发基于文档的应用程序的基本框架。在这个框架中,数据的维护及其显示,分别由两个不同但又彼此紧密相关的类——文档类和视图类来负责,而框架窗口则是视窗的包容器。框架的核心是文档和视图。一个文档是一个数据对象,用户编辑过程中与这个数据对象进行交互。数据是由File菜单中的New或Open命令创建的,一般都保存在一个文件中。一个视图是一个窗口对象,用户通过这个窗口对象与一个文档进行交互。在文档/视图结构中,文档的任务是对数据进行管理和维护,数据被保存在文档类的成员变量中。文档通过一个被称为串行化(serialize)的过程将数据保存到磁盘文件或数据库中。MFC类库为数据的串行化提供了默认的支持,只需要在此基础上稍加修改,就可以为自定义的文档类提供串行化支持。文档类还可以处理命令消息。这里所谓的命令消息是指来自如菜单、工具栏按钮和加速键的WM_COMMAND通知消息。除了WM_COMMAND外,文档不能处理其他的Windows消息。视图类在文档和用户之间起中介作用。视图可以直接或间接地访问文档类中的这些成员变量,它从文档类中(而不是从存储介质中)将文档中的数据取出来,然后在屏幕上显示文档的数据。同时,它可以接收用户的输入,并接收用户的修改,通过调用文档和视图的接口将修改的信息反馈给文档类。实际的数据更新仍然是由文档来完成的。每一个文档可以有多个视图类的成员函数,但每个视图只能对应于一个确定的文档。也就是说,视图是文档的不同表现形式。可见,文档/视图模式总的工作方式是:视图把文档中的数据以特定的方式显示于计算机屏幕上,用户通过与视图的交互来查看数据并对数据进行修改。然后,视图通过相关联的文档类的成员函数将经过修改的数据传递给文档对象。文档对象获得修改过的数据之后,对其进行必要的修改,最后保存到永久介质(如磁盘)中。文档/视图模型的一个重要机制是文档、视图及框架的关联性,三者互相协调,互相包含指向对方的指针。这种关联是通过一种叫做文档模板的类来完成的。程序开始运行时,将调用CMYAPP类InitInstance成员函数来完成程序的一系列初始化工作,其中有一段程序如代码2-2所示。代码2-2 框架程序的初始化
CsingleDocTemplate *pDocTemplate; pDocTemplate=new CSingleDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS (CMySDIDoc), RUNTIME_CLASS (CMainFrame), RUNTIME_CLASS (CMySDIView)); AddDocTemplate(pDocTemplate);CSingleDocTemplate类即单文档模板类,它首先定义了一个单文档模板类的指针,然后动态创建一个单文档模板类的实例,该实例中将特定的文档类(CMySDIDoc)、视图类(CMySDIView)和框架类(CMainFrame)绑定在一起,最后调用AddDocTemplate函数,将这个模板实例添加到应用程序的文档模板列表中。
Visual C++首先是一种程序设计语言,同时也是一个集成开发工具,它提供了自动生成软件代码和可视化资源编辑的功能。Visual C++是Windows环境下最主要的面向对象应用开发环境之一,使用Visual C++可以灵活地开发从底层软件到上层直接面向用户的软件。“只有想不到,没有做不到”是程序员对VC的评价,而VC也因此成为了专业程序员的首选编程工具。在开始Visual C++程序设计之前,首先对开发平台即Visual C++6.0的集成开发环境(IDE)有一个了解。在Developer Studio启动之后,就会看到一个窗口。该窗口中每个区域都有其特定的用途,如图2-4所示。
1.工作区(Workspace)当首次启动Visual C++时,在Developer Studio的左侧有一块区域,占去一大块面积,却没有显示什么内容,这就是工作区。通过它可以用以下3种不同的方法来查看应用程序的各个部分。 Class View(类视图):用户可以通过它在C++类的层次上找到并操作源代码,它提供了应用程序中所有类的整体结构框图,例如可以找到某一个类,定位到定义该类的位置,修改它的成员和方法。 Resource View(资源视图):用户可以通过它在应用程序中找到并编辑各种资源,包括对话框、图标和菜单的设计等。 File View(文件视图):用户可以通过它查看构成应用程序的各个文件并确定它们的位置,进行代码编写工作。2.输出窗格(Output Pane)输出窗格是Developer Studio向用户提供信息的地方,这些信息包括编译程序的进展说明、警告及出错信息。3.编辑区(Editor Area)编辑区位于Developer Studio的右边区域。它是Visual C++中进行一切编辑工作的区域,当编辑C++的源代码时将在这里显示代码编辑窗;当设计对话框时,窗口绘制器也在此显示。另外,当设计应用程序使用图标时,编辑区又将显示图标绘制器。编辑区基本上就是Developer Studio的全部区域,不能被窗格、菜单或工具栏所占据。4.菜单栏(Menu Bar)菜单栏是Windows应用程序必不可少的要素之一,它由File、Edit、View、Insert、Project、Build和Tools等组成,每个菜单又由多个选项构成。1)File菜单:选项中最主要的是【New】选项。选中【New】选项将打开【New】对话框,如图2-5所示。
利用【Files】选项卡可以实现各种类型普通文件的创建。各种类型普通文件的用途如表2-1所示。
【Projects】选项卡可以创造各种类型的Visual C++工程文件。而各种类型工程文件的用途如表2-2所示。
【Workspaces】选项卡可以创建新的工作区。2)Edit菜单:通过Edit菜单可以对已经创建的工程中的有关文件进行编辑加工。3)View菜单:View菜单中的命令主要用来改变窗口和工具栏的显示方式、检测源代码、激活调试时所用的各个窗口,它主要由【Class Wizard】、【Resource Includes】、【Workspace】、【Output】、【Debug Windows】等一系列选项组成。【Class Wizard】是编写MFC应用程序的专用工具,其中常用的是【Message Maps】和【Member Variables】选项卡。 【Message Maps】选项卡:把消息映射到与窗口、对话框、控件、菜单选项和快捷键有关的处理函数,创建或删除消息处理函数,查看已经拥有的消息处理函数的消息并跳转到相应的处理代码中去。 【Member Variable】选项卡:用于增加或删除变量,或增加新的类收集并验证输入到表单视图(Form View)中的数据,其中Control IDs是映射到成员变量的控件的ID值,Type是成员变量的类型,Member是成员变量名。系统默认将所有资源符号保存在resource.h文件中。也可以在【Resource Includes】选项中的【Symbol Header file】文本框中自定义新的资源符号存储文件。【Workspace】选项:用来显示工作区窗口;【Output】选项:用来显示输出区窗口;【Debug Windows】选项:用来调试程序。4)Insert菜单:为工程添加新的类(Class)、窗体(Form)和资源(Resource)等内容。5)Project菜单:创建、修改和保存正在编辑的工程文件。6)Build菜单:编译、建立和执行应用程序。7)Tools菜单:简单快速地访问多个不同的开发工具。8)Windows菜单:对用户可见窗口的格式进行设置,在各个窗口之间进行切换。9)Help菜单:向用户提供各种帮助选项。
通过前述内容,我们已经掌握了使用VC开发程序的基本过程。下面,将举一个利用VC生成多文档应用程序的实例。这里将用到VC提供的一个强大工具AppWizard。【例2-1】 简单的多文档应用程序本例题通过讲解如何生成简单的多文档应用程序,让读者对Visual C++的集成开发环境有一个直观的认识,并了解Visual C++生成多文档应用程序的编程方法,为后续实例讲解打基础。 设计步骤[1] 选择【File】【New】菜单命令,打开【New】对话框;选择MFC AppWizard(exe)工程类型,在【Project Name】域键入工程名称Demo1,在【Location】域键入工程文件存放位置,其他选项为默认值,如图2-6所示。
[2] 单击按钮进入【MFC AppWizard-Step 1】对话框,工程类型选择Multiple documents,其他选项为默认值,如图2-7所示。
[3] 单击按钮进入【MFC AppWizard-Step 2 of 6】对话框,这里需要决定在应用程序中是否需要数据库支持。这里选择None选项,如图2-8所示。
[4] 单击按钮进入【MFC AppWizard-Step 3 of 6】对话框,这里需要决定在应用程序中是否需要OLE支持。添加的OLE支持越多,应用程序就越大。最基本的OLE支持层次是用做容器(Container)。容器既可以作为客户,又可以存储链接对象和嵌入对象。这里选择None选项,其他项为默认值,如图2-9所示。
[5] 单击按钮进入【MFC AppWizard-Step 4 of 6】对话框,这里上半部分需要选择应用程序中要包含的界面元素类型,采用默认设置即可。下半部分可以设置应用程序文件列表中列出的最近使用文件的数目,如图2-10所示。
[6] 图2-10中有一个按钮,单击这个按钮,显示如图2-11所示的对话框。可设置应用程序默认打开并操作文件的类型。这里设置为以bmp为文件扩展名的位图文件。
[7] 单击按钮,进入【MFC AppWizard-Step 5 of 6】对话框,这里需要选择应用程序中界面风格,选择“MFC Standard”;是否在源文件中自动生成注释代码,选择“Yes,please”;应用MFC类库的方式,选择“As a shared DLL”,如图2-12所示。
[8] 单击按钮进入【MFC AppWizard-Step 6 of 6】对话框,可以指定应用程序中自动生成的文档、视图、框架类的基类。这里选择默认设置,如图2-13所示。
[9] 单击按钮完成应用程序工程文件的建立。应用程序开始运行时,调用CDemo1App类InitInstance成员函数来完成程序的一系列初始化工作,其中,有如下代码:CMultiDocTemplate* pDocTemplate;pDocTemplate = new CMultiDocTemplate(
IDR_DEMO1TYPE, RUNTIME_CLASS(CDemo1Doc), RUNTIME_CLASS(CChildFrame), RUNTIME_CLASS(CDemo1View));AddDocTemplate(pDocTemplate);CMultiDocTemplate类是多文档模板类,它动态创建一个多文档模板类实例,该实例将有关文档、视图及框架关联在一起。最后调用AddDocTemplate函数,将这个模板实例添加的程序的文档模板列表中。VC中运行该应用程序的结果如图2-14所示。