简单画图程序课程设计说明书.docx

上传人:b****6 文档编号:7918247 上传时间:2023-01-27 格式:DOCX 页数:30 大小:347.24KB
下载 相关 举报
简单画图程序课程设计说明书.docx_第1页
第1页 / 共30页
简单画图程序课程设计说明书.docx_第2页
第2页 / 共30页
简单画图程序课程设计说明书.docx_第3页
第3页 / 共30页
简单画图程序课程设计说明书.docx_第4页
第4页 / 共30页
简单画图程序课程设计说明书.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

简单画图程序课程设计说明书.docx

《简单画图程序课程设计说明书.docx》由会员分享,可在线阅读,更多相关《简单画图程序课程设计说明书.docx(30页珍藏版)》请在冰豆网上搜索。

简单画图程序课程设计说明书.docx

简单画图程序课程设计说明书

目录

1基本功能描述-1-

2设计思路-1-

3软件设计-3-

3.1设计步骤-3-

3.2界面设计-6-

3.3关键功能的实现-6-

4结论与心得体会-8-

5参考文献-10-

6思考题-10-

7附录-11-

7.1调试报告-11-

7.2测试结果-12-

7.3关键源代码-14-

简单画图程序

1基本功能描述

简单画图程序实现了常见图形的绘制、图形属性的设置和图形数据的暂存等功能。

该程序的具体功能模块包括以下几项:

(1)图形绘制模块。

该模块实现直线段、椭圆、矩形等图形的绘制功能。

(2)图形属性设置模块。

该模块实现绘图线条的线宽,线色,图形填充色等属性设置功能。

(3)图形数据暂存模块。

该模块实现直线段、椭圆、矩形等图形数据暂存功能,涉及图形的坐标、线宽、线色、填充色等数据。

2设计思路

根据基本功能描述,简易画图程序有3个功能模块组成,其中图形绘制模块在鼠标消息处理函数中编码实现。

鼠标左键按下响应OnLButtonDown()函数,确定绘图起始点,鼠标移动响应OnMouseMove()函数,利用橡皮筋技术实时显示绘制的图形,鼠标左键弹起响应OnLButtonUp()函数,保存图形相关参数到文档类中并绘制最终的图形。

图形相关数据的保存用到图元类,每当用户绘制完一个图形后,我们就可以实例化一个对应的图元子类对象,该对象实例就对应了用户所画的图形,图元的相关参数就保存在该图元类对象中,最后将图元类的指针存入文档类中定义的m_MapList列表类变量中。

数据暂存模块定义了图元基类CMapElement,直线段图元子类Cline,椭圆图元子类CEllipse,矩形椭圆子类CRectangle,其中CMapElement从CObject类公有继承,直线段图元子类CLine、椭圆图元子类CEllipse、矩形图元子类CRectangle均从CMapElement公有派生,CMapList类从CObArray列表对象类继承,CMapList对象实例可用于保存指向CObject对象的指针。

创建以上图元类及CMapList类是为了在窗口大小改变或者窗口最大化时能够利用OnDraw()函数实现图元的重画。

图形属性设置模块比较简单,仅需在视图类中定义相关的变量,并在视图类的构造函数中初始化,然后在程序运行时动态改变其参数值即可。

视图类中定义了m_LineWidth、m_LineColor、m_FillColor等变量,控制绘图的线宽、线色、填充色等,其他变量在软件设计部分将会进行讲解,程序流程图如下图1所示。

图1程序流程图

3软件设计

3.1设计步骤

(1)利用应用程序向导生成一个基于单文档的应用程序,工程名称为YangRui。

(2)在CYangRuiView类中添加私有成员变量,添加的成员变量及其对应的ID列于下表1所示。

表1视图类中定义的变量

变量类型

变量名称

变量说明

CPoint

m_StartPoint

鼠标绘图开始点坐标

CPoint

m_EndPoint

鼠标绘图终止点坐标

