画板设计报告(共14页).doc
精选优质文档-倾情为你奉上青岛理工大学琴岛学院设 计 报 告课题名称:画图板学 院:青岛理工大学琴岛学院专业班级:计算机网络技术101班学 号:学 生:李经纬指导教师:张秀国青岛理工大学琴岛学院教务处2011年 12 月 30 日学 生李经纬指导教师张秀国课题名称绘图板设计时间2011/12/19至2011/12/30设计地点8#209设计目的1、熟悉用vc编写应用程序的基本方法。2、体会windows编程的消息处理机制。3、强化对C+语言的理解和应用。4、增加对C+和Mfc的认识,锻炼自己的动手能力、查询资料的能力和独立思考的能力指导教师评语系部教研室意 见一、需求分析1.选题:程序的原型最先是老师在上课时演示的,老师指导我们做画图只能实现单一的画线功能,只可以画出直线或者图形,每次只能画出当前图形之前画出的图形不再显示,而且上课的时候只能实现几个颜色的画图,无法实现填充画图以及自由选择颜色。经过查阅资料,手动添加了一些代码和函数实现了这些功能。2.界面:(1) 程序打开界面如下图1所示:图1 打开界面(2)程序打开界面如下图2所示:图2 设置界面3.功能划分: 本画图板可以实现的功能主要有画点,画直线,画圆,画矩形,任意直线,设置直线颜色,设置填充颜色还有线条类型。(1)画图菜单子菜单中可以选择画图形的方式,可以画出的图形有点、直线、矩形,椭圆、以及任意直线。(2)选择画点功能可以在任意位置画出一个点,默认像素为1,颜色为黑色。(3)选择画矩形可以画出一个由默认白色填充的矩形,关于填充色可以在颜色中进行选择自定义颜色。(4)椭圆也可以实现和矩形相同的功能。(5)可以选择画曲线。(6)颜色菜单下可以选择图形颜色以及填充色。(7)点击帮助可显示版本信息以及作者。(8)设置菜单中有线段粗细和类型的选择及预览程序运行实现效果如下图3所示:图3.运行实现界面图4.版权信息4. 用到的类表格、每个类中用到的函数及添加的命令响应表格、各资源对应的ID号表格:表1 用到的类类名描述说明CShape图元基类CDC指针Cline线段类,定义线宽,颜色以及绘制点Crectangle矩形图元类,绘制矩形CEllipse椭圆类,绘制椭圆CDot点类,绘制一个点CMyDrawDoc文档类,实现图元容器的定义和操作CMainFrame框架类CMyDrawView视图类,添加画图函数,设置鼠标移动等功能表 表2 CMyDrawView类用到的函数及命令响应添加的函数和变量描述说明OnDot用来设定画点OnRectangle用来设定矩形OnLine用来设定直线OnAutoline用来设定任意直线OnEllipse用来设定椭圆OnLbuttonDown鼠标左键按下消息响应函数OnLButtonUp左键抬起时消息响应函数OnMouseMove鼠标移动相应函数OnDraw绘制图形函数,设定怎样画出图形BOOL m_bDraw;绘制图形变量CPoint m_ptOrigin;起始点CPoint m_ptEnd;结束点UINT m_nDrawType绘制图形形状COLORREF m_clrFill填充色COLORREFm_clrShape边框颜色int m_nLineStyle线条的样式UINT m_nLineWidth线条的宽度CAutoLine *autoline自由画线CMyDrawDoc* GetDocument()设置文档对象指针表3 在CMainFrame类中用到的函数及添加的命令响应添加函数和命令响应描述说明m_wndStatusBar初始化框架类m_wndToolBa加载工具栏 表4.各个菜单项对应的ID号ID号描述说明IDM_DOT画点IDM_LINE直线IDM_RECTANGLE矩形IDM_ELLIPSE椭圆IDM_AUTOLINE自定义画线IDM_CLRSHAPE图形颜色IDM_CLRFILL填充颜色ID_APP_ABOUT帮助版权信息二、详细设计1.直线图元类的实现在头文件中添加如下代码,定义函数以及参数在CLine类下添加消息处理函数CShape(),添加代码:class CLine :public CShape CLine(COLORREF m_clrShape,CPoint m_ptOrigin,CPoint m_ptEnd,UINT m_nLineWidth,int m_nLineStyle); void Serialize(CArchive &archive);void Draw(CDC *pDC); public:COLORREF m_clrShape; CPoint m_ptOrigin,m_ptEnd;UINT m_nLineWidth;int m_nLineStyle;这样就实现了画直线的功能,其中CLine()表示绘制纯虚函数,参数为设备指针。Serialize函数是为了实现CArray,CList和CMap调用这个函数以串行化元素。缺省的实现进行按位读写,Draw(CDC *pDC)作用是格式化为字符串COLOREF是为了描绘一个RGB颜色,Cpoint定义了一个位置点,UINT m_nLineWidth定义线宽,m_nLineStyle定义线形。在.cpp文件中实现的代码如下CLine:CLine(COLORREF m_clrShape,CPoint m_ptOrigin,CPoint m_ptEnd,UINT m_nLineWidth,int m_nLineStyle)this->m_clrShape=m_clrShape;this->m_ptOrigin=m_ptOrigin;this->m_ptEnd=m_ptEnd;this->m_nLineWidth=m_nLineWidth;this->m_nLineStyle=m_nLineStyle;void CLine:Serialize(CArchive &ar) if(ar.IsStoring()ar<<m_clrShape<<m_ptOrigin<<m_ptEnd<<m_nLineWidth<<m_nLineStyle; elsear>>m_clrShape>>m_ptOrigin>>m_ptEnd>>m_nLineWidth>>m_nLineStyle; void CLine:Draw(CDC *pDC) CPen pen(m_nLineStyle,m_nLineWidth,m_clrShape);CPen *penOld=pDC->SelectObject(&pen); pDC->MoveTo(m_ptOrigin); pDC->LineTo(m_ptEnd); pDC->SelectObject(penOld); CLine:Cline()为调用友元函数利用指针分别指向颜色,形状,点大小等,void CLine:Serialize()表示从CLine类中读取信息,if(ar.IsStoring()表示判断是保存文件还是读取文件,” ar<<”和” ar>>”分别表示读取内容和写入内容。void CLine:Draw(CDC *pDC) 声明一个画笔对象,利用线型、线宽、颜色参数,CPen *penOld=pDC->SelectObject(&pen)表示选择画笔,返恢复来画笔对象指针,pDC->MoveTo(m_ptOrigin)表示画笔起点,pDC->LineTo(m_ptEnd)表示画线到终点,pDC->SelectObject(penOld)表示恢复原来画笔对象。2.椭圆图元类的实现class CEllipse :public CShapeCOLORREF m_clrShape;COLORREF m_clrFill;CPoint m_ptOrigin;CPoint m_ptEnd;该函数省略的部分为和直线类相同的部分,在此不做赘述。COLORREF m_clrShape是选择绘制图形边框的颜色,COLORREF m_clrFill是绘制图形填充颜色,CPoint m_ptOrigin绘制起始点,CPoint m_ptEnd绘制结束点,点图元类,矩形图元类的功能实现和椭圆以及直线类类似,在此不做赘述,.cpp文件实现与直线类代码大同小异,在此也不一一列举了。3.任意直线图元类的实现相比起直线类以及其他两个类的不同之处在于lass CAutoLine :public CShapepublic:COLORREF m_clrShape;UINT m_nLineWidth;int m_nLineStyle;CArray<CPoint,CPoint> m_ptArray;DECLARE_SERIAL(CAutoLine);CArray<CPoint,CPoint> m_ptArray定义了模板类CArray的一个实例ptArray,它的元素是CPoint对象DECLARE_SERIAL(CAutoLine)为一个可以串行化的CObject派生类产生必要的C+标题代码。串行化是把某个对象的内容从一个文件读出和写入一文件。在.H文件中使用DECLARE_SERIAL宏,接着在需要访问此类对象的全部.CPP文件中包含此文件。如果DECLARE_SERIAL包含在类定义中,那么IMPLEMENT_SERIAL必须包含在类工具中。DECLARE_SERIAL宏包含全部DECLARE_DYNAMIC,IMPLEMENT_DYCREATE的功能4.绘图类的实现这个类非常重要,要实现所绘图形的显示靠此函数。void CMyDrawView:OnDraw(CDC* pDC)CMyDrawDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);int nCount=pDoc->m_obArray.GetSize();for(int i=0;i<nCount;i+)(CShape*)pDoc->m_obArray.GetAt(i)->Draw(pDC);CMyDrawDoc* pDoc = GetDocument()对文档头指针的传递,得到文档对象的指针nCount=pDoc->m_obArray.GetSize()是为了获得到容器内的图元数目. (CShape*)pDoc->m_obArray.GetAt(i)->Draw(pDC)作用是遍历所有的图元对象指针,调用虚函数Draw()绘制图元5.绘制图形边框的颜色形状该函数是为了给绘制的图形边框着色实现代码如下void CMyDrawView:OnClrshape() CColorDialog dlg;dlg.m_cc.Flags |=CC_RGBINIT;dlg.m_cc.rgbResult=m_clrShape; if(IDOK=dlg.DoModal()m_clrShape=dlg.m_cc.rgbResult;其中CColorDialog dlg为调用颜色对话框,实现的功能如图4所示,dlg.m_cc.Flags |=CC_RGBINIT这其中"|" 组合符不能去掉,因为Flags会有个默认值,dlg.m_cc.rgbResult=m_clrShape用来保存上一次选择的结果,m_clrShape=dlg.m_cc.rgbResult用来表示选择的结果,同样,在void CMyDrawView:OnClrfill()函数中,同样通过CColorDialog dlg调用颜色选择对话框实现对颜色的选择,这个函数是选择填充颜色。其余代码出了传递参数不同外其余相同,在此不做列举。图4. CColorDialog dlg功能实现界面6.鼠标移动消息响应功能下面是鼠标按下实现功能代码void CMyDrawView:OnLButtonDown(UINT nFlags, CPoint point) m_ptOrigin=point;SetCapture();m_bDraw=TRUE;m_ptEnd=point;在此段函数中,SetCapture()表示当鼠标在窗口之外仍能捕捉动作,m_bDraw=TRUE表示判断鼠标是否确实实在视图区中按下的,m_ptEnd=point用于记录鼠标落点。下面是鼠标抬起时实现功能代码void CMyDrawView:OnLButtonUp(UINT nFlags, CPoint point) CClientDC dc(this);if(m_bDraw)m_bDraw=FALSE;ReleaseCapture();CMyDrawDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);switch(m_nDrawType) case 1:/画点CDot *dot=new CDot(m_clrShape,point);pDoc->m_obArray.Add(dot);break;case 2:/画线break;case 3:/矩形break;case 4:/椭圆break;case 5:/任意线break;Invalidate();/刷新显示,强调调用onDraw()函数CView:OnLButtonUp(nFlags, point);ReleaseCapture()判断是否在视图区内,如果是视图区内按下的鼠标,就是绘图状态,CMyDrawDoc* pDoc = GetDocument()表示得到文档对象指针,switch(m_nDrawType)表示根据当前工具类型执行操作,case1,2,3,4,5分别表示画点,画线,画矩形,画椭圆,任意线,其中每段函数都是调用相关类实现功能。下面是鼠标移动画线实现代码void CMyDrawView:OnMouseMove(UINT nFlags, CPoint point) .if(m_bDraw)switch(m_nDrawType)case 1:break;case 2:CClientDC dc(this);CPen pen(m_nLineStyle,m_nLineWidth,m_clrShape);dc.SetROP2(R2_WHITE);dc.MoveTo(m_ptOrigin);dc.LineTo(m_ptEnd);dc.SetROP2(R2_COPYPEN);CPen *penOld=dc.SelectObject(&pen);dc.MoveTo(m_ptOrigin);dc.LineTo(point);dc.SelectObject(penOld);m_ptEnd=point;break;case 3:break;case 4:break;case 5:break;default:break;CView:OnMouseMove(nFlags, point);首先判断鼠标是否按下,鼠标没有按下,不是绘图状态,就退出函数,这里使用了一个具有异或功能的画笔,第一次使用时绘制图形,第二次使用则把上次的图形擦掉了,即在原来的基础上重新绘制图形。此处只列举了一种情况,其余代码与此类似,在此不再赘述。7.对画图板初始状态进行设置在绘制图形之前对所绘制的各选项进行初始化CMyDrawView:CMyDrawView()m_nLineWidth=1;m_nLineStyle=0;m_clrShape=RGB(0,0,0);m_clrFill=RGB(255,255,255);m_nDrawType=0;m_ptOrigin=0;m_bDraw=FALSE;初始状态时所绘点的粗度,默认图线长度为零,初始填充色为无色,默认边框颜色为黑色,画板没有任何图形,鼠标是未按下状态。三、遇到问题和解决方法问题1:工程内的一些文件无法打开。解决方法:在fileview中手动载入缺失的文件,并将文件代码中的#ifndef_和#define_两行语句删除并重新打开工程。问题2:添加Invalidate()之后,将其放在OnMouseMove()里,但时只能在窗口内画一个图形,即每画完一个图形就刷新一次解决方法:将Invalidate()改为Invalidate(0),这时可以绘制多个图形,但是鼠标每移动一个位置都进行一次刷新,绘图结束后,绘图过程中所有的痕迹都存在,产生了许多拖动的影子,最后将Invalidate()放在了OnLButtonUp()中,那么每次重绘,上次的图形会作为背景被保留下来问题3:提示无法找到#endif出现宏编译错误解决方法:通过将出现问题的文件删除然后重建使问题得到解决问题4:开始调试时总是提示变量未进行定义解决方法:在视图类的MyDrawView.cpp文件中试用了点,线段,矩形,椭圆,任意直线这五个图元类,因此需要在头文件中添加#include”SOline”等进行调用。问题5:开始定义的画图板的的各个功能为灰色,无法实现解决方法:在建立类向导中为其添加功能函数,然后为其添加实现代码问题6:创建时无法找到鼠标移动函数解决方法:需要在建立类向导里分别添加WM_LBUTTONDOWN、WM_LBUTTONUP、WM_MOUSEMOVE三个鼠标响应函数分别表示鼠标左键的按下,抬起,移动问题7:对帮助对话框的内容进行修改,但是修改完成后执行程序不显示解决方法:删除Debug文件夹,然后进行重新编译,执行问题解决问题8:LINK:fatal error LNK1168:cannot open Debug/MyDraw.exe for writing。解决方法:一般情况是程序上次运行并没有正常关闭,重新启动计算机后问题得到解决。问题9:想取消繁琐的工具栏,只用一个菜单栏或创建一个DialogBar,但不知道该如何取消。解决方法:开始只知道取消菜单栏是用一个函数SetMenu()然后将其参数设为NULL,即可取消菜单栏,但不知道用什么函数取消工具栏。其实很简单,只要在CMainFram类中的OnCreat()函数中,将设置ToolBar的相关语句屏蔽掉就可以了。四、总结与展望:这次的MFC程序编写遇到了比想象中更大的挫折,出现了许多从未接触过的困难,但是通过资料的查询和自己的实验琢磨将大部分问题解决,没有解决的问题也通过变换思路的方法间接实现了。通过这次课程设计实践我真的学习到了不少东西,首先便是去了解什么是MFC。微软基础类库(MFC:Microsoft Foundation Class)是微软为Windows程序员提供的一个面向对象的Windows编程接口,它大大简化了Windows编程工作。使用MFC类库的好处是:首先,MFC提供了一个标准化的结构,这样开发人员不必从头设计创建和管理一个标准Windows应用程序所需的程序,而是“站在巨人肩膀上”,从一个比较高的起点编程,故节省了大量的时间;其次,它提供了大量的代码,指导用户编程时实现某些技术和功能。MFC库充分利用了Microsoft开发人员多年开发Windows程序的经验,并可以将这些经验融入到你自己开发的应用程序中去。对用户来说,用MFC开发的最终应用程序具有标准的、熟悉的Windows界面,这样的应用程序易学易用;另外,新的应用程序还能立即支持所有标准Windows特性,而且是用普通的、明确定义的形式。事实上,也就是在Windows应用程序界面基础上定义了一种新的标准MFC标准。随着编程语言的推陈出新,MFC一些缺点也日益突出。最重要的就是入门门槛相对其他语言要高,而且同样完成一个任务代码量相对较多。而原有的优势如运行速度快等,也因为其他编程语言的日臻完善和个人电脑的运算速度增加而显得不那么突出。这次课设使我了解编程思想和编程技巧,也认识了软件生命周期的各个环境,包括构思、设计、编写、调试、修改等。编程的风格也很重要,MFC适用于大型系统软件和应用软件的开发。课程设计时培养综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对我们实际工作能力的具体训练和考察过程,经过这两个星期的上机实践学习,使我对MFC有了更进一步的认识和了解。在不长时间里我明白了,不仅仅要重视,而且要通过不断地上机操作才能更好的学习这门语言。同时,我也认识到自己有很多不足的地方,对MFC中经常出现的错误还不够了解。通过本次实践设计,使我在这方面有所提高,同时,也锻炼了自己的设计能力从代码的编写,调试错误,完成系统这一过程让我学到了很多东西,比如在MFC中提供了很多编程接口,而各个接口之间又是通过函数互相连接,对各个编程接口的陌生是我遇到的最大障碍之一,还有就是在MFC中编写程序要严格区分大小写,负责会造成编译错误。这次程序的设计也使我对MFC的编程产生了兴趣,在今后的生活学习中,MFC将与我常伴。由于时间急迫且能力有限,许多想要实现的功能未能完成。其中最大的遗憾便是没有图像的选择功能,没有了这个功能使已有的图形无法进行修改,大大降低了这个程序的可用性。而且其中点、线、面的几个基本图形及上色功能太基本,这对于用户的使用造成了一定的困难,我希望通过几个快捷键的加入使图形能按照用户的需求画的更规则的,以便减少用户的操作难度。除此之外文字输入及编辑缺失也是这个软件的致命伤,如果添加对于文字的基本处理功能再加上本身的图像处理功能,这个程序便显得相对完整一些,使得基本的应用成为了可能。参考文献:面向对象程序设计(C+语言)清华大学出版社 数据结构教程(第三版) 清华大学出版社专心-专注-专业