当前位置:文档之家› C++课设:简单画图程序

C++课设:简单画图程序

简单画图程序1.基本功能描述本次课程设计的任务是利用计算机和VC开发环境编写一个简单画图程序,该程序的设计指标(即主要功能)有:①用鼠标拖动绘制圆、椭圆、矩形,线等基本图形;②能控制画笔的线宽和颜色;③能对图形进行颜色填充;④在鼠标移动的过程中能实时显示当前绘制的图形。

除了以上几点功能,我有另外添加了工具栏、铅笔、橡皮等功能来使程序更方便地让用户使用,简化了人机交互的过程。

2.设计思路首先是界面的问题,既然课设的题目是简单画图,那在建立工程的时候就要选择文档结构而不是以前做的基于对话框。

可选择单文档结构或多文档结构,但想到画图界面一般只有一个,从简洁的角度考虑,选择单文档结构。

而且用户界面在设计的时候要尽可能简单美观,一目了然,对相应功能有图标提示,使用户方便使用。

然后便是画图功能的具体实现。

分析课设要求,可以发现功能一要求的的椭圆、矩形、直线可以分别通过Ellipse();、Rectangle();、MoveTo();、LineTo();这四个函数来实现。

功能二控制画笔线宽和颜色可以给二者分别关联参数,通过改变线宽参数值来控制线宽,通过调用通用对话框改变颜色参数值来控制颜色。

功能三对图形进行颜色填充虽以前未接触过,但查阅资料后发现可以调用ExtFloodFill();并合理设定参数值来实现。

功能四的实时显示功能可以通过调用MouseMove();函数来实现。

这些功能需要建立菜单资源来表示各个功能选项,并建立相应的消息响应函数来进行实现。

另外,画图程序主要是通过鼠标来进行操作,所以要对鼠标消息的响应及处理函数多下功夫来思考和编写。

至于额外添加的功能,工具栏通过添加工具栏资源和关联相应菜单中画图功能ID实现;铅笔、橡皮的功能则是利用MouseMove();函数,在其中做了一些改动来实现。

图1 程序流程图MouseMove 函数鼠标左键弹起响应函数m_ptOldOrigin=point;2.1.程序流程图:开始 变量初始化(m_nDrawType ,m_clr 等)铅笔橡皮点直线椭圆线宽线型设置颜色选择填充响应函数 m_Pen(m_Eraser)=TRUE并将其他橡皮(铅笔)、填充等所关联变量置为FALSE.响应函数 m_nDrawType =1/2/3/4;对应点、直线、矩形、椭圆矩形响应函数 创建相应对话框IDOK==1?更改变量m_clr (m_nLineWidth ,m_nLineStyle)参数值响应函数 m_Fill=TRUE 并将其他橡皮、铅笔等所关联变量置为FALSE.鼠标左键按下 响应函数m_ptNewOrigin=point; 进行填充铅笔功能橡皮功能画点画直线画矩形画椭圆结束判断各参数值以确定功能3.软件设计3.1.设计步骤1)打开VS2010,选择新建项目,选中MFC应用程序,标题为CWN_Graphic;2)选择单文档结构,其他为默认值,点击完成。