int

m_DrawType

绘图类型

int

m_LineWidth

线宽

COLORREF

m_LineColor

线色

COLORREF

m_FillColor

填充色

BOOL

m_LButtonDown

鼠标左键是否按下标志

HCURSOR

m_Cursor

光标资源句柄

视图类中新增的这些变量和后面的程序相关,其初始化在试图类的构造函数中完成,初始化后,程序默认绘图类型为直线,线宽为一个像素,线色为黑色,填充色为白色,鼠标左键按下标志为FALSE,光标在客户区显示为十字光标。

(3)编辑IDR_MAINFRAME菜单栏,在菜单栏增加“绘图”菜单项,并删去编辑菜单项,绘图菜单项子菜单项标题(Caption)及对应ID号列于下表2中。

表2菜单项及其对应ID

菜单项标题

ID

菜单项标题

ID

直线

ID_LINE

1

ID_LINEWIDTH1

椭圆

ID_ELLIPSE

2

ID_LINEWIDTH2

矩形

ID_RECTANGLE

3

ID_LINEWIDTH3

线色

ID_LINECOLOR

4

ID_LINEWIDTH4

填充色

ID_FILLCOLOR

5

ID_LINEWIDTH5

利用类向导ClassWizard添加以上菜单项的COMMAND和UPDATE_COMMAND_UI消息处理函数,并编写相关源代码,具体代码参见附录。

(4)创建可浮动的工具栏,并将新建的工具栏的ID改为IDR_DRAW,在CMainFrame的protected处添加CToolm_DrawToolBar声明一个绘图工具条对象,然后在CMainFrame类的OnCreate()函数中添加相关代码,具体见附录所列代码。

工具栏按钮与菜单项相对应,并且将工具栏ID设为和菜单栏ID一致,这样就可以不用编写工具栏按钮的消息处理函数,减少编程量。

(5)添加鼠标消息处理函数OnLButtonDown()、OnMouseMove()、OnLButtonUp(),利用橡皮筋技术实时显示绘制图形,并绘制最终图形,具体源代码参看附录。

添加过程为:

选择View菜单下的ClassWizard菜单项打开类向导,在类列表中选择CYangRuiView类,在消息列表框中选择WM_LBUTTONDOWN消息并用鼠标左键双击,此时类向导自动在成员函数列表框中添加该消息的处理函数。

用同样方法添加WM_MOUSEMOVE消息和WM_LBUTTONUP消息的处理函数,如图2所示。

图2添加鼠标消息处理函数

(6)图元类定义及重画,创建图元基类CMapElement,直线段图元子类CLine,椭圆图元子类CEllipse,矩形图元子类CRectangle,其中CMapElement从CObject公有继承,CLine类、CEllipse类、CRectangle类从CMapElement公有继承,另外创建类CMapList从列表对象类CObArray公有继承,用于保存指向CObject对象的指针。

创建类的过程为:

在类面板树形列表的根节点“YangRuiClass”上右击,在弹出的快捷菜单中选择“NewClass…”,将会出现如图3所示“NewClass”对话框,按照图3填好相关参数,单击OK按钮即可创建CMapElement类,其他类的创建同理。

图3CMapElement类的创建

所有的类创建完成后类视图如图4所示。

图4类面板视图

3.2界面设计

该程序为单文档程序,未用到相关控件,故界面比较简单,仅添加了菜单栏和工具栏,其中线宽菜单为弹出式菜单,自己创建的工具栏按钮ID与相应菜单项ID对应,故不用再编写工具栏的消息处理函数。

程序运行时显示菜单栏和工具栏状态如下图5所示,图中为画矩形,线宽为3个象素时菜单栏和工具栏(可浮动)状态。

图5菜单栏及工具栏状态显示

图中直线、椭圆、矩形菜单项通过打钩显示其选中状态,线宽1、2、3、4、5通过打点显示其选中状态。

3.3关键功能的实现

