1、目录1. 基本功能描述 12. 设计思路 13. 软件设计 33.1 设计步骤 .33.2 界面设计 .83.3 关键功能的实现 .94. 结论与心得体会 105. 思考题 106. 附录 116.1 调试报告 .116.2 测试结果 .116.3 关键源代码 .12武汉理工大学面向对象程序设计课程设计说明书1简单画图程序1. 基本功能描述简单画图程序实现了常见图形的绘制、图形属性的设置和图形数据的暂存等功能。该程序的具体功能模块包括以下几项:1) 图形绘制模块。该模块实现直线段、椭圆、矩形等图形的绘制功能。在鼠标移动的过程中能实时显示当前绘制的图形。2) 图形属性设置模块。该模块实现绘图线条
2、的线宽,线色,图形填充色等属性设置功能。3) 图形数据暂存模块。该模块实现直线段、椭圆、矩形等图形数据暂存功能,涉及图形的坐标、线宽、线色、填充色等数据。2. 设计思路1) 对需要用到的变量进行初始化。2) 选择相应的图形之后就响应相应的消息处理函数,给 shape 赋对应的值。选择不同的线宽,线色与填充色,即可改变画笔或画刷的属性。3) 鼠标的按下响应函数 OnLButtonDown(),捕捉鼠标当前位置得到起点的坐标,鼠标的拖动响函数 OnMouseMove()改变终点的坐标,鼠标的弹起响应 OnLButtonUp(),确定终点坐标,刷新,得到绘制图形。4) 选择图形或其它属性,可进行下一
3、次绘制。5) 程序的流程图如下:开始武汉理工大学面向对象程序设计课程设计说明书2定义并初始化变 shape 线色 m_ncolor 填充色 m_fcolor 画笔 pen 画刷 brush 绘图起点 opoint 绘图终点 cpoint选择线宽改变画笔属性 默认值(W=1)选择线色改变画笔属性 默认值(黑色)武汉理工大学面向对象程序设计课程设计说明书3选择填充改变画刷属性 默认值(白色)直线 矩形 椭圆响应函数OnLine()shape=1响应函数OnRect()shape=2响应函数OnEllipse()shape=3武汉理工大学面向对象程序设计课程设计说明书4图 1 程序流程图3. 软件设
4、计3.1 设计步骤鼠标左键按下 响应函数 OnLButtonDown()opoint=point鼠标移动 响应函数 OnMouseMove()epoint=point响应 OnPaint(),绘制图形鼠标左键弹起响应函数 OnLButtonUp()刷新,得到图形结束武汉理工大学面向对象程序设计课程设计说明书51) 创建单文档创建一个 MFC AppWizardexe工程,命名为“LiYuJing”,如图 1 所示,并创建单文档,如图 2 所示。创建成功后,系统自动生成相应的类,如图 3 所示。图 2 创建工程武汉理工大学面向对象程序设计课程设计说明书6图 3 创建单文档图 4 生成类2) 编辑
5、菜单添加需要的菜单项,如图 4 所示;并在菜单的属性中设定好所对应的 ID,如图 5 所示,各项菜单对应的 ID 如表 1 所示(其中线宽菜单为弹出菜单,只需在菜单项目属性中的弹出选项前打勾即可,分隔线亦只需在菜单项目属性中选中分隔符选项即可) 。武汉理工大学面向对象程序设计课程设计说明书7图 5 添加菜单项图 6 设置菜单 ID表 1 对应菜单 ID菜单名 ID 菜单名 ID直线 ID_LINE 线宽 1 ID_W1矩形 ID_RECT 线宽 2 ID_W2椭圆 ID_ELLIPSE 线宽 3 ID_W3武汉理工大学面向对象程序设计课程设计说明书8颜色 ID_COLOR 线宽 4 ID_W4
6、填充色 ID_FILLCOLOR 线宽 5 ID_W5建立类向导,在视图类 CLiYuJingView 中,对各菜单项添加对应的 COMMAND 消息处理函数,部分菜单项还添加对应的 UPDATE_COMMAND_UI 消息函数,如图 7 所示。图 7 建立类向导3) 创建工具栏在插入处选择资源,新建工具栏,如图 8 所示;武汉理工大学面向对象程序设计课程设计说明书9图 8 新建工具栏在工具栏上添加相应的按钮,在属性处更改其 ID,如图 9 所示。图 9 编辑工具栏4) 添加鼠标消息处理函数添加鼠标消息处理函数 OnLButtonDown()、OnMouseMove()、OnLButtonUp
7、(),利用橡皮筋技术实时显示绘制图形,并绘制最终图形,具体源代码参看附录。添加过程为:武汉理工大学面向对象程序设计课程设计说明书10选择 View 菜单下的 ClassWizard 菜单项打开类向导,在类列表中选择 CLiYuJingView 类,在消息列表框中选择 WM_LBUTTONDOWN 消息并用鼠标左键双击,此时类向导自动在成员函数列表框中添加该消息的处理函数。然后再用同样方法添加 WM_MOUSEMOVE消息和 WM_LBUTTONUP 消息的处理函数,如图 10 所示。图 10 添加相应代码3.2 界面设计各控件名称,类型,属性以及相关变量如表 2 所示。表 2 界面控件表控件名
8、称 控件类型 属性 相关变量绘图 下拉式菜单 无 无直线 菜单项工具栏按钮 ID_LINE int shape矩形 菜单项工具栏按钮 ID_RECT int shape椭圆 菜单项工具栏按钮 ID_ELLIPSE int shape武汉理工大学面向对象程序设计课程设计说明书11线宽 弹出式菜单 无 int w颜色(线色) 菜单项工具栏按钮 ID_COLORCOLORREF m_nColor填充色 菜单项工具栏按钮 ID_FILLCOLORCOLORREF m_fColor整体界面如图 11 所示。图 11 整体界面显示3.3 关键功能的实现1) 选择要绘制的图形在直线、矩形以及椭圆的消息处理函
9、数里为 shape 分别赋值为 1,2,3,在 OnPaint()函数里添加 3 个 if 语句的代码来这实现这三个图形的绘制:当选择画直线时, shape=1,则执行绘制直线代码,当选择画矩形时,shape =2,则执行绘制矩形的代码,当性选择画椭圆武汉理工大学面向对象程序设计课程设计说明书12时,shape=3,则执行绘制椭圆的代码。2) 改变线宽在 OnPaint()创建的画笔中,pen.CreatePen(PS_SOLID,w, m_nColor),线宽处用 w 表示,则改变 w 的值即改变了画笔的粗细。选择菜单绘图 线宽选择划线宽度值,此时所选的线宽值就赋给线宽变量 w。若不选择线宽
10、值,则 w=1(即默认线宽值为 1)。3) 改变线色在 OnPaint()创建的画笔中,pen.CreatePen(PS_SOLID,w, m_nColor),线的颜色处用m_nColor 表示,则改变 m_nColor 即改变了画笔的颜色。选择菜单绘图颜色,会弹出通过 WM_COLORREF 从系统中引入的颜色选择对话框,选择颜色后,点击确定则相应颜色值就赋给变量 m_nColor,此时画笔的颜色就会发上变化。若不选择颜色,则默认(线)颜色为黑色。4) 改变填充色在 OnPaint()创建的画刷中,brush.CreateSolidBrush(m_fColor),颜色就是用 m_fColor
11、表示的,改变 m_fColor 即改变了画刷的颜色。选择菜单绘图填充色,会弹出通过WM_COLORREF 从系统中引入的颜色选择对话框,选择颜色后,点击确定则相应颜色值就赋给变量 m_fColor,此时画刷的颜色就会发上变化。若不选择颜色,则默认填充色为白色。5) 橡皮筋技术实现鼠标实时绘图利用橡皮筋技术可以实现在鼠标拖拽作图时,实时显示当前绘图的情况。这样,我们就要在鼠标移动的消息处理函数中添加相应的代码。在鼠标左键按下的时候,记录下图元起始点;在鼠标移动的时候,获取鼠标当前位置,绘制出新的图形,同时,将上一次绘制的图形擦除,这就是橡皮筋技术。在 OnMouseMove()函数中调用 Set
12、ROP2()函数将绘图模式设置为 NOTXORPEN(同或)模式,使用同或模式绘图就可以画上真实的图形,并擦除上次绘制的图形。在 OnLButtonDown()函数中调用 SetCapture()函数捕捉鼠标, OnLButtonUp()函数中调武汉理工大学面向对象程序设计课程设计说明书13用 ReleaseCapture()函数释放鼠标。整个绘图过程就是在鼠标左键按下时确定绘图起点,移动鼠标实时显示绘制的图形,鼠标左键弹起即完成图形的绘制的过程。4. 结论与心得体会这次课设我成功地完成了设计要求,能用鼠标拖动绘制直线段、椭圆、矩形等基本图形;能控制所绘制图形的线宽、线色、填充色等。经过程序调
13、试,该简单画图程序能够绘制指定线宽、线色、填充色的图形,在鼠标移动的过程中能实时显示当前绘制的图形。在拿到任务书后,我通过查阅资料,不断编程调试,以及请教同学,最终实现绘图程序的要求。我学会了鼠标消息的分类,鼠标消息处理函数的常见编程方法,以及捕捉鼠标 SetCapture()函数,释放鼠标 ReleaseCapture()函数。同时,利用橡皮筋技术实现鼠标绘图的实时显示是我最大的收获。我在调试程序时,发现绘制直线时鼠标左键弹起直线并没有绘制结束,而再次单击鼠标左键,又以上次绘制的直线段终点作为起点绘制直线,即绘制出的直线段是一段连着一段的。在自己检查数遍并未发现错误之处后,我求助了同学,在
14、OnLButtonDown()函数中添加了一句 cpoint=opoint=point0 之后问题得以解决。通过这次课程设计,我学到了很多与计算机绘图相关的基础知识,并进一步体会到面向对象的程序设计的强大,以及 Windows 应用程序用户界面统一、友好,独立于设备的图形操作特点。这次的课程设计虽只是做了一个简单的绘图工具,但是也让我从设计者的角度了解了设计一个程序的过程,看似一个很简单的工具,其制作的背后工作是繁琐的。哪怕是平时我们使用的很顺手的一个小工具,其开发的一切步骤都不可小觑,所以,关于编程还有太多的东西等着我们去了解,学习。5. 思考题1) 说明直线、椭圆、矩形绘制使用的函数,及其
15、参数含义?答:直线、椭圆、矩形绘制使用的函数是 OnPaint()。函数里面定义和创建了绘图的画笔 pen 和填充图形的画刷 brush,3 种图形本身对应的消息处理函数里分别赋给 shape3武汉理工大学面向对象程序设计课程设计说明书14个不同的值:1,2,3,在 OnPaint()里有 3 个 if 语句,用来这实现这三个图形的绘制:当选择画直线时,shape=1,则执行绘制直线代码,当选择画矩形时,shape =2,则执行绘制矩形的代码,当性选择画椭圆时,shape=3,则执行绘制椭圆的代码。2) 如何控制菜单项的状态,使用的消息类型?答:通过添加 UPDATE_COMMAND_UI 消
16、息函数,在生成的函数里添加相关代码来控制菜单项的状态及使用的消息类型。如选择直线时,使 shape=1,则 OnUpdateLine 里添加 pCmdUI-SetCheck(shape=1),那么当 shape 的值为 1 时,即代表选择了直线项,此时菜单中的直线选项前就打勾了,代表选中。矩形和椭圆类似。3) 如何设置菜单和工具栏按钮的快捷键操作?答:切换到资源视图,选择 Accelerator 资源类型,双击 IDR_MAINFRAME 加速键资源,打开加速键编辑窗口。 在 ID 下拉列表框中选择相应菜单项的 ID,在 Key 一栏中输入相应键值(比如 L) ,选择 Ctrl 复选框和 Vi
17、rtKey 单选按钮,关闭加速键编辑窗口,即可完成加速键设置,如图 12 所示。图 12 快捷键设置6. 附录6.1 调试报告1) 一开始我并没有添加刷新函数 Invalidate(),这就使程序运行之后,无论鼠标左键按下时如何移动无法绘图,这是因为当一个窗口内键入内容其实就是将窗口刷新了,相当于更新了窗口,故必须有刷新函数。武汉理工大学面向对象程序设计课程设计说明书152) 在调试程序时,发现绘制直线时鼠标左键弹起直线并没有绘制结束,而再次单击鼠标左键,又以上次绘制的直线段终点作为起点绘制直线,即绘制出的直线段是一段连着一段的。在 OnLButtonDown()函数中添加了一句 cpoint
18、=opoint=point0 之后问题得以解决。这是因为要给初始坐标和终止坐标赋个 0 值,不然系统无法判断坐标位置。6.2 测试结果编译、连接、运行程序后,在窗口中绘制不同线宽,不同线色,不同填充色的图形后窗口如图 13 所示。图 13 绘制各个图形6.3 关键源代码1) 在“MainFrm.h”中,在 class CMainFrame : public CFrameWnd 里的 protected 下定义:CToolBar m_drawToolBar; /工具栏武汉理工大学面向对象程序设计课程设计说明书162) 在“MainFrm.cpp”中,在 CMainFrame:OnCreate(L
19、PCREATESTRUCT lpCreateStruct)里添加以下代码:if (!m_drawToolBar.Create(this) |!m_drawToolBar.LoadToolBar(IDR_DRAW) TRACE0(“Failed to create status barn“);return -1; 3) 在“LiYuJingView.h”中,在 class CLiYuJingiew : public CView 里的 public 下定义相关变量:CLiYuJingDoc* GetDocument();COLORREF m_nColor;COLORREF m_fColor;CPo
20、int cpoint; CPoint opoint;BOOL m_Down;int w;int shape;HCURSOR m_Cursor;/光标资源句柄4) 在 “LiYuJingViewView.cpp”中,添加如下函数及代码:CLiYuJingView:CLiYuJingView()武汉理工大学面向对象程序设计课程设计说明书17/ TODO: add construction code herew=1; /初始线宽默认为 1shape=0;m_fColor=RGB(255,255,255);/初始填充色为白色m_Cursor=AfxGetApp()-LoadStandardCursor
21、(IDC_CROSS);void CLiYuJingView:OnW5() w=5; /令线宽为 5 void CLiYuJingView:OnW1() w=1; /令线宽为 1void CLiYuJingView:OnW2() w=2; /令线宽为 2void CLiYuJingView:OnW3() 武汉理工大学面向对象程序设计课程设计说明书18w=3; /令线宽为 3void CLiYuJingView:OnW4() w=4; /令线宽为 4void CLiYuJingView:OnUpdateW1(CCmdUI* pCmdUI) pCmdUI-SetRadio(w=1); /当线宽为
22、1 时,此选项前标有圆点void CLiYuJingView:OnUpdateW2(CCmdUI* pCmdUI) pCmdUI-SetRadio(w=2); /当线宽为 2 时,此选项前标有圆点void CLiYuJingView:OnUpdateW3(CCmdUI* pCmdUI) 武汉理工大学面向对象程序设计课程设计说明书19pCmdUI-SetRadio(w=3); /当线宽为 3 时,此选项前标有圆点void CLiYuJingView:OnUpdateW4(CCmdUI* pCmdUI) pCmdUI-SetRadio(w=4); void CLiYuJingView:OnUpda
23、teW5(CCmdUI* pCmdUI) pCmdUI-SetRadio(w=5);void CLiYuJingView:OnLine() shape=1; /选择直线,则令 shape 为 1m_Cursor=AfxGetApp()-LoadStandardCursor(IDC_CROSS);void CLiYuJingView:OnRect() shape=2; /选择矩形,则令 shape 为 2武汉理工大学面向对象程序设计课程设计说明书20m_Cursor=AfxGetApp()-LoadStandardCursor(IDC_CROSS); void CLiYuJingView:OnE
24、llipse() shape=3; /选择椭圆,则令 shape 为 3m_Cursor=AfxGetApp()-LoadStandardCursor(IDC_CROSS); void CLiYuJingView:OnUpdateLine(CCmdUI* pCmdUI) pCmdUI-SetCheck(shape=1); /shape 为 1 时,直线选项前打上勾void CLiYuJingView:OnUpdateRect(CCmdUI* pCmdUI) pCmdUI-SetCheck(shape=2); /shape 为 2 时,矩形选项前打上勾void CLiYuJingView:OnU
25、pdateEllipse(CCmdUI* pCmdUI) 武汉理工大学面向对象程序设计课程设计说明书21pCmdUI-SetCheck(shape=3); /shape 为 3 时,椭圆选项前打上勾void CLiYuJingView:OnColor() CColorDialog Color; / 创建颜色对话框if(Color.DoModal() = IDOK) / 如果用户点击 OK 按钮 m_nColor=Color.GetColor(); / 更改颜色,把颜色赋到 m_nColorvoid CLiYuJingView:OnFillcolor() CColorDialog FullCol
26、or; / 创建颜色对话框if(FullColor.DoModal() = IDOK) / 如果用户点击 OK 按钮 m_fColor=FullColor.GetColor(); / 更改颜色,把颜色赋到 m_fColorvoid CLiYuJingView:OnPaint() CPaintDC dc(this); / device context for paintingCPen pen; /定义画笔CBrush brush; /定义画刷武汉理工大学面向对象程序设计课程设计说明书22pen.CreatePen(PS_SOLID,w, m_nColor); /创建画笔brush.CreateS
27、olidBrush(m_fColor); /创建画刷dc.SelectObject( /获取画笔dc.SelectObject( /获取画刷if(shape=1)dc.MoveTo(opoint.x,opoint.y);dc.LineTo(cpoint.x,cpoint.y); /绘制直线,从 opoint 到 cpoint 连线if(shape=2)dc.Rectangle(opoint.x,opoint.y,cpoint.x,cpoint.y); /绘制矩形if(shape=3)dc.Ellipse(opoint.x,opoint.y,cpoint.x,cpoint.y); /绘制椭圆vo
28、id CLiYuJingView:OnLButtonDown(UINT nFlags, CPoint point) / TODO: Add your message handler code here and/or call defaultm_Down=TRUE; /鼠标按下 SetCapture(); /获取坐标cpoint=opoint=point; /把鼠标所在坐标赋给起点坐标 opointReleaseCapture(); /释放坐标CView:OnLButtonDown(nFlags, point);武汉理工大学面向对象程序设计课程设计说明书23void CLiYuJingView:
29、OnMouseMove(UINT nFlags, CPoint point) if(m_Down) /如果鼠标按下SetCursor(m_Cursor);/设置使用光标资源CClientDC dc(this);/构造设备环境对象CPen newpen;/新画笔CPen *oldpen;/老画笔CBrush newbrush;/新画刷CBrush *oldbrush;/老画刷/创建指定宽度和线色的画笔newpen.CreatePen(PS_SOLID, w,m_nColor); newbrush.CreateSolidBrush(m_fColor);/创建指定颜色的画刷oldpen=dc.Sel
30、ectObject( /将创建的画笔选入设备环境oldbrush=dc.SelectObject( /将创建的画刷选入设备环境dc.SetROP2(R2_NOTXORPEN);/设置同或绘图模式/判断鼠标移动的同时鼠标左键按下,并且要绘制的是直线段if(m_Downdc.LineTo(cpoint);/绘制新的直线段cpoint=point;/保存新的终止点dc.MoveTo(opoint);dc.LineTo(point);/判断鼠标移动的同时鼠标左键按下,并且要绘制的是椭圆if(m_Down/绘制新的矩形dc.Rectangle(opoint.x,opoint.y,point.x,poin
31、t.y);cpoint=point;/保存新的终止点/判断鼠标移动的同时鼠标左键按下,并且要绘制的是矩形if(m_Downdc.Ellipse(opoint.x,opoint.y,point.x,point.y);cpoint=point;/保存新的终止点newbrush.DeleteObject();/删除新画笔dc.SelectObject(oldpen);/恢复原有画笔newbrush.DeleteObject();/删除新画刷dc.SelectObject(oldbrush);/恢复原有画刷CView:OnMouseMove(nFlags, point);void CLiYuJingView:OnLButtonUp(UINT nFlags, CPoint point) m_Down=FALSE; /鼠标不按下,即弹起Invalidate(0); /刷新 CView:OnLButtonUp(nFlags, point);