c++课程设计(简易绘图程序)_第1页
c++课程设计(简易绘图程序)_第2页
c++课程设计(简易绘图程序)_第3页
c++课程设计(简易绘图程序)_第4页
c++课程设计(简易绘图程序)_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、精选优质文档-倾情为你奉上目 录1、需求与功能分析为了检验一个学期以来自己学习c+这门课程能够学到多少知识,加上原来就对图像处理就比较感兴趣,曾经更有想过要做一个可以合成红蓝3D图片的一款软件,就是那种需要带上红蓝眼镜才可以看到3D效果的那种图片,自己也有用photoshop做过这样的图片,但是photoshop需要调很多东西才能合成这样的图片,而且还要用相机送两个不同的角度拍两张照片作为源图片去合成红蓝3D图片,虽然我知道原理并不难,但是当我选择了” 简易绘图程序”这个课程设计的题目之后,才发现每实现一个功能都需要花很多的精力,而且实现那些功能之后还会发现各种各校的bug,需要细心去寻找解决

2、的办法。如今课程设计也要上交,一样还有很多我想实现的功能都还没实现,最终也没有实现我想要实现的功能-合成红蓝3D图片。只做了一些简单的绘图功能。功能分析,目前这个软件的主要功能有如下:1、 画直线:通过OnLine()函数实现。2、 画矩形:通过OnRectangle()函数实现。3、 画椭圆:通过OnEllipse()函数实现。4、 铅笔工具:可以画任意线条。通过OnPencil()函数实现。5、 橡皮擦:可以擦除所画的线条。该功能还没实现。6、 右键弹出菜单:可以在客户中点击鼠标右键,快速选择常用菜单。通过OnContextMenu函数实现。7、 状态栏显示鼠标移动的坐标:在程序的右下角显

3、示,通过OnUpdateX(CCmdUI *pCmdUI)和OnUpdateY(CCmdUI *pCmdUI)这两个函数实现。8、 画图颜色选择:可以画任何颜色的线条,通过OnEditColor()函数实现。9、 读取bmp位图:可以在电脑中选择一个bmp位图,在程序中显示出来,通过新建一个Cdib类来读取bmp文件信息再view类和Doc类调用来显示该位图。10、 保存为bmp位图:可以将在程序所画的图形保存为一幅bmp图片,通过view中的SaveAsBmp(CString filename)实现。11、 线条类型及线宽的设置:可以将画出的线条设置成实线、虚线、点线,还可以设置线条的粗细,

4、通过示例这一功能可以立刻显示所选择线条的粗细及线型。通过新建CSettingDlg类,再在view类中调用OnSetting()函数实现画笔的对话框,CSettingDlg类中的OnPaint()函数是实现示例功能的。12、 窗口的重绘时不擦除原来的内容:可以在窗口发生变化时,窗口的内容不消失,程序在窗口尺寸发生变化时,将会发送WM_PAINT消息,这时首先会擦除窗口背景,然后进行重绘操作,这样就把窗口中先前绘制的内容擦除了。我是使用双缓冲来解决这个问题的,双缓冲设计思路:如果只是为了让窗口闪烁不那么厉害,避免背景色的填充是最直接的办法。但是那样的话,窗体上会变的一团糟。因为每次绘制图象的时候

5、都没有将原来的图象清除,造成了图象的残留,于是窗体重绘时,画面往往会变的乱七八糟。所以单纯的禁止背景重绘是不够的。我们还要进行重新绘图,但要求速度很快,于是想到了使用 BitBlt函数。它可以支持图形块的复制,速度很快。我们可以先在内存中作图,然后用此函数将做好的图复制到前台,同时禁止背景刷新,这样就消除了闪烁。以上就是双缓冲绘图的基本的思路。一部分代码写在了OnLButtonUp(UINT nFlags, CPoint point)函数里面,也有一部分打码写在了OnDraw(CDC* pDC)函数里面。2、系统总体框架简单绘图工具 保存位图颜色及线型设置读取位图铅笔工具画椭圆画矩形画直线 图

6、1 总体框架3、模块设计与分析3.1画图模块:该模块的大部份功能都写在了view类里面,这样造成了后期的修改造成了一定的影响,对于排错,修复bug增加了难度,对于初次使用mfc做一个相对大一点的程序,在函数分配,类的建立都有很多不足的地方。该模块也是此次程序的重点模块之一,主要负责画一些简单图形,例如:直线、矩形、椭圆、任意曲线(铅笔)等等;有线型、线宽的设置;还有画笔颜色的选择,可以画各种各样颜色的线条。该模块的设计思路是:简易画图工具线型、线宽设置颜色选择。3.2贴图模块:该模块是为了读取bmp位图设计的,主要代码写在CDib类里面,再通过view类和Doc类去调用显示位图,这个模块同样是

