《最新MFC课程设计实验报告.docx》由会员分享,可在线阅读,更多相关《最新MFC课程设计实验报告.docx(159页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、Four short words sum up what has lifted most successful individuals above the crowd: a little bit more.-author-dateMFC课程设计实验报告MFC课程设计实验报告面向对象可视化对象编程课程设计总结报告班级: 学号: 姓名: 2016.12.12-2016.12.23目录一、课程设计的目的3二、课程设计的内容与设计思路31.课设内容32.设计思路4三、程序实现过程与细节51.涉及的主要函数列表52.工程的新建73.建立图元属性对话框74.控件的关联95.枚举型106.定义动态数组117
2、.建立Shape类及其子类128OnDraw()159. 鼠标左键消息响应函数1610.鼠标右键双击消息响应函数1711颜色按钮1812获取鼠标点击处的逻辑坐标1913.对话框中控件的显示与隐藏1914.文档的存取20四、运行效果211.编译运行,按下Ctrl+鼠标左键212.选择文本,弹出角度框213.创建正方形、圆形、文本224.创建三角形和椭圆225.单击鼠标左键修改正方形和文本属性236.右键双击删除三角形237.保存退出24五、设计小结24六、主要代码清单251Shape.h252.Shape.cpp293.LwhView.cpp44一、课程设计的目的1. 参加本课程设计的同学已经学
3、习了C语言程序设计和面向对象可视化编程两门课程,现在需要通过一个相对实际性的开发过程来巩固与鉴定一下学习成效,可以查看离实际需要还有哪些部分没有完全掌握,需要加强检测;2. 本课程设计可以提供一个稍微具有规模的程序开发的例子,让同学们可以体会到程序的构思、编码以及调试的完整过程,最后并总结课程设计的过程;3.通过本次课程设计,可以对自身做一个评估,看看在哪方面不足从而加强学习;二、课程设计的内容与设计思路1.课设内容要求:采用单文档方式,文档中存储图形画面的各个图元数据,视图负责图形的绘制。文档支持图形的序列化(连载),提供新建、打开、保存等操作。视图除了绘制图形,还提供图形交互,能够按住Ct
4、rl键再鼠标左键单击来创建图元,鼠标左键双击编辑修改图元属性,鼠标右键双击删除图元。图元创建与修改时的参数由参数对话框来编辑。创建时以鼠标左击时光标的所在位置作为基点来创建图元。2.设计思路我们的最终目的是显示一个单文档窗口,且可利用从对话框中输入的数据绘制图形。所以,首先建立一个单文档程序,再添加对话框,用来创建与修改图形参数,之后给对话框中的各复选框,编辑框,按钮添加消息响应函数,进行控件关联,并利用枚举型使参数传递。定义一个动态数组以存储从对话框中获取的数据,之后添加Shape类,用来绘图,由Shape类定义一个指针指向动态数组,便可从中读出之前存储的数据进行绘图,从而达到目的,思路图参
5、考如图1,2:图1.Shape的六个派生类图2.工程思路图解三、程序实现过程与细节1.涉及的主要函数列表附表1函数定义与功能一览表序号函数名函数定义定义所在文件名函数功能1OnInitDialog()BOOL CType:OnInitDialog()Type.cpp对对话框进行初始化处理2OnOk()void CType:OnOK()Type.cpp按确定按钮时调用3OnFillColorButton()void CType:OnFillColorButton()Type.cpp按下按钮,弹出颜色选择对话框4OnLinelColorButton()void CType:OnLineColorB
6、utton()Type.cpp按下按钮,弹出颜色选择对话框5OnDraw()void CLwhView:OnDraw(CDC* pDC)LwhView.cpp应用程序窗口的客户区进行绘图6OnLButtonDown()void CLwhView:OnLButtonDown(UINT nFlags, CPoint point)LwhView.cpp按下鼠标左键,执行该函数7OnRButtonDblClk()void CLwhView:OnRButtonDblClk(UINT nFlags, CPoint point)LwhView.cpp双击鼠标右键时,执行该函数8OnSelchangeComB
7、oxTuYuanType()void CType:OnSelchangeComBoxTuYuanType()LwhView.cpp选择图元属性组合框时,显示或隐藏某个编辑框9Serialize()void CSquare:Serialize(CArchive &ar)void CRectangle:Serialize(CArchive &ar)void CTriangle:Serialize(CArchive &ar)void CCircle:Serialize(CArchive &ar)void CEllipse:Serialize(CArchive &ar)void CText:Seria
8、lize(CArchive &ar)Shape.cpp将表单内容序列化10CSquare()CSquare:CSquare()Shape.cpp缺省构造函数,初始化11CSquare()CRectangle()CCircle()CEllipse()CTriangle()Ctext()CSquare:CSquare()CRectangle:CRectangle()CCircle:CCircle()CEllipse:CEllipse()CTriangle:CTriangle()CText:CText()Shape.cpp接受由对话框传递过来的参数12Draw(CDC*pDC)void CSquar
9、e:Draw(CDC*pDC)void CRectangle:Draw(CDC*pDC)void CCircle:Draw(CDC*pDC)void CEllipse:Draw(CDC*pDC)void CTriangle:Draw(CDC*pDC)void CText:Draw(CDC*pDC)Shape.cpp绘制函数13IsMatched(CPoint pnt)bool CSquare:IsMatched(CPoint pnt)bool CRectangle:IsMatched(CPoint pnt)bool CCircle:IsMatched(CPoint pnt)bool CElli
10、pse:IsMatched(CPoint pnt)bool CTriangle:IsMatched(CPoint pnt)bool CText:IsMatched(CPoint pnt)Shape.cpp图元匹配函数图3.主要函数OnLButtonDown()2.工程的新建打开Microsoft Visual C+ 6.0 点击File New 在Projects中选择 MFC AppWizard (exe) ; 在 Project name中输入工程的名字Lwh,在 Location中选择工程存放的路径。填完后点击OK按钮。填完后点击OK按钮,在弹出来的对话框中我们选择Single docu
11、ment,再点击Finish,完成工程的创建。之后编译运行,结果参见图3。图4.新建工程结果示意图3.建立图元属性对话框点击ResouceView,右击Dialog插入Dialog,这时会弹出来一个对话框,双击“确定”按钮,选择“Create a new class”,点击OK,设置类名为CTypeOK,之后设置对话框属性为IDD_TYType,参见图4,绘制对话框,参见附表2.属性表给各复选框、编辑框、按钮修改属性。附表2属性表序号名称ID7角度IDC_Angle1图元类型IDC_m_ComBox_TuYuanType8线型IDC_m_ComBoxLineType2线色按钮IDC_LineC
12、olorButton9线色(R/G/B)IDC_LineColor(R/G/B)3填充色按钮IDC_FillColorButton10填充色(R/G/B)IDC_FillColor(R/G/B)4高度IDC_High11原点XIDC_OrgX5宽度IDC_Width12原点YIDC_OrgY6线宽IDC_LineWidth13填充风格IDC_m_ComBoxFillType图5.构造对话框结果示意图4.控件的关联要实现这个步骤,首先要明白在MFC中变量的声明定义,对于控件关联型的数值变量,value类型(double,int,CString等等),在生成时向导帮你做了3件事:1)在.h文件中进
13、行声明;2)在.cpp中的构造函数中,进行了初始化;3)在.cpp文件中的DoDataExchange()中进行控件关联;DDX_Text(pDX, IDOK, m_btnTest);所以,要进行控件关联,要做的也是这三件事(可在ClassWizard中进行添加,则系统自动生成。下面介绍手动添加,以图元类型IDC_m_ComBox_TuYuanType为例)1) 在Type.h中声明:protected:CComboBox m_ComBox_TuYuanType;2)在Type.cpp中进行初始化:BOOL CType:OnInitDialog() (在ClassWizard中添加)CDial
14、og:OnInitDialog();/ TODO: Add extra initialization herem_ComBox_TuYuanType.AddString(正方形);m_ComBox_TuYuanType.AddString(矩形);m_ComBox_TuYuanType.AddString(三角形);m_ComBox_TuYuanType.AddString(圆);m_ComBox_TuYuanType.AddString(椭圆);m_ComBox_TuYuanType.AddString(文本);m_ComBox_TuYuanType.SetCurSel(0);3)在Type
15、.cpp中进行控件关联(DoDataExchange()中):DDX_Control(pDX, IDC_ComBox_TuYuanType, m_ComBox_TuYuanType);5.枚举型枚举类型定义的一般形式为:enum 枚举名枚举值表 。在枚举值表中应罗列出所有可用值。这些值也称为枚举元素。注意枚举值是常量,不是变量,不能再对它赋值。 枚举元素本身由系统定义了一个表示序号的数值,从0开始顺序定义为0,1,21)定义(Type.h)public:EnumTuYuanTyp m_TuYuanTyp;2)枚举(Type.h)enum EnumTuYuanTyp EnumTuYuanTyp_
16、Square,/正方形 EnumTuYuanTyp_Rectangle,/矩形 EnumTuYuanTyp_Triangle,/三角形 EnumTuYuanTyp_Circle,/圆 EnumTuYuanTyp_Ellipse,/椭圆 EnumTuYuanTyp_Text/文本;3) 利用枚举型传参(Type.cpp)void CType:OnOK() UpdateData();/ TODO: Add extra validation hereint iSel=m_ComBox_TuYuanType.GetCurSel();/得到当前选择的索引值 switch(iSel)case 0:m_Tu
17、YuanTyp=EnumTuYuanTyp_Square; break;case 1: m_TuYuanTyp=EnumTuYuanTyp_Rectangle; break;case 2: m_TuYuanTyp=EnumTuYuanTyp_Triangle;break;case 3: m_TuYuanTyp=EnumTuYuanTyp_Circle;break;case 4:m_TuYuanTyp=EnumTuYuanTyp_Ellipse;break;case 5:m_TuYuanTyp=EnumTuYuanTyp_Text;break;default:ASSERT(0);CDialog:
18、OnOK();6.定义动态数组1)定义(LwhDoc.h)public:CObArray m_Elements;2)清除(LwhDoc.cpp)/清除图元地址,释放空间CLwhDoc:CLwhDoc()for(int i=0;im_Elements.GetSize();i+)delete m_Elementsi;m_Elementsi=NULL;m_Elements.RemoveAll();7.建立Shape类及其子类一个类要支持支持序列化Serialize,必须从CObject派生,并且在类的声明(.h文件)中包含DECLARE_SERIAL申明,在类的实现(.cpp)中包含IMPLEMEN
19、T_SERIAL申明。所以,要建立支持序列化的Shape类,首先选择ClassView,鼠标右键单击工程名,选择New Class,在类的类型中选择Generic Class,输入类名CShape,并在下方Derived From中输入CObject,继承类型为public,点击确定,系统会生成相应的Shape.cpp文件和Shape.h文件。在Shape.h中定义其成员变量和成员函数,注意OnDraw函数应定义为纯虚函数(参见附表1.函数定义与功能一览表)。然后由Shape类派生其六个子类CSquare,CRectangle,CTriangle,CCircle,CEllipse,CText,
20、继承方式均为public,在子类中也定义其成员函数及变量(以CSquare为例)class CShape : public CObject public:CShape();virtual CShape();virtual void Draw(CDC*pDC)=0;/绘制图元virtual bool IsMatched(CPoint pnt)=0;/点是否落在图形内部virtual void Serialize(CArchive& ar) = 0;int OrgX;int OrgY;int width;int high;int linewidth; int R1,R2,G1,G2,B1,B2;c
21、lass CSquare:public CShapepublic:CSquare();CSquare(int x,int y,int w,int line,int r1,int g1,int b1,int r2,int b2,int g2);void Draw(CDC*pDC);/绘制bool IsMatched(CPoint pnt);/重载点pnt是否落在图元内virtual void Serialize(CArchive& ar );/序列化正方形图元private:DECLARE_SERIAL(CSquare)/声明类CSquare支持序列化;在Shape.cpp中对Shape类极其子
22、类进行序列化,并写入子类的成员函数,完成绘图和进行图元匹配功能(以CSquare为例)IMPLEMENT_SERIAL(CSquare, CObject, 1) /实现类CSquare的序列化,指定版本为1void CSquare:Serialize(CArchive &ar)if (ar.IsStoring()ar OrgX OrgY;/原点坐标ar width;ar OrgX OrgY;/原点坐标ar width;ar linewidth;/线宽CSquare:CSquare()/缺省构造函数,初始化OrgX = 400;/原点坐标OrgY = 400;linewidth= 1;/线宽wi
23、dth = 100;CSquare:CSquare(int x, int y, int w,int line,int r1,int g1,int b1,int r2,int b2,int g2)OrgX = x;/原点坐标OrgY = y; linewidth=line;width = w;R1=r1;R2=r2;G1=g1;G2=g2;B1=b1;B2=b2; void CSquare:Draw(CDC*pDC)/绘制函数CPen pen, *pOldPen;pen.CreatePen(PS_SOLID, linewidth,RGB(R1,G1,B1);pOldPen = (CPen*)pD
24、C-SelectObject(&pen);CBrush brush, *pOldBrush;brush.CreateHatchBrush(HS_DIAGCROSS, RGB(R2,G2,B2);pOldBrush = (CBrush*)pDC-SelectObject(&brush);pDC-Rectangle(OrgX - width / 2, OrgY -width / 2, OrgX + width / 2, OrgY + width / 2);pDC-SelectObject(pOldPen);pDC-SelectObject(pOldBrush);bool CSquare:IsMat
25、ched(CPoint pnt)/图元匹配函数if (OrgX-width/2 = pnt.x & pnt.x = OrgX + width/2) & (OrgY - width/2 = pnt.y & pnt.y m_Elements.GetSize() 0)for (int i=0; i m_Elements.GetSize(); i+)p = (CShape*)pDoc-m_Elementsi;p-Draw(pDC);/ TODO: add draw code for native data here9. 鼠标左键消息响应函数按下Ctrl+W组合键,在弹出的MFC ClassWizard
26、 对话框中选择Message Map,在Class name选择CLwhView类,在Object ID中选择CLwhView,在右边的Messages中为其添加鼠标左键的消息响应函数OnLButtonDown,双击OnLButtonDown函数(参见附表1.函数定义与功能一览表),出现OnLButtonDown()的定义模块,写入以下代码:CType dlg;if (nFlags&MK_CONTROL) = MK_CONTROL)/Ctrl键按下 dlg.DoModal();即可实现在单文档运行界面按下Ctrl+鼠标左键弹出对话框的操作,但是,要实现当弹出对话框按下OK键就可以画出图形的操作
27、,就得利用枚举型传过来的参数进行选择判断(switch语句),然后执行画图操作(以CSquare为例)if (dlg.DoModal() = IDOK) switch(dlg.m_TuYuanTyp) case EnumTuYuanTyp_Square: p = new CSquare(dlg.X,dlg.Y,dlg.Width,dlg.LineWidth, dlg.LineColorR,dlg.LineColorG,dlg.LineColorB, dlg.FillColorR,dlg.FillColorG,dlg.FillColorB); break; 当不按下Ctrl键,直接按左键,要进行
28、修改图元属性的功能,则也是在此处添加相应代码,对应之前的按下Ctrl键的if语句,写入else语句,添加重新绘图的功能代码即可。(具体见主要代码清单)10.鼠标右键双击消息响应函数与添加鼠标左键消息相应的方法一样(参见附表1.函数定义与功能一览表),先在ClassWizard中添加,双击进入定义模块,要实现右键双击删除,并弹出一个警告是否删除的对话框,首先得明白我们基于图元的数据存储在于动态数组m_Elements,所以,要删除图元,只需删除该图元对应数组中存储的数据即可,主要代码如下:for (int i=0;i m_Elements.GetSize(); i+)p = (CShape*)p
29、Doc-m_Elementsi;if (p-IsMatched(pntLogical)CCut cut;if(cut.DoModal()=IDOK) pDoc-m_Elements.RemoveAt(i); delete p; Invalidate(); 11颜色按钮 CColorDialog类实现了标准的颜色对话框,因此用创建CColorDialog类的对象去调用DoModal()函数,即可显示出对话框,如果DoModal()返回IDOK,则用GetColor()来获取颜色对话框中选择的颜色值 ,以下是线色按钮的相关代码:void CType:OnLineColorButton() / TO
30、DO: Add your control notification handler code here COLORREF color = RGB(47, 78, 107);/ 颜色对话框的初始颜色 CColorDialog colorDlg(color); / 构造颜色对话框,传入初始颜色值 if (IDOK = colorDlg.DoModal() color = colorDlg.GetColor();/ 获取颜色对话框中选择的颜色值 SetDlgItemInt(IDC_LineColorR, GetRValue(color); / 在线色编辑框中显示所选颜色的R分量值 SetDlgIte
31、mInt(IDC_LineColorG, GetGValue(color);/ 在线色编辑框中显示所选颜色的G分量值SetDlgItemInt(IDC_LineColorB, GetBValue(color);/ 在线色编辑框中显示所选颜色的B分量值 12获取鼠标点击处的逻辑坐标函数:Point();函数功能:该函数检取光标的位置,以屏幕坐标表示;函数原型:BOOL GetCursorPos(LPPOINT lpPoint);参数:IpPoint; (参见附表1.函数定义与功能一览表)POINT结构指针:接收光标的屏幕坐标;代码如下:CType:CType(CWnd* pParent /*=N
32、ULL*/): CDialog(CType:IDD, pParent)POINT point;GetCursorPos(&point);X = point.x; Y = point.y; 13.对话框中控件的显示与隐藏首先要清楚控件的显示与隐藏是基于对其他控件进行操作,在该工程中,要实现我在图元属性组合框中选择“文本”,则出现角度框,而选择其他则不出现角度框,所以,应对该组合框添加消息相应函数,在ClassWizard中,选中IDC_m_ComBox_TuYuanType(参见附表1.函数定义与功能一览表),选择Messages为CBN_CELCHANGE,双击进入定义模块,写入如下代码:vo
33、id CType:OnSelchangeComBoxTuYuanType() / TODO: Add your control notification handler code hereint iSel=m_ComBox_TuYuanType.GetCurSel();/得到当前选择的索引值 switch(iSel)case 0:case 1:case 2:case 3:case 4:GetDlgItem(IDC_STATIC1)-ShowWindow(SW_HIDE);/隐藏角度框GetDlgItem(IDC_Angle)-ShowWindow(SW_HIDE);break;case 5:G
34、etDlgItem(IDC_STATIC1)-ShowWindow(SW_SHOW);/显示角度框GetDlgItem(IDC_Angle)-ShowWindow(SW_SHOW);break;default:ASSERT(0);break;Invalidate();14.文档的存取文档的存储主要通过文档类重载成员函数Serialize来实现。void COovpExam1Doc:Serialize(CArchive& ar)m_Elements.Serialize(ar);/其中m_Elements是文档用来保存图元对象的数组四、运行效果1.编译运行,按下Ctrl+鼠标左键图6.按下Ctrl
35、+鼠标键结果示意图2.选择文本,弹出角度框图7.角度框的显示结果示意图3.创建正方形、圆形、文本图8.创建图形结果示意图14.创建三角形和椭圆图9.创建图形结果示意图5.单击鼠标左键修改正方形和文本属性图10.修改图形属性结果示意图6.右键双击删除三角形图11.弹出删除警告窗口结果示意图图12.删除三角形结果示意图7.保存退出五、设计小结1. 通过这次实验,进一步加深了我对类的运用,使我大概了解了构造函数和析构函数在程序中的应用,这次查找错处也使我更小心去注意程序的细节问题。2. 即使在MFC中,MFC虽然是VC+中的一个特色,对我来说还是有很多的地方并不了解。我对VC+缺乏整体上的认识,我只
36、是在程式化的执行它。比如说,在系统已给的类的搭建,类中成员函数的插入,已有类的功能等等诸多,我的了解尚为浅薄。3. 通过这次实验至少得到了认识和了解windows绘图的功能,比如: CDC类和CObject类以及其派生类的应用,还在实验中通过调用OnDraw函数绘制不同尺寸、颜色、风格的几个图形和图位。但是要想熟练掌握还需要大量的实践。4. 通过这次实验我掌握了动态数组的应用,动态数组相对于静态数组来说可以更加有效利用存储空间。而这也是我以前没有掌握的知识。5. 面向对象的操作要求思路清晰,过程严谨,就好似一个连环扣,缺一环而不可。这次实验中我深刻地了解到了编写程序的思路与实验过程,我很珍惜这
37、次经验。6. 最后,感谢那些给予我帮助的老师和同学们!大家辛苦了!六、主要代码清单1Shape.h/ Shape.h: interface for the CShape class./#include afx.h#include Type.h#include math.h#if !defined(AFX_SHAPE_H_9F3D8253_0729_4802_9938_EDAA421048A0_INCLUDED_)#define AFX_SHAPE_H_9F3D8253_0729_4802_9938_EDAA421048A0_INCLUDED_#if _MSC_VER 1000#pragma o
38、nce#endif / _MSC_VER 1000class CShape : public CObject public:CShape();virtual CShape();virtual void Draw(CDC*pDC)=0;/绘制图元virtual bool IsMatched(CPoint pnt)=0;/点是否落在图形内部virtual void Serialize(CArchive& ar) = 0;int OrgX;int OrgY;int width;int high;int linewidth; int R1,R2,G1,G2,B1,B2;class CSquare:pu
39、blic CShapepublic:CSquare();CSquare(int x,int y,int w,int line,int r1,int g1,int b1,int r2,int b2,int g2);void Draw(CDC*pDC);/绘制bool IsMatched(CPoint pnt);/重载点pnt是否落在图元内virtual void Serialize(CArchive& ar );/序列化正方形图元private:DECLARE_SERIAL(CSquare)/声明类CSquare支持序列化; class CRectangle:public CShapepubli
40、c:CRectangle();CRectangle(int x,int y,int w,int h,int line,int r1,int g1,int b1,int r2,int b2,int g2);void Draw(CDC*pDC);/绘制bool IsMatched(CPoint pnt);/重载点pnt是否落在图元内virtual void Serialize(CArchive& ar );/序列化正方形图元private:DECLARE_SERIAL(CRectangle)/声明类CRectangle支持序列化;class CTriangle:public CShapepubli
41、c:CTriangle();CTriangle(int x,int y,int w,int h,int line,int r1,int g1,int b1,int r2,int b2,int g2);void Draw(CDC*pDC);/绘制bool IsMatched(CPoint pnt);/重载点pnt是否落在图元内virtual void Serialize(CArchive& ar );/序列化正方形图private:DECLARE_SERIAL(CTriangle)/声明类CTriangle支持序列化;class CCircle:public CShapepublic:CCircle();CCircle(int x,int y,int w,int line,int r1,int g1,int b1,int r2,int b2,int g2);void Draw(CDC*pDC);/绘制bool IsMatched(CPoint pnt);/重载点pnt是否落在图元内virtual void Serialize(CArchive& ar );/序列化正方形图
限制150内