第12章综合程序设计•在设计C++程序时,可以先基于DOS平台快速地设计出构成程序核心代码的各个类,然后再将这些类移植到利用VC++向导建立的应用程序框架中,用这些类扩展框架程序的功能,就能够设计出Windows应用程序。•本章将把前面几章建立的comFinal、Account、Chemistry类移植到Windows环境中,构造一个Windows系统中的学生成绩管理程序•本章的目的是介绍将DOS平台的类移植到Windows程序中的方法。12.1在应用程序框架中包含并修改自定义类1、comFinal程序回顾–从第4章到第7章,每章最后一节的编程实作都在不断地扩展学生成绩管理程序的功能,并在第7章设计出了基于DOS平台的应用程序com_main.dsw–到目前为止,已经设计出了学生档案管理程序中完善的类comFinal、Account、Chemistry。–其中comFinal是基类,实现了公共课English、Chinese、Math的管理功能,而Account、Chemistry类则继承了comFinal类的功能,分别用于管理会计学和化学两个专业的课程。类的继承结构如图12-1所示。ComFinal的继承结构classcomFinal{charname[20];intEnglish,Chinese,Math,Total;floataverage;public:comFinal(char*n,intEng,intChi,intMat);comFinal(){};~comFinal(){};char*getName()intgetEng();intgetChi()intgetMat();intgetTotal();floatgetAverage()voidshow();};classAccount:publiccomFinal{intAccoun;intEcon;intmajTotal;floatmajAve;public:Account();Account(){};intgetMajtotal()floatgetMajave()intgetAccountintgetEcon()voidshow()classChemistry:publiccomFinal{intChemistr;intAnaly;intmajTotal;floatmajAve;public:Chemistry(){};intgetMajtotal()floatgetMajave()intgetChe()intgetAnl()voidshowC();voidshow();};12.1在应用程序框架中包含并修改自定义类•已经完成了的工作–到目前为止,在控制台下已经设计出各个Class,为了便于代码重用,将每个类的定义放在一个.H头文件中,实现代码放在一个.Cpp文件中.各类的源文件名称如下:–comFinl.h–comFinl.cpp–Accout.h–Account.cpp–Chemistry.h–Chemistry.cpp12.1在应用程序框架中包含并修改自定义类•程序移植任务–将基于控制台已经设计完善的这3个类:comFinal、Account、Chemistry移植到Windows程序中,并为它设计菜单、鼠标点击事件,数据输入对话框,并实现文档序列化功能。12.1在应用程序框架中包含并修改自定义类【例12-1】用VC++向导建立一个应用程序框架,然后将第7章建立的comFinal、Account、Chemistry三个类的上述6个文件添加到应用程序框架中。•过程如下移植控制台的comfinl到MFC1.建立应用程序框架(1)启动VC++6.0,选择“文件”菜单的“新建”命令。(2)通过弹出的新建对话框建立一个“MFCAppWizard(exe)”单文档项目文件,假设将该项目文件保存在目录C:\dk中,项目文件名是comMFC。–向导将在目录C:\dk下生成一个comMFC目录,并在其中产生与项目相关的文件,包括项目文件comMFC.dsw及与应用程序类、框架窗口类、文档类、视图类相关的以下头文件和源程序文件:–comMFC.h/comMFC.cpp应用程序类的头文件和源文件–MainFrm.h/MainFrm.cpp框架窗口类的头文件和源文件–comMFCView.h/comMFCView.cpp视图类的头文件和源文件–comMFCDoc.h/comMFCDoc.cpp文档类的头文件和源文件2.将自定义类添加到应用程序框架中(1)将第7章建立的:comFinl.h,comFinl.cpp,Accout.h,Account.cpp,Chemistry.h,Chemistry.cpp文件复制到comMFC项目文件的目录C:\dk\comMFC中。(2)通过VC++的“工程”菜单将这6个文件添加到应用程序框架中。方法是:–选择VC++的菜单命令“工程|添加工程|Files…”,然后在弹出的文件选择对话框中,将6个文件全部添加到应用程序框架的工程项目中。3.修改自定义类•将在DOS程序中设计的C++类移植到Windows程序中后,以下两个问题需要修改–首先,数据输入/输出问题。DOS系统采用字符方式输入/输出数据,而Windows系统采用图形方式输入/输出数据,因此那些在DOS系统中用于输入或输出数据的类成员函数在Windows程序中就不能再用了,可将这类成员函数删除或注释掉。本例不作修改。–需要在每个类的源程序文件中增加对stdafx.h文件的包含,因为stdafx.h文件中预定义了Windows程序需要用到的一些全局性数据、变量及函数。3.修改自定义类•现在来看看在自定义类的源程序中不包含stdafx.h头文件会产生的问题。(1)编译comMFC,将会见到如下3个错误信息:–fatalerrorC1010:unexpectedendoffilewhilelookingforprecompiledheaderdirectiveChemistry.cpp–这些错误指出在编译Chemistry.cpp、comFinl.cpp等源文件时,没有找到需要的预编译头文件stdafx.h,应该在comFinl.cpp、Account.cpp和Chemistry.cpp中包含stdafx.h头文件。2)在自定义类的源文件中增加对stdafx.h头文件的包含在comFinal.cpp文件中增加stdafx.h头文件包含/*comFinal.cpp*/#includestdafx.h//不包含该头文件将产生编译错误#includecomFinl.h……在Chemistry.cpp文件中增加stdafx.h头文件包含/*Chemistry.cpp*/#includestdafx.h//不包含该头文件将产生编译错误#includeChemistry.h……在account.cpp文件中增加stdafx.h头文件包含/*account.cpp*/#includestdafx.h//不包含该头文件将产生编译错误#includeaccount.h“(3)编译程序,这次不会有任何错误,运行它将见到MFC默认的框架程序界面12.2在事件函数中操作类对象•应用程序框架中的每个类就像一个容器,可以在其中包含其他类的对象,即可用其他类定义它的对象成员。•如在例12-1建立的框架程序中,可以在应用程序类comMFC、框架窗口类MainFrm、视图类comMFCView及文档类comMFCDoc中定义comFinal、Account和Chemistry类的对象,并通过框架类的事件函数调用自定义类的成员函数,实现需要的程序功能。12.2在事件函数中操作类对象【例12-2】扩展例12-1的程序功能,左键单击奇数次时产生一个会计学类Account的对象,单击偶数次时产生一个化学类Chemistry的对象,并在鼠标单击位置生成一个椭圆,将产生的学生对象的数据显示在该椭圆中。程序设计思路:在视图类comMFCView中实现程序功能。将鼠标单击时生成的Account和Chemistry对象分别保存在不同数组中,并以鼠标单击位置为中心建立一个矩形,然后产生WM_PAINT消息,调用视图类的OnPaint成员函数在屏幕上以数组中保存的矩形为边框画内切椭圆,在椭圆中输出所建类对象的数据成员。12.2在事件函数中操作类对象程序实现方法:在comMFCView类中定义3个数组che、acc、m_rectBubble,che用于保存Chemistry类的对象,acc用于保存Account类的对象,m_rectBubble用于保存建立的矩形。然后利用VC++向导为comMFCView添加鼠标左键单击的消息响应函数OnLButtonDown和WM_PAINT消息响应函数OnPaint,并在该函数中输出che、acc、m_rectBubble这3个数组中的对象。12.2在事件函数中操作自定义类对象实现过程如下:(1)在comMFCView.h头文件中包含Account和Chemistry类的头文件。/*comMFCView.h*/#includeChemistry.h//增加Chemistry类的头文件包含#includeAccount.h//增加Account类头文件包含classCComMFCView:publicCView{……}红字为添加的程序代码(2)在comMFCView类的声明中定义Account和Chemistry类的对象数组che、acc及其他数据成员,增加的代码如下粗体字所示。classCComMFCView:publicCView{……protected:#defineMAX_BUBBLE250//类对象的最多个数CRectm_rectBubble[1000];//保存鼠标位置的矩形intm_nBubbleCount;//矩形个数的计数器char*name;//代表Account或Chemistry的名字ints1,s2,s3,s4,s5;//代表5科目成绩的变量Chemistryche[MAX_BUBBLE];//保存Chemistry对象的数组Accountacc[MAX_BUBBLE];//保存Account对象的数组……};红字为添加的程序代码12.2在事件函数中操作自定义类对象(3)在CComMFCView类的构造函数中初始化矩形计数器m_nBubbleCount。CComMFCView::CComMFCView(){m_nBubbleCount=0;}红字为添加的程序代码(4)利用VC++的类向导为CComMFCView类添加鼠标左键单击事件的消息响应函数,并修改其中代码voidCComMFCView::OnLButtonDown(UINTnFlags,CPointpoint){if(m_nBubbleCount1000){//下面3行语句以鼠标光标位置为中心,60为半径建立一个矩形对象,并//将它/保存在矩形数组m_rectBubble中intr=60;CRectrect(point.x-r,point.y-r,point.x+r,point.y+r);m_rectBubble[m_nBubbleCount]=rect;//s1…s5分别代表学生的这5科成绩,产生50~100之间的随机数代表成绩s1=rand()%50+50;s2=rand()%50+50;s3=rand()%50+50;s4=rand()%50+50;s5=rand()%50+50;if(m_nBubbleCount%2){//偶数次单击鼠标时建立一个Chemistry类对象name=化学系;che[m_nBubbleCount]=Chemistry(name,s1,s2,s3,s4,s5);}else{//奇数次单击鼠标时建立一个Account类对象name=会计系;acc[m_nBubbleCount]=Account(name,s1,s2,s3,s4,s5);}m_nBubbleCount++;//对象计