7、此次程序的重点模块之一,也是花费时间最多的一个模块,开始的时候,我使用了读取程序里面的位图资源,但是这样的办法虽然能够成功显示出位图,但是却十分麻烦,就是要先把想要显示的位图放到程序的位图资源里面,然后再通过LoadBitmap函数把位图资源加载到程序再显示出来。这样对使用都来说是非常不合理的,但是我却从这里懂得了一个显示位图的思路,要显示一幅位图需要有以下几点:(1) 读取bmp位图信息,bmp位图的信息包括:位图文件头BITMAPFILEHEADER和位图信息头BITMAPINFOHEADER,还有就是颜色表RGBOUAD。最后一部分是实际的位图数据IMAGEDATA。(2) 创建兼容DC

8、,这和相对比较容易,通过CreateCompatibleDC函数创建。(3) 将位图选入兼容DC中,也就是先把位图存到内存之中,通过SelectObject函数实现。(4) 将兼容DC中的位图贴到当前DC中,也就是显示在屏幕上,通过BitBlt或者StretchBlt这两个函数都可以实现,区别在于,前者不可以自动压缩图片在一个窗口显示全部的图片内容,而后者可以。后来我在另一本书上看到了其它的方法,也了解了DDB(设备相关图)和DIB(设备无关图),DDB位图的格式相当依赖于设备,所以它不适用于图像的交换,所以,大部分的BMP位图都会包含DIB。为了完成位图的显示,需要完成:装载位图、获取位图文

9、件头信息、获取位图信息、获取颜色表信息、获取做准备数据信息、获取位图尺寸、获取颜色总数、获取颜色位数、创建位图调色板、绘制位图等等。但是windows并没有提供DIB操作的类,需要自己动手写一个CDib的类,虽然这个类网上有可以直接复制,但是我还是按照书本那里,自己跟着课本的思路,手动把代码写上去,所以花费的时间比较多,即使是这样,有一些还是没有完全理解。封装好CDib类之后,再在View类和Doc类中写上相应的调用函数。便可以在程序中通过“打开”从磁盘中读取bmp位图了。设计思路基本上和上面的步骤一样。此时还需要面临另外一个问题,就是窗口的重绘。此功能已在功能分析上有说明,就是利用双缓冲解决

10、这个问题。3.3窗口模块:这部分大多数都是编译器自动生成,只做了一些修改,例如:使程序一开始运行便最大话,还是自定义程序的标题。刚开始做的时候,创建成单文档的了,后来需要用到多文档的,然后又不想再重新做过,所以只能手动修改,把单文档改成了多文档的。新建一个多文档的程序,然后用旧的那个单文档对照着多文档的源代码,一个个类的修改。3.4菜单模块:该部分同样大部分都是编译器自动生成的,自己增添了一部分菜单例如:绘图工具、颜色设置、线条设置等等。还有右键弹出菜单,有新建窗口、颜色及线条设置、退出程序等等,让使用者可以进行快速的操作。3.5工具栏与状态栏模块:除了编译器自动生成的之外,还加入了画直线、矩

11、形、椭圆、铅笔等工具的快速选择,状态栏可以显示鼠标移动的坐标。该部分让我觉得有点难度的就是那些工具栏那些图标,我画了很久才画出那个铅笔的图标,听说可以从磁盘里加载这些图标的,但是我不知道怎么要怎么做。4、类的设计与分析4.1、CAboutDlg类 由编译器生成,只做了两处的修改:m_pMainWnd->SetWindowText(_T("简单绘图工具");/设定主框架窗口标题pMainFrame->ShowWindow(SW_MAXIMIZE);/显示主框架窗口默认最大化4.2、CChildFrame类 由编译器生成,只做了一处的修改:cs.style |= W

12、S_VISIBLE|WS_MAXIMIZE;/使子窗口一打开就是最大化4.3、CDib类按照书本上的代码进行封装,以下是各成员函数和数据成员表1 CDib类说明表名称属性说明lpbminfo数据成员指向BITMAPINFO结构的指针lpbmihrd数据成员指向BITMAPINFOHEADER结构的指针bmfHeader 数据成员BITMAPFILEHEADER结构lpdib数据成员指向DIB的指针lpDIBBits数据成员DIB像素指针dwDIBSize数据成员DIB大小m_hDib数据成员DIB对象的句柄*lpRgbQuag数据成员指向颜色表的指针DrawDib()成员函数显示位图Const

13、ructPalette()成员函数构造逻辑调色板GetBits()成员函数取得位图数据的入口地址GetWidth()成员函数取得位图的宽度GetHeight()成员函数取得位图的高度GetPalSize()成员函数取得调色板的大小GetColorNum()成员函数取得位图包含的颜色数目GetBitCount()成员函数取得位图的颜色深度CopyHandle()成员函数用于复制位图对象LoadFile()成员函数从文件中加载位图GetRectWidth()成员函数取得区域的宽度GetRectHeight()成员函数取得区域的高度GetReqByteWidth()成员函数转换后的字节数ClearM

14、emory()成员函数清除内存中的DCInitMembers()成员函数初始化成员变量4.4、CDrawingDoc类由编译器生成,添加不少内容:因为显示bmp位图时,有一部分操作需要在这里进行,首先在头文件中添加了以下:public:HGLOBAL GetHObject() const return m_hDIB; /获取DIB对象的句柄CPalette *GetDocPal() const return m_palDIB; /获取调色板指针CSize GetDocDimension() const return m_sizeDoc; /获取调色板大小void UpdateObject(HG

15、LOBAL hDIB); /更新DIB对象void SetDib(); /初始化DIB对象protected:HGLOBAL m_hDIB;/定义指向DIB的句柄变量CPalette *m_palDIB;/定义指向逻辑调色板的指针CSize m_sizeDoc;/文档大小的变量4.5、CDrawingView类编译器自动生成的类,全部的画图操作都在此类中完成,包括bmp位图的显示也是在该类中通过调CDib类中的函数来完成的。表1 CDrawingView类说明表名称属性说明m_Shape数据成员用于选择图形的类型(直线,矩形,椭圆,铅笔)m_MouseDown数据成员用于判断鼠标按下的消息响应

16、m_LineEnd数据成员画图的终点m_LineOrg数据成员画图的起点m_Mousex数据成员状态栏x坐标m_Mousey数据成员状态栏y坐标m_clr数据成员画笔颜色选择m_nLineWidth数据成员指向颜色表的指针onece数据成员判断窗口变化时,避免m_dcCompatible的多次创建m_dcCompatible数据成员建立与屏幕显示兼容的内存显示设备OnContextMenu()成员函数右键弹出菜单OnDraw()成员函数屏幕显示bmp位图内容 和窗口重绘OnEditColor()成员函数颜色选择OnLine()成员函数画直线OnRectangle()成员函数画矩形OnEllip

17、se()成员函数画椭圆OnPencil()成员函数铅笔工具OnLButtonDown()成员函数鼠标按下响应函数OnLButtonUp()成员函数鼠标弹起响应函数OnMouseMove()成员函数鼠标移动响应函数OnUpdateX()成员函数状态栏x坐标显示与更新OnUpdateY()成员函数状态栏y坐标显示与更新OnEraseBkgnd()成员函数窗口重画OnInitialUpdate()成员函数初始化pView指针值OnSetting()成员函数画笔设置对话框响应函数SaveAsBmp()成员函数把所画的图保存为bmp文件OnFileSaveAs()成员函数另存为.消息响应函数4.6、CM

18、ainFrame类主要同编译器生成,修改小部分:static UINT indicators =ID_SEPARATOR, / status line indicatorID_INDICATOR_CAPS,ID_INDICATOR_NUM,ID_INDICATOR_SCRL,ID_X,ID_Y; ID_X,ID_Y是状态栏中的x和y坐标. cs.style&=FWS_ADDTOTITLE; /使主窗口的标题不发生变化4.7、CSettingDlg类由自己创建,主要是响应菜单中的各个设置选项,该类实现的功能比较少。表1 CSettingDlg类说明表名称属性说明m_nLineWidth数

19、据成员记录线的粗细m_nLineStyle数据成员记录线条的类型OnChangeLineWidth()成员函数编辑框控件(IDC_LINE_WIDTH)的响应函数OnRadio1()成员函数选择画实线OnRadio2()成员函数选择画虚线OnRadio3()成员函数选择画点线OnPaint()成员函数在示例中显示所需要的线型5、特色算法分析在函数或成员方法里找出你认为比较有特色的12个算法。5.1 CDib类中的显示bmp位图 流程图:流程图1:设备无关位图的读取 流程图2:设备无关图的显示流程程序运行获取文件绝对路径名打开文件分析文件头结构文件是否为bmp文件?获取位图大小、分配内存读取信息

20、头结构根据得到的信息判断像素起始地址程序结束恢复旧的调色板程序运行从文档获取位图数据指针从数据指针获取位图高宽等必要信息判断是否带有颜色表?从颜色表创建逻辑调色板选中新建的逻辑调色板,同时保留旧的调色板根据相应参数调用WinAPI,显示位图程序结束根据相应参数调用WinAPI,显示储备NNY Y 代码: 功能:在磁盘中读取一幅bmp位图,然后显示到屏幕上。 算法思路:首先理解bmp位图里面所包含的信息然后再以下步骤实现:<1>读取bmp位图信息,bmp位图的信息包括:位图文件头BITMAPFILEHEADER和位图信息头BITMAPINFOHEADER,还有就是颜色表RGBOUAD

21、。最后一部分是实际的位图数据IMAGEDATA。<2>创建兼容DC,这和相对比较容易,通过CreateCompatibleDC函数创建。<3>将位图选入兼容DC中,也就是先把位图存到内存之中,通过SelectObject函数实现。<4>将兼容DC中的位图贴到当前DC中,也就是显示在屏幕上,通过BitBlt或者StretchBlt这两个函数都可以实现,区别在于,前者不可以自动压缩图片在一个窗口显示全部的图片内容,而后者可以自动压缩和拉伸图片让它布满整个客户区。加载位图信息代码:HGLOBAL CDib:LoadFile(CFile &file)/将指定

22、的文件中的DIB对象读到指定的内存区域中DWORD dwFileSize;dwFileSize=file.GetLength();/获取文件大小if (file.Read(LPSTR)&bmfHeader,sizeof(bmfHeader)!=sizeof(bmfHeader)/读取文件头return NULL; /大小不一致,返回NULLif (bmfHeader.bfType!=DIB_MARKER)/判断是否是DIB对象return NULL;m_hDib=(HGLOBAL):GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,dwFileSize

23、-sizeof(BITMAPFILEHEADER);/分配DIB内存if (m_hDib=0)return NULL; /给CDib类的成员变量赋值lpdib=(LPSTR):GlobalLock(HGLOBAL)m_hDib);/锁定lpbminfo=(BITMAPINFO*)lpdib;lpbmihrd=(BITMAPINFOHEADER*)lpdib;lpRgbQuag=(RGBQUAD*)(lpdib+lpbmihrd->biSize);int m_numberOfColors=GetColorNum(LPSTR)lpbmihrd);if (lpbmihrd->biClrU

24、sed=0)lpbmihrd->biClrUsed=m_numberOfColors;DWORD colorTableSize=m_numberOfColors*sizeof(RGBQUAD);lpDIBBits=lpdib+lpbmihrd->biSize+colorTableSize;if(file.ReadHuge(lpdib,dwFileSize-sizeof(BITMAPFILEHEADER)!=dwFileSize-sizeof(BITMAPFILEHEADER)/读像素,大小不一致时:GlobalUnlock(HGLOBAL)m_hDib);/解除锁定:GlobalF

25、ree(HGLOBAL)m_hDib);/释放内存return NULL;:GlobalUnlock(HGLOBAL)m_hDib);/解除锁定return m_hDib;/返回DIB句柄显示位图部分函数代码:BOOL CDib:DrawDib(HDC hDC,LPRECT lpDCRect,HGLOBAL hDIB,LPRECT lpDIBRect,CPalette *pPal) /绘制DIB对象BOOL bSuccess=FALSE;/重画成功标志HPALETTE hOldPal=NULL;/以前的调色板if(hDIB=NULL)/判断是否是有效的DIB对象return FALSE;/不是