1)选择要绘制图形的种类

在CYangRuiView视图类中定义int类型的变量m_DrawType,该变量等于1、2、3时分别表示绘制直线段、椭圆、矩形等图形。

在直线、椭圆、矩形菜单项的消息处理函数中分别赋值相应变量,即选中了相应的图形种类。

起初在CYangRuiView的构造函数中将m_DrawType赋值为1,表示程序默认选择的绘图类型为直线段。

2)选择线宽、线色、填充色

在CYangRuiView视图类中定义m_LineWidth、m_LineColor、m_FillColor分别表示线宽、线色、填充色,并在CYangRuiView视图类的构造函数中分别将这些变量初始化,初始化后线宽为1个象素,线色为黑色,填充色为白色。

在程序运行时改变这些变量的值,然后创建相应的画笔、画刷,并选入设备环境DC,即可绘制相应属性要求的图形。

3)橡皮筋技术实现鼠标实时绘图

利用橡皮筋技术可以实现在鼠标拖拽作图时,实时显示当前绘图的情况。

这样,我们就要在鼠标移动的消息处理函数中添加相应的代码。

在鼠标左键按下的时候,记录下图元起始点;在鼠标移动的时候,获取鼠标当前位置,绘制出新的图形,同时,将上一次绘制的图形擦除,这就是橡皮筋技术。

在OnMouseMove()函数中调用SetROP2()函数将绘图模式设置为NOTXORPEN(同或)模式,使用同或模式绘图就可以画上真实的图形,并擦除上次绘制的图形。

在OnLButtonDown()函数中调用SetCapture()函数捕捉鼠标,OnLButtonUp()函数中调用ReleaseCapture()函数释放鼠标。

整个绘图过程就是在鼠标左键按下时确定绘图起点,移动鼠标实时显示绘制的图形,鼠标左键弹起即完成图形的绘制的过程。

4)图元定义及重画

在该简单画图程序中提供了三种可供绘制的图形:

直线段、椭圆、矩形。

这样我们就可以定义三个类分别与之对应,即直线段类、椭圆类、矩形类,每一个图元(用户绘制的图形)都是其对应的类的实例。

同时,不同类型的图元之间又有相同的部分,比如图元控制点坐标、线宽、线色、填充色等。

所以我们可以定义一个图元类,作为具体的图形类的基类。

在其父类中定义图元共有的成员变量和成员函数,而在每个子类中定义具有自己特色的成员变量和成员函数。

图元类的继承体系如下图6所示。

图6图元类继承体系

图6中CMapElement为图元基类,CLine、CEllipse、CRectangle为相应图元子类,

图6中继承方式都为公有继承。

CMapElement定义了图元子类共有的成员变量和成员函数,需要说明的是其中成员函数draw用于完成图元的绘制。

该函数定义为虚函数,即由图元的子类来完成具体的实现,也就是说由每个图元子类自己来决定如何进行绘制。

再创建CMapList类,CMapList类从CObArray列表对象类公有继承,CMapList对象实例可用于保存指向CObject对象的指针。

这样的继承体系结构可以实现通过指向基类的指针实现在运行时的多态性。

在绘制完图元时,实例化对应的图元子类,并设置相关图形参数,然后调用draw函数绘制图元,之后将图元子类的指针存入m_MapList列表中,最后在OnDraw函数中添加相应代码将m_MapList图元列表中的每个图元一一绘制出来即可完成图元的重画。

上述相关类的具体代码参见附录。

定义图元类是为了在程序窗口最大化、最小化或者窗口大小发生改变时窗口中绘制的图形不会丢失,实现图元的重画。

其实现机制是在窗口发生变化时,系统发送WM_PAINT消息,自动调用OnDraw函数,实现窗口的刷新。

4结论与心得体会

这次课程设计我成功的完成了任务书的技术要求,能用鼠标拖动绘制直线段、椭圆、矩形等基本图形;能控制所绘制图形的线宽、线色、填充色等。