3.2 .界面设计3.2.1.添加菜单1)选择资源视图,鼠标右键,添加,资源;2)在资源视图中打开添加的菜单资源,将各个功能的名称添加进去并合理安排,并设置好相应的ID,如图2:图2编辑菜单及相应ID3.2.2 .添加工具栏1)在资源视图下右键选择添加资源,ToolBar;2)打开新建的工具栏,在上面添加各个小按钮,按钮图像自行画出;3)将每个按钮的ID与菜单项一一对应起来,如图3:图3工具栏样式及ID3.3.关键功能实现1)打开类向导;2)为各个菜单项添加消息函数,如图4:图4 添加消息函数相关ID、关联变量及响应函数如表1:表1相关功能ID 及所关联变量名称ID 关联变量响应函数点IDM_DOT m_nDrawType = 1 OnDot()直线IDM_LINE m_nDrawType = 2 OnLine()矩形IDM_RECTANGLE m_nDrawType = 3 OnRectangle()椭圆IDM_ELLIPSE m_nDrawType = 4 OnEllipse()画笔IDM_PEN m_Pen = TRUE OnPen()填充IDM_FILL m_Fill = TRUE OnFill()橡皮(小)IDM_ERASER1 - OnEraser1()橡皮(中)IDM_ERASER2 - OnEraser2()橡皮(大)IDM_ERASER3 - OnEraser3()线宽+线型IDM_LINE_WIDTH - OnLineWidth()颜色IDM_Color - OnColor()3)按照所需在CWN_GraphicView.h中添加变量并在CWN_GraphicView.cpp中对变量初始化:UINT m_nDrawType = 0;//绘画类型初始为0CPoint m_ptOldOrigin = 0;//坐标点初始为(0,0)CPoint m_ptNewOrigin = 0;UINT m_nLineWidth = 0;//线宽初始为0UINT m_EraserWidth = 1;//橡皮初始大小为1INT m_nLineStyle = 0;//线宽初始为0BOOL m_Pen = FALSE;//画笔功能未被选中BOOL m_Eraser = FALSE;//橡皮功能未被选中BOOL m_LButtonDown = FALSE;//鼠标左键未按下BOOL m_Fill = FALSE;//填充功能未被选中COLORREF m_clr = RGB(0,0,0);//颜色初始值为黑色4)在各响应函数中添加相应代码,例如:/**********左键按下************//*该函数实现了再鼠标左键按下时确定按下点的坐标、将左键被按下置为1和判断是否填充选项被选中,若选中则进行填充,未选中则无操作*/void CCWN_GraphicView::OnLButtonDown(UINT nFlags , CPoint point){m_ptNewOrigin=point; //将当前点坐标传给变量m_ptOldOrigin=point;m_LButtonDown=TRUE; //左键按下赋值1if(m_Fill==TRUE) //填充功能{CClientDC dc(this);HBRUSH hBrush=CreateSolidBrush(m_clr); //选择画刷dc.SelectObject(hBrush);dc.ExtFloodFill (m_ptNewOrigin.x,m_ptNewOrigin.y,RGB(0,0,0),0);//该函数将使用当前刷子填充显示表面区域}CView::OnLButtonDown(nFlags,point);}/***********左键松开************//*该函数通过在鼠标左键松开时,将松开点坐标传给PC,并由之前选择的绘画类型来判断要进行的绘画操作*/void CCWN_GraphicView::OnLButtonUp(UINT nFlags , CPoint point){m_LButtonDown=FALSE; //左键松开赋值0CClientDC dc(this);CPen pen(m_nLineStyle,m_nLineWidth,m_clr); //创建画笔画刷dc.SelectObject (&pen); //选择画笔CBrush*pBrush=CBrush::FromHandle ((HBRUSH)GetStockObject(NULL_BRUSH));dc.SelectObject (pBrush); //选择画刷m_ptNewOrigin=point; //左键松开的坐标点送给m_ptNewOriginswitch(m_nDrawType){case 1:/*******画点*******/dc.SetPixel(point,m_clr);break;case 2:/*******画线*********/dc.MoveTo (m_ptOldOrigin);dc.LineTo (m_ptNewOrigin);break;case 3:/**********画矩形**********/dc.Rectangle (CRect(m_ptOldOrigin,m_ptNewOrigin));break;case 4:/*********画椭圆**********/dc.Ellipse (CRect(m_ptOldOrigin,m_ptNewOrigin));break;}CView::OnLButtonUp (nFlags,point);}/*************线型+线宽设置*********//*该函数在线型线宽功能被选择时,会生成一个线型线宽设置对话框(之前在资源中添加和编辑的对话框资源),并将用户操作后的线型线宽值传给PC*/void CCWN_GraphicView::OnLineWidth(){// TODO: 在此添加命令处理程序代码CSettingDlg line_dlg;line_dlg.m_nLineWidth = m_nLineWidth ; //将先前设置的线宽回传给对话框line_dlg.m_nLineStyle = m_nLineStyle; //将先前设置的线型回传给对话框if(IDOK==line_dlg.DoModal ()){m_nLineWidth=line_dlg.m_nLineWidth ;m_nLineStyle = line_dlg.m_nLineStyle ;}}/*************动态显示函数******************//*该函数单独写出,配合OnMouseMove();函数可实现动态显示的功能*/void CCWN_GraphicView::Draw(){CClientDC dc(this);CPen pen(m_nLineStyle,m_nLineWidth,m_clr);CPen *oldPen=dc.SelectObject(&pen);dc.SelectStockObject(NULL_BRUSH);int drawmode=dc.SetROP2(R2_NOTXORPEN);/*R2_NOTXORPEN模式的作用是:先把画笔的颜色取反,再与屏幕颜色进行“或”操作,从而得到像素最终显示的颜色。

*/switch(m_nDrawType){case 2:dc.MoveTo(m_ptOldOrigin);dc.LineTo(m_ptNewOrigin);break;case 3:dc.Rectangle(CRect(m_ptOldOrigin,m_ptNewOrigin));break;case 4:dc.Ellipse(CRect(m_ptOldOrigin,m_ptNewOrigin));break;}dc.SetROP2(drawmode);dc.SelectObject(oldPen);}/*************MOUSE MOVE***************//*此函数与前面的动态显示函数(Draw();)进行配合便可实现在鼠标移动时的实时显示功能,思路是在绘图时,先用屏幕背景色覆盖掉鼠标移动前的画面,然后用选定的画笔颜色重新绘制下一次鼠标移动的画面*/void CCWN_GraphicView::OnMouseMove(UINT nFlags, CPoint point){// TODO: 在此添加消息处理程序代码和/或调用默认值CClientDC dc(this);CPen pen(m_nLineStyle,m_nLineWidth,m_clr);CPen *oldPen=dc.SelectObject(&pen);if(m_LButtonDown!=FALSE){Draw();m_ptNewOrigin=point;Draw();if(m_Pen==TRUE) //铅笔功能{m_nDrawType=0; //画图类型改为初始值,以免多重画图dc.MoveTo (m_ptOldOrigin);dc.LineTo (m_ptNewOrigin);//修改线段起点m_ptOldOrigin=m_ptNewOrigin;m_ptNewOrigin=point;}if(m_Eraser==TRUE) //橡皮功能{m_nDrawType=0;CPen pen(m_nLineStyle,m_EraserWidth,RGB(255,255,255));dc.SelectObject(&pen);dc.MoveTo (m_ptOldOrigin);dc.LineTo (m_ptNewOrigin);//修改线段起点m_ptOldOrigin=m_ptNewOrigin;m_ptNewOrigin=point;}}dc.SelectObject(oldPen);CView::OnMouseMove(nFlags, point);}/************选择铅笔**************//*该函数在选择铅笔功能后,将铅笔功能置为真,其他有干扰的功能置为假*/void CCWN_GraphicView::OnPen(){// TODO: 在此添加命令处理程序代码m_Pen = TRUE; //画笔被选中m_Fill = FALSE; //取消填充功能m_Eraser = FALSE; //取消橡皮功能}4.结论与心得体会本次课程设计虽说是“简单”画图程序的设计,但真要是自己做起来,感觉一点也不简单。

相关主题