26、,则返回lpdib=(LPSTR):GlobalLock(hDIB);/锁定DIBlpDIBBits=GetBits(lpdib);/找到DIB图像像素起始位置if(pPal!=NULL)/获取调色板,并选取到设备环境中HPALETTE hPal=(HPALETTE)pPal->m_hObject;hOldPal=:SelectPalette(hDC,hPal,TRUE);:SetStretchBltMode(hDC,COLORONCOLOR); /设置显示模式bSuccess=:StretchDIBits(hDC,lpDCRect->left,lpDCRect->top,G

27、etRectWidth(lpDCRect),GetRectHeight(lpDCRect), /目标文件信息lpDIBRect->left,lpDIBRect->top,GetRectWidth(lpDIBRect),GetRectHeight(lpDIBRect), /源文件信息lpDIBBits,(LPBITMAPINFO)lpdib,DIB_RGB_COLORS,SRCCOPY); /指向DIB像素指针,指向位图信息结构指针,使用颜色数目,光栅操作类型:GlobalUnlock(hDIB);if(hOldPal=NULL):SelectPalette(hDC,hOldPal,

28、TRUE);return bSuccess;5.2 CDrawingView类中的画图部分 功能:在客户区中实现画直线、矩形、椭圆、任意曲线。画完之后可以保存为bmp格式的文件。 算法思路:在View类中创建画笔,然后通过调用各个函数去画不同的形状在画图方面,我写了4个函数, OnLine()、OnRectangle()、OnEllipse()、OnPencil()。OnLine()函数:SetClassLong(this->GetSafeHwnd(),GCL_HCURSOR,(LONG)LoadCursor(NULL,IDC_CROSS);DC.LineTo(m_LineEnd);DC

29、.MoveTo(m_LineOrg);m_LineEnd=point;DC.LineTo(m_LineEnd);OnRectangle()函数:DC.SelectStockObject(HOLLOW_BRUSH);DC.Rectangle(m_LineOrg.x,m_LineOrg.y,m_LineEnd.x,m_LineEnd.y);DC.MoveTo(m_LineOrg);m_LineEnd=point;DC.Rectangle(m_LineOrg.x,m_LineOrg.y,m_LineEnd.x,m_LineEnd.y);OnEllipse()函数:DC.SelectStockObje

30、ct(HOLLOW_BRUSH);DC.Ellipse(m_LineOrg.x,m_LineOrg.y,m_LineEnd.x,m_LineEnd.y);DC.MoveTo(m_LineOrg);m_LineEnd=point;DC.Ellipse(m_LineOrg.x,m_LineOrg.y,m_LineEnd.x,m_LineEnd.y);OnPencil()函数:DC.SetROP2(R2_COPYPEN); /保证重叠的线不会变化,使画出来的线条始终为黑色DC.MoveTo(m_LineOrg);DC.LineTo(point);m_LineOrg=point;(注:这些代码不是写在

31、OnLine()、OnRectangle()、OnEllipse()、OnPencil()这4个函数中,而是写在OnLButtonUp()和OnMouseMove()中)分别把以上的四个功能的代码同时写在OnLButtonUp()和OnMouseMove()中,因为如果只写在OnLButtonUp()里面的话,画线条时在鼠标移动中线条不会立刻显示,要等鼠标左键弹起之后才显示画出来,同时在OnMouseMove()便可以解决这个问题,但是如果只在OnMouseMove()写这些函数的话,当两次把线条画在同一个地方时,原来的线条会消失,所以必须把这四个功能同时写在这两个函数之中,才可以顺利实现我想

32、要的效果。 流程图:程序运行选择哪个画图工具调用OnMouseMove()鼠标左键按下在屏幕显示所画线条调用OnLButtonUp()再画一次鼠标左键弹起画图结束画画 画铅直矩 椭 笔线形 圆6、功能测试图6-1 多窗口测试图图6-2 画直线测试图图6-3 画矩形测试图图6-4 画椭圆测试图图6-5 铅笔工具测试图图6-6 颜色设置测试图图6-7 读取位图测试图7、存在的不足与对策本次课程设计,是第一次使用面向对象语言做的程序,以前一直都是在win32下的编程,在这种界面化的编程环境中,感觉到了面向对象语言的实用性,和win32下的那种感觉是完全不同的。由于是第一次使用mfc做相对大一点的程序

33、,之前课本只有介绍过几个很简单的mfc程序,所以当时学得并不多,不过通过这次的课程设计,对mfc的使用熟悉了很多,同时也发现了自己c+语言基础很不牢固,在类与类之间的函数调用非常不熟悉,还有指针的使用也不熟悉,而且在做程序之前并没有好好的规划,造成很多的函数和成员变量都写在了View类之中,对于排错和修得bug造成了极大的不便,有时候一个小错误都需要找很久才能找到,直到现在也依然有一些bug还没有修复的。不过程序整体上已经没有太大的问题了。这次课程设计里面花时间最多的还是对CDib类的封装,虽然可以有书本对照着,但是依然有很多地方没理解的,为了让程序可以从磁盘中读取bmp文件和显示到屏幕上,我先后看了两篇CDib类的源代码,才开始动手封装的,在此之前还要去理解bmp文件所包含的信息,bmp位图的信息包括:位图文件头BITMAPFILEHEADER和位图信息头BITMAPINFOHEADER,还有就是颜色表RGBOUAD。最后一部分是实际的位图数据IMAGEDATA。中有理解了这些之后才有可能会理解CDib类的封装。封装完之后,还要将它导入到我的工程文件夹之中然后还要在View类和Doc类之中添加相应的代码,才能实现从有磁盘中读取bmp位图。到后来我才发现该CDib类中的,保存位图是不起作用的,每

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论