经过程序调试,该简单画图程序能够绘制指定线宽、线色、填充色的图形,并且在窗口大小发生变化时图形不丢失,实现窗口客户区的刷新重画。

记得第一次学习C语言的时候我就对程序设计充满兴趣,尤其是图形界面的设计,曾经在学完C语言的时就试图参考他人的方法编写一个贪吃蛇的程序,但是由于是在TC中开发,而且其中图形函数操作比较复杂,后来就不了了之了。

但是在初步学完MFC程序设计后,我就觉得图形界面设计不再是一个难题,而且对图形设计比较感兴趣,所以我就选择了简单画图程序作为我的课设题目。

拿到任务书后,我就开始查阅资料,构思总体的设计方案,然后开始具体的代码编写,由于菜单栏、工具栏之前学过,所以此部分没有太大的问题,很轻易的就完成了,然后就是改变线宽、线色、填充色等图形属性参数,这三个属性设置通过三个相关的变量来进行控制,线宽通过菜单项消息处理函数实现,线色和填充色通过调用CColorDialog通用颜色对话框实现,这一部分也没有太多的问题。

这次课设的主要任务,也就是画图部分,正是我收获最大的地方,通过查阅资料,不断编程调试,最终实现绘图程序的要求。

我学会了鼠标消息的分类,鼠标消息处理函数的常见编程方法,以及捕捉鼠标SetCapture()函数,释放鼠标ReleaseCapture()函数。

同时,利用橡皮筋技术实现鼠标拖拽绘图的实时显示也是我最大的收获之一。

本以为完成以上程序设计就可以完成画图程序的要求,但是我在自己调试时发现,只要窗口发生变化,所绘制的图形就会消失,这让我烦恼不已。

后来仔细分析原因,是由于绘图部分的代码并没有放在OnDraw()函数中,导致窗口发生变化时所绘制的图形不能够重绘于窗口之上。

为了解决这个问题,我查阅了很多资料,比如说双缓存技术、图元定义及重画等,由于双缓存技术比较难理解,后来在权衡之后,我还是选择图元定义及重画来实现窗口大小改变时的刷新重绘问题。

正是图元类定义,让我充分体会到面向对象的程序设计(OOP)的强大,通过类的继承实现运行时的多态,其代码重用机制相对于传统的C语言面向过程的程序设计来说具有非常大的优越性。

我在调试程序时,发现绘制直线时鼠标左键弹起直线并没有绘制结束,而再次单击鼠标左键,又以上次绘制的直线段终点作为起点绘制直线,即绘制出的直线段是一段连着一段的。

起初我怀疑是编程算法的问题,后来仔细检查,发现在OnLButtonUp()函数中漏了一条m_LButtonDown=FALSE;鼠标左键弹起的语句,所以导致绘制直线时遇到上述问题。

一条语句竟能产生如此不同的运行结果,这不得不让我再次体会到程序编写需要严谨,不容一丝马虎,多了或者少了一条语句,最终程序的运行结果就迥然不同。

总的来说,这是一次很有意义的课程设计。

通过这次课程设计,我学到了很多与计算机绘图相关的基础知识,并进一步体会到面向对象的程序设计的强大,以及Windows应用程序用户界面统一、友好,独立于设备的图形操作特点。

这次课设,带给我的不仅是理论知识的升华,更是编程能力的又一次历练。

这次课设,让我学会了使用MSDN查阅相关MFC类函数的用法,以及在网上查阅资料,并能发现其中的存在的一些问题并改正过来,然后用到自己的程序中。

这次课设,进一步激发了我对编程的兴趣,在以后,我会通过编程来解决自己在学习和生活中遇到的问题,将学到的知识更好的用于实践当中。

5参考文献

[1]张海林,杜忠友,姜玉波.VisualC++简明教程.北京:

电子工业出版社,2007

[2]刘春辉,徐建飞.VisualC++程序设计学习笔记.北京:

电子工业出版社,2008

[3]揣锦华.面向对象程序设计与VC++实践.西安:

西安电子科技大学出版社,2005

[4]黄维通.VisualC++面向对象与可视化程序设计(第2版).清华大学出版社,2003

6思考题

1)说明直线、椭圆、矩形绘制使用的函数,及其参数含义?

答:

画直线需要LineTo()和MoveTo()两个函数配合使用。

LineTo()函数以当前位置所在的点为直线的起点,另指定一个点为直线的终点,画出一段直线。

MoveTo()函数只是将当前位置移到指定位置点,其函数说明为BOOLCDC:

:

MoveTo(intX,intY),其中(intX,intY)为指定点坐标。

LineTo()函数原型为BOOLCDC:

:

LineTo(intnXEnd,intnYEnd),其中(nXEnd,nYEnd)为直线的终点位置。

画椭圆使用函数为Ellipse(),椭圆由其外接矩形确定,其函数原型为BOOLCDC:

:

Ellipse(intnLeftRect,intnTopRect,intnRightRect,intnBottomRect),其中参数nLeftRect和nTopRect为外接矩形左上角坐标,而nRightRect和nBottomRect为外接矩形的右下角坐标。

画矩形函数为Rectangle(),其原型为BOOLCDC:

:

Rectangle(intnLeftRect,intnTopRect,intnRightRect,intnBottomRect),其中参数nLeftRect和nTopRect为矩形左上角坐标,而nRightRect和nBottomRect为矩形的右下角坐标。

2)如何控制菜单项的状态,使用的消息类型?

答:

给相应的菜单项ID添加UPDATE_COMMAND_UI消息的响应函数并添加相关代码即可改变菜单项的状态,通过调用CCmdUI类的成员函数实现。

CCmdUI常用的方法有voidSetCheck(intnCheck=1)和voidSetRadio(BOOLbOn=TRUE),其中前者设置菜单项的check状态,显示标志为“√”,后者与SetCheck功能类似,但显示标志为“•”。

控制菜单项使用的消息类型为UPDATE_COMMAND_UI,具体的控制代码可参见附录。

3)如何设置菜单和工具栏按钮的快捷键操作?

答:

切换到资源视图,选择Accelerator资源类型,双击IDR_MAINFRAME加速键资源,打开加速键编辑窗口。

在ID下拉列表框中选择相应菜单项的ID,在Key一栏中输入相应键值(比如L),选择Ctrl复选框和VirtKey单选按钮,关闭加速键编辑窗口,即可完成加速键设置,如图7所示。

图7快捷键设置

7附录

7.1调试报告

在代码编写的过程中,我一般是编写完一个函数或者功能模块就编译连接一次,看看有没有错误提示,如果有,则充分利用错误提示,并使用注释符注释掉相关问题语句,然后改正错误代码或增添相关代码,直至编译连接通过,最后编写下一个函数模块。

这样编写一部分,调试通过一部分,继续编写,可以防止一次编写完代码后编译错误太多,不便于查错,从而浪费太多的时间。

我在调试的过程中遇到的主要问题及相应的解决办法如下:

1)程序编译连接通过,也能运行,但是在绘制直线时鼠标左键弹起直线并没有绘制结束,而再次单击鼠标左键,又以上次绘制的直线段终点作为起点绘制直线,即绘制出的直线段是一段连着一段的。

起初我怀疑是编程算法的问题,后来仔细检查,发现在OnLButtonUp()函数中漏了一条m_LButtonDown=FALSE;鼠标左键弹起的语句,所以导致绘制直线时遇到上述问题。

另外说明一下在CYangRuiVIew的构造函数中先将其初始化为FALSE,在OnLButtonDown()函数中将其修改为TRUE。

2)在OnLButtonUp()函数中加上m_LButtonDown=FALSE;语句后,再次编译连接运行程序,发现在改变线色后在绘制直线,鼠标拖拽绘图实时显示的直线线色不是指定的线色,而是黑色,鼠标左键释放后显示的线色才是正常的选择线色。

仔细分析该现象,可以看出问题出现在OnMouseMove()函数中,由于鼠标实时绘图与绘图模式有关,此时选中的绘图模式为R2_NOT(取反)模式,将OnMouseMove()函数中的dc.SetROP2(R2_NOT);语句改为dc.SetROP2(R2_NOTXORPEN);语句,即绘图模式改为同或绘图模式,然后运行测试,发现改变线色,绘制直线,鼠标拖拽绘图能够实时显示所绘制的指定线色的直线段。

3)头文件的问题。

为了解决窗口大小改变窗口中内容不丢失,在该画图程序中新增了许多图元类及列表对象类,由此在相关类中如果用到另一个类必须要包含相关头文件。

起初,我在各相关类中编好代码后编译有103个错误,而我的代码并没有写错,之后仔细分析错误,发现是没有添加相关头文件的问题,这样我在CMapElement类头文件中添加#include,在CMapList头文件中也添加头文件#include,在CYangRuiDoc类头文件中包含#include"CMapList.h"头文件,在CYangRuiView类实现文件中添加以下头文件#include"Line.h"、#include"Ellipse.h"、#include"Rectangle.h",这样之后再次编译连接可以通过,而且程序能够实现任务书的所有技术要求。

4)其他一些小的语法错误,如变量为定义或者重复定义、变量大小写错误、掉了分号等等都可以在编译器错误提示下轻松解决,故此类调试错误并不详细列出。

7.2测试结果

编译、连接、运行程序后,在窗口中绘制不同线宽,不同线色,不同填充色的图形后窗口如图8所示。

图8绘制的各种属性图形

改变窗口大小后窗口显示的图形内容不变,仅窗口的大小发生变化,具体如下图9所示。

图9窗口发生变化时显示的图形

图10未绘图时窗口显示

程序刚刚运行时,拖动自创建工具条到指定位置后的窗口显示如图10所示。

在上图中,工具条均可浮动,初始时绘图类型为直线,线宽为1个象素,故直线工具栏按钮,线宽1按钮为选中状态。

7.3关键源代码

1)在CMainFrame类头文件protected处添加如下变量

CToolBarm_DrawToolBar;//绘图工具条对象

2)在“MainFrm.cpp”实现文件的OnCreate()函数中添加如下代码:

//创建绘图工具条

if(!

m_DrawToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||!

m_DrawToolBar.LoadToolBar(IDR_DRAW))

{

TRACE0("Failedtocreatetoolbar\n");

return-1;//failtocreate

}

//设置绘图工具条的停放状态

m_DrawToolBar.EnableDocking(CBRS_ALIGN_ANY);

EnableDocking(CBRS_ALIGN_ANY);

DockControlBar(&m_wndToolBar);

//在主窗口中放置绘图工具条

DockControlBar(&m_DrawToolBar);

3)在CYangRuiView类中定义相关变量如下:

private:

intm_DrawType;//绘图类型

intm_LineWidth;//线宽

COLORREFm_LineColor;//线色

COLORREFm_FillColor;//填充色

BOOLm_LButtonDown;//鼠标左键是否按下标志

CPointm_StartPoint;//鼠标绘图开始点坐标

CPointm_EndPoint;//鼠标绘图终止点坐标

HCURSORm_Cursor;//光标资源句柄

4)在CYangRuiDoc类的public中添加下面的成员变量

CMapListm_MapList;//当前绘制的图元列表

5)在CYangRuiView类的构造函数中初始化相关变量,如下所示:

CYangRuiView:

:

CYangRuiView()

{

//TODO:

addconstructioncodehere

m_LineWidth=1;//初始线宽为1个像素

m_LineColor=RGB(0,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工作范文 > 行政公文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1