mfc简单绘图程序_第1页
mfc简单绘图程序_第2页
mfc简单绘图程序_第3页
mfc简单绘图程序_第4页
mfc简单绘图程序_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

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

文档简介

...wd......wd......wd...MFC简单的绘图程序——目录摘要2关键字2TOC\o"1-3"\u1引言2设计目的32功能说明22.1菜单栏32.1.1图形32.1.2画笔42.1.3画硬币42.2工具栏52.3状态栏53功能的实现53.1视图设计53.2编辑资源63.3编程思路及各个函数的实现7(1)思路7(2)代码的实现71.为根本形状创立一个基类82.根本形状类的创立82.1矩形类的创立及定义82.2圆形类的创立及定义102.3正五边形类的创立及定义112.4正三角形类的创立及定义142.5椭圆类的创立及定义162.6正四边形类的创立及的定义172.7正六边形类的创立及定义182.8直线类的创立及定义193.各根本形状类在CMyDraw2_0类中的调用和绘图的实现203.1矩形类的调用与与绘图的实现203.2圆形类的调用243.3正三角形类的调用253.4根本类型调用的剩余代码264.画笔的使用、颜色及大小的调整295.画硬币356.工具栏中的自定义控件387.状态栏中的显示394程序功能的测试415最后总结42摘要:本绘图程序能够进展根本图形的绘画,如直线,圆,矩形,三角形等等,并且在此根基上添加了多边形的绘画,如正五边形等。除此之外,还能够进展随手画,即用鼠标随意画线条。为了更好的绘图,还添加了对画笔粗细的调整,以及对画笔颜色的调整,除了特定的颜色,颜色还可根据输入的RGB值随意更改。还有一些教师的要求,参加了画硬币、显示硬币数目即鼠标坐标等信息。本程序主要采用面向对象写法。关键字:程序设计,MFC,绘图引言设计目的本绘图程序的设计不仅仅局限于教师课堂的要求,通过C++的编写实现绘图要求,我还想要在此根基上,参加自己的一些想法,想要更好地了解MFC,更好地去实现自己的想法。功能说明2.1菜单栏2.1.1图形图形栏中包括直线、矩形、圆形、椭圆、多边形,多边形中包括正三角形、正四边形、正五边形、正六边形。①选择直线,可用鼠标拖动画出一条直线②选择矩形,可用鼠标拖动画出矩形③选择圆形,可用鼠标拖动画出圆形④选择椭圆,可用鼠标拖动画出椭圆⑤选择正三角形,可用鼠标拖动画出正三角形⑥选择正四边形,可用鼠标拖动画出正方形⑦选择正五边形,可用鼠标拖动画出正五边形⑧选择正六边形,可用鼠标拖动画出正六边形(注:为了验证自己的想法以及想让画出的图形随意地变换方向,特意在正三角形一项中参加了旋转效果,使鼠标在拖动时能旋转三角形)2.1.2画笔画笔栏中包括颜色、大小及铅笔(1)颜色颜色中包括黑色、红色、绿色、蓝色、橙色、黄色、青色、紫色、粉色、自定义①选择黑色,画出的图形将为黑色②选择红色,画出的图形将为红色③选择绿色,画出的图形将为绿色④选择橙色,画出的图形将为橙色⑤选择黄色,画出的图形将为黄色⑥选择青色,画出的图形将为青色⑦选择紫色,画出的图形将为紫色⑧选择粉色,画出的图形将为粉色⑨选择自定义,可输入RGB值,画出的图形将显示输入的颜色(2)大小大小中包括1、2、3、4、5、6、7①选择1,画笔大小设为1②选择2,画笔大小设为2③选择3,画笔大小设为3④选择4,画笔大小设为4⑤选择5,画笔大小设为5⑥选择6,画笔大小设为6⑦选择7,画笔大小设为7(3)铅笔选中铅笔后,将可以用鼠标进展随意画线2.1.3画硬币画硬币中包括画、增加、减少、去除①选择画,将在客户端窗口中画出初始数量为10的硬币②选择增加,窗口中的硬币数目将增加1个③选择减少,窗口中的硬币数目将减少1个④选择去除,刷新窗口,将硬币消去2.2工具栏工具栏中除了原有的图标外,还参加了自定义的图标①选择,可用鼠标拖动画出一条直线②选择,可用鼠标拖动画出矩形③选择,可用鼠标拖动画出圆形④选择,可用鼠标拖动画出正三角形⑤选择,可用鼠标进展随手画⑥选择,可在窗口画出硬币后,将硬币数量+1⑦选择,可在窗口画出硬币后,将硬币数量-1⑧选择,可利用鼠标对所绘图形进展擦除,橡皮擦的大小与画笔大小一样2.3状态栏状态栏中除了原有的显示外,还参加了硬币的数量以及鼠标的x坐标和y坐标功能的实现3.1视图设计利用MFC生成画图应用程序框架具体步骤如下:(1)执行VC程序,选择File|New命令,弹出New对话框.单击Projects标签,转到Projects选项卡,选择MFCAppWizard(exe)选项,然后在Projectname文本框中输入MyDraw2_0〔原来也做过一个,不过并没有以面向对象的写法去写,这个就当作是我的第二个版本),文本框是指工程的本地路径。(2)由于本程序是实现画线,要在视图中完成,所以首先创立一个基于单文档的应用程序3.2编辑资源利用ResourceView中的Menu编辑器在菜单栏添加菜单,该流程图如下3.2所示:图3.2利用ResourceView中的ToolBar编辑器,在工具栏中添加自定义控件。控件图案如下所示:3.3编程思路及各个函数的实现(1)思路:首先,画定义好的形状。直线、矩形、圆形等等都属于根本的形状,那么我设定一个基类,称它为CShape,给这个基类定义一个画画的虚函数Draw(CDC*pDC),在这个类里面派生出各个需要的类,如CCircle类,并为这些派生类定义各自的属性及方法,重写基类的Draw函数。当我需要用到这些类的时候,只需要在View类里创立指针,然后调用里面Draw方法。由于是当鼠标拖动的时候画出所需的图形,需要添加鼠标响应函数,onLButtonDown(),onLButtonUp,以及onMouseMove()。画画主要是在onMouseMove()里实现。接着,是画笔的颜色和大小,本来是想单独创立一个画笔类,定义颜色和大小属性,使CCircle等派生类多继承,在继承一个画笔类,但尝试了几遍,发现在菜单里选择颜色时就会使程序停顿运行,于是就放弃了。重新构思之后,由于画图是在CMyDraw2_0里实现的,就直接在CMyDraw2_0中定义了颜色和大小的变量,这样也方便。然后是画硬币。并没有为这个创立单独的类,直接在CMyDraw2_0中的OnDraw()中画硬币,并且在CMyDraw2_0中添加了增加和减少硬币的方法。工具栏中只要和为各个图标添加函数,作用和菜单栏中的图形一栏中对应即可。最后还有硬币的数量和鼠标坐标放在状态栏中显示,下面开场进展函数代码的实现。代码的实现:为根本形状创立一个基类,命名为CShape。在ClassViewz中右键点击MyDraw2_0classes->newclass,在弹出窗口的顶部下拉框中选择GenericClass,如以下列图在头文件中添加虚函数Draw(CDC*pDC)public: CShape(); virtualDraw(CDC*pDc)=0;//添加的虚函数 virtual~CShape();根本形状类的创立(注:以矩形、圆形、正五边形、正三边形为重点介绍〕 2.1矩形类的创立及定义创立一个矩形类,继承CShape类,如图在该类中重新定义画画函数Draw(),并添加带参数的构造函数,矩形的左上角,以及矩形的宽度和高度,代码如下:Public:CRectangle(); Draw(CDC*pDC);//重新定义Draw函数 CPointpoint_LeftUp;//矩形的左上角坐标 CRectangle(intx,inty,intw=0,inth=0);//带参数的构造函数,x表示左上角的横坐标,y表示左上角的纵坐标 intwidth;//矩形的宽度 intheight;//矩形的高度 virtual~CRectangle();在无参数构造函数中初始化point_LeftUp的坐标和宽度以及高度的值,代码如下:CRectangle::CRectangle(){point_LeftUp.x=0;//左上角坐标x值设置为0point_LeftUp.y=0;//左上角坐标x值设置为0width=0;//矩形的宽度初始为0height=0;//矩形的高度初始为0}在带参数的构造函数中将值赋给point_LeftUp和宽度以及高度,代码如下: point_LeftUp.x=x;//将传入的x值赋给左上角坐标的x值 point_LeftUp.y=y;//将传入的y值赋给左上角坐标的y值 width=w; //将传入的w值赋给width height=h; //将传入的h值赋给height重写Draw(CDC*pDC)函数,代码如下:CRectangle::Draw(CDC*pDC){ pDC->Rectangle(point_LeftUp.x,point_LeftUp.y,point_LeftUp.x+width, point_LeftUp.y+height);//利用Rectangle()函数画出矩形,其中的值分别为矩形的左上角横坐标, 左上角纵坐标,右下角横坐标,右下角纵坐标}在CMyDraw2_0View中引入矩形类的头文件:双击CMyDraw2_0View,在代码//MyDraw2_0View.h:interfaceoftheCMyDraw2_0Viewclass///////////////////////////////////////////////////////////////////////////////#if!defined(AFX_MYDRAW2_0VIEW_H__3809529C_6744_4AD2_80A4 _D44683D0A5AF__INCLUDED_)#define AFX_MYDRAW2_0VIEW_H__3809529C_6744_4AD2_80A4_D44683D0 A5AF__INCLUDED_下添加如下代码:#include"Rectangle.h"并在View类中添加私有成员变量,创立矩形类的指针:右键点击CMyDraw2_0View,选择AddMemberVariable,在弹出的对话框中如下输入:将在CMyDraw2_0View头文件中出现如下代码Private:CRectangle*rectangle;//定义指向矩形类的指针, 为私有变量2.2圆形类的创立及定义创立一个圆形类,命名为CCircle,继承CShape类,在该类中添加公有成员变量,代码如下:public: CCircle(); CCircle(intx,inty,intradius=0);//带参数的构造函数,其中,x表示圆心的x值,y表示圆心的y值,radius表示圆的半径 Draw(CDC*pDC);//重新定义Draw函数 virtual~CCircle(); intRadius;//定义圆的半径 CPointcenter_point;//定义圆的中心点在无参数的构造函数中初始化变量值,代码如下:CCircle::CCircle(){center_point.x=0;//圆心的横坐标初始为0center_point.y=0;//圆心的纵坐标初始为0Radius=0;//圆的半径初始为0}在带参数的构造函数中将传入的值赋给各变量,代码如下:CCircle::CCircle(intx,inty,intradius){ center_point.x=x;//将传入的x值赋给圆心的横坐标 center_point.y=y;//将传入的y值赋给圆心的纵坐标 Radius=radius;//将传入的radius值赋给圆的半径}重写定义的Draw函数,代码如下:CCircle::Draw(CDC*pDC){ pDC->Ellipse(center_point.x-Radius,center_point.y-Radius,center_p oint.x+Radius,center_point.y+Radius);//利用Ellipse()函数进展圆的绘制,其中的值分别为圆的外接正方形的左上角横坐标、纵坐标,右下角横坐标、纵坐标}在CMyDraw2_0View中引入圆形类的头文件:#include"Circle.h"添加私有成员变量,创立圆形类的指针变量:CCircle*circle;//创立圆形类的指针,可以直接写在矩形类只针对下方2.3正五边形类的创立及定义创立一个正五边形类,命名为CPentangle,继承CShape类,在该类中添加公有成员变量,代码如下:public: CPentangle(); CPentangle(intx,inty,intradius=0);//带参数的构造函数,x为外接圆圆心的横坐标,y为外接圆圆心的纵坐标,radius为外接圆的半径 intRadius;//定义外接圆半径 CPointcP;//定义外接圆圆心 Draw(CDC*pDC);//重新定义Draw函数 virtual~CPentangle();在无参数的构造函数中初始化各变量,代码如下:CPentangle::CPentangle(){cP.x=0;//圆心横坐标初始为0cP.y=0;//圆心纵坐标初始为0 Radius=0;//外接圆半径初始为0}在带参数的构造函数中将传入的值赋给各变量,代码如下:CPentangle::CPentangle(intx,inty,intradius){ cP.x=x;//将传入的x值赋给圆心的横坐标 cP.y=y;//将传入的y值赋给圆心的纵坐标 Radius=radius;//将传入的radius值赋给外接圆半径}下面重写的Draw函数与前两个不同,需要用到数学函数cos()以及sin(),由于两个函数用的是弧度制,还需引入数学变量PI,为了能够顺利的写入这些函数,需要在CPentangle类的客户端中引入数学类的头文件:双击ClassView中的CPentangle(),在出现的构造函数上方,在如下代码//Pentangle.cpp:implementationoftheCPentangleclass.////////////////////////////////////////////////////////////////////////#include"stdafx.h"#include"MyDraw2_0.h"#include"Pentangle.h"下添加数学类头文件:#include“math.h〞再定义一个宏变量PI,添加如下代码:#definePI3.1415926开场重写Draw(CDC*pDC)函数,代码如下:CPentangle::Draw(CDC*pDC){ doublerc=Radius*cos(36*PI/180);//将半径和36度的余弦值相乘并且赋给新的变量rc doublers=Radius*sin(36*PI/180);//将半径和36度的正弦值相乘并且赋给新的变量rs doubleRc=Radius*cos(18*PI/180);//将半径和18度的余弦值相乘并且赋给新的变量Rc doubleRs=Radius*sin(18*PI/180); //将半径和18度的正弦值相乘并且赋给新的变量Rs POINTpts[]={{cP.x+rs,cP.y+rc},{cP.x-rs,cP.y+rc},{cP.x-Rc,cP.y-Rs},{cP.x,cP.y-Radius},{cP.x+Rc,cP.y-Rs}};//利用点类的数组将五个点储存在点数组pts中pDC->Polygon(pts,5);//利用函数Polygon()进展多边形的绘画,其中pts为储存的点,5为点的个数}下面对Draw函数中各数据进展深层次的分析,说明它们的来历:如以下列图:以外接圆圆心为坐标轴中心,设该点的坐标为(cP.x,cP.y);则右下角的坐标为cP.x+R*sin(36*PI/180),cP.y+R*cos(36*PI/180)按顺时针方向看,接下去的几个点的坐标分别为cP.x-R*sin(36*PI/180),cP.y+R*cos(36*PI/180)cP.x-R*cos(18*PI/180),cP.y-R*sin(18*PI/180)cP.x,cP.y-RcP.x+R*cos(18*PI/180),cP.y-R*sin(18*PI/180)以上为正五边形5个点的来历,接下来在CMyDraw2_0View中引入正五边形类的头文件:#include“Pentangle.h〞添加一个私有变量,创立指向正五边形的指针变量:CPentangle*pentangle;2.4正三角形类的创立及定义(这个类中添加了旋转)创立一个正三角形类,命名为CDelta,继承CShape类,在该类中添加公有成员变量,代码如下:public: CDelta(); CDelta(intx,inty,intradius=0);//带参数的构造函数,其中x为外接圆圆心的横坐标,y为外接圆圆心的纵坐标,radius为外接圆半径 intRadius;//外接圆半径 CPointcp;//外接圆圆心 doubletheta;//在正三角形原图上旋转过的角度 doublest;//该变量储存的是sin(theta) doublect;//该变量储存的事cos(theta) Draw(CDC*pDC);重新定义Draw函数 virtual~CDelta();在无参数构造函数中初始化变量,代码如下:CDelta::CDelta(){cp.x=0;//圆心的横坐标初始为0cp.y=0;//圆心的纵坐标初始为0Radius=0;//外接圆半径初始为0}在带参数构造函数中将传入的值赋给各变量,代码如下:CDelta::CDelta(intx,inty,intradius){ cp.x=x;//将传入的x值赋给圆心的横坐标 cp.y=y;//将传入的y值赋给圆心的纵坐标 Radius=radius;//将传入的radius值赋给外接圆半径 ct=1;//调用该函数时将cos(theta)设置为1 st=0;//调用该函数时将sin(theta)设置为0}与正五边形一样,要引入数学类的头文件以及定义宏变量PI,#include“math〞#definePI3.1415926开场重写定义的Draw(CDC*pDC)函数,代码如下:CDelta::Draw(CDC*pDC){ doublerc=Radius*cos(60*PI/180);//外接圆半径与60度余弦值相乘后赋给rc doublers=Radius*sin(60*PI/180);//外接圆半径与60度正弦值相乘后赋给rs ct=cos(theta);//将theta的余弦值赋给ct st=sin(theta);//将theta的正弦值赋给st POINTdx1,dx11;//定义两个点(接下来会详细说明) POINTdx2,dx22;//同上 POINTdx3,dx33;//同上 dx1.x=cp.x-cp.x; dx1.y=cp.y-Radius-cp.y; dx11.x=dx1.x*ct-dx1.y*st+cp.x; dx11.y=dx1.y*ct+dx1.x*st+cp.y; dx2.x=cp.x-rs-cp.x; dx2.y=cp.y+rc-cp.y; dx22.x=dx2.x*ct-dx2.y*st+cp.x; dx22.y=dx2.y*ct+dx2.x*st+cp.y; dx3.x=cp.x+rs-cp.x; dx3.y=cp.y+rc-cp.y; dx33.x=dx3.x*ct-dx3.y*st+cp.x; dx33.y=dx3.y*ct+dx3.x*st+cp.y;POINT pts[]={{dx11.x,dx11.y},{dx22.x,dx22.y},{dx33.x,dx33.y}};//定义点数组,存储正三角形的三个点pDC->Polygon(pts,3);//利用画多边形的函数Polygon()画正三角形,pts为储存的三个点,3为点的个数}接下来对Draw函数里的变量以及运算进展解释:R如以下列图,正三角形的中心到各顶点的距离为半径,R设中心点的坐标为(cp.x,cp.y),则可得到右下角的坐标为cp.x+R*sin(60*PI/180),cp.y+R*cos(60*PI/180)按顺时针方向,接下来两个点的坐标分别为cp.x-R*sin(60*PI/180),cp.y-R*cos(60*PI/180)cp.x,cp.x-R此时,我们得到了三个顶点的坐标,如果按这三个点的坐标画图,就会得到如以下列图的三角形,在此根基上,不妨设此图形逆时针转过的角度为,有以下原理作为根基:设一个点的坐标为(x1,y1),它绕另一个点(x2,y2)旋转角,得到新的点的坐标为:x=(x1-x2)*cos-(y1-y2)*sin+x2;y=(y1-y2)*cos+(x1-x2)*sin+y2;显然,只需得到三个点绕中心旋转后各自的新坐标,我们就可以根据旋转的角得到新的正三角形在Draw(CDC*pDC)函数中,用theta来代替,以右下角顶点为例,原坐标为cp.x+rs,cp.y+rc按如下代码将cos(theta)和sin(theta)替换:ct=cos(theta);st=sin(theta);用dx3.x储存该点与中心点横坐标的差dx3.y储存该点与中心点纵坐标的差,如下:dx3.x=cp.x+rs-cp.x;dx3.y=cp.y+rc-cp.y; 用dx33储存该点旋转后得到的新的坐标:dx33.x=dx3.x*ct-dx3.y*st+cp.x;dx33.y=dx3.y*ct+dx3.x*st+cp.y;这样就得到了该点旋转后的坐标,其它两点按同样方法即可得到新坐标,dx22为左下角的新坐标,dx11为正上方的新坐标接下来,在CMyDraw2_0View的头文件中引入正三角形类,#include“Delta.h〞添加私有变量,创立正三角形类的指针变量:CDelta*delta;接下来我直接给出剩下根本形状类的代码(只在当中作注释,不再详细解释)2.5椭圆类的创立和定义创立名为CEllipse的类,继承CShape,在该头文件中添加如下代码:classCEllipse:publicCShape{public: CEllipse(); CEllipse(intx,inty,intw=0,inth=0);//带参数的构造函数,值分别为外接矩形左上角的横坐标、纵坐标、宽度、高度 intwidth;//外接矩形的宽度 intheight;//外接矩形的高度 CPointcenter_point;//椭圆中心点 Draw(CDC*pDC);//重新定义Draw函数 virtual~CEllipse();};在该类app中添加如下代码:CEllipse::CEllipse(){center_point.x=0;//将中心点横坐标初始为0center_point.y=0;//将中心点纵坐标初始为0width=0;//将外接矩形宽度初始为0height=0;//将外接矩形高度初始为0}CEllipse::CEllipse(intx,inty,intw,inth){center_point.x=x;//将传入的x值赋给中心点的横坐标center_point.y=y;//将传入的y值赋给中心点的纵坐标width=w;//将传入的w值赋给宽度height=h;//将传入的h值赋给高度}CEllipse::Draw(CDC*pDC){ pDC->Ellipse(center_point.x-width,center_point.y-height,center_point.x+width,center_point.y+height);//利用Ellipse()函数画椭圆}在CMyDraw2_0View的头文件中引入椭圆类,#include“Ellipse.h〞添加私有变量,创立椭圆类的指针变量:CEllipse*ellipse;2.6正四边形类的创立及定义命名为CQuadrangle,头文件中添加如下代码:public: CQuadrangle(); CQuadrangle(intx,inty,intradius=0);//带参数的构造函数,参数分别为中心点的横坐标、纵坐标、外接圆半径 intRadius;//外接圆半径 CPointcPoint;//中心点 Draw(CDC*pDC);//重新定义Draw函数 virtual~CQuadrangle();在该类app中添加如下代码:CQuadrangle::CQuadrangle(){cPoint.x=0;//将中心点的横坐标初始为0cPoint.y=0;//将中心点的纵坐标初始为0Radius=0;//将外接圆的半径初始为0}CQuadrangle::CQuadrangle(intx,inty,intradius){cPoint.x=x;//将传入的x值赋给中心点的横坐标cPoint.y=y;//将传入的y值赋给中心点的纵坐标Radius=radius;//将传入的radius赋给外接圆半径}CQuadrangle::Draw(CDC*pDC){ doubleRc=Radius*cos(45*PI/180);//将半径与45度余弦值的乘积赋给RcPOINTpts[]={{cPoint.x+Rc,cPoint.y+Rc},{cPoint.x+Rc,cPoint.y-Rc},{cPoint.x-Rc,cPoint.y-Rc},{cPoint.x-Rc,cPoint.y+Rc}};//定义点数组,储存四个顶点 pDC->Polygon(pts,4);//利用多边形绘画函数画正四边形}在CMyDraw2_0View的头文件中引入正四边形类,#include“Quadrangle.h〞添加私有变量,创立正四边形类的指针变量:CQuadrangle*quadrangle;2.7正六边形的创立及定义命名为CRegularHexagon,头文件中添加如下代码:public: CQuadrangle(); CQuadrangle(intx,inty,intradius=0);//带参数的构造函数,参数分别为中心点的横坐标、纵坐标、外接圆半径 intRadius;//外接圆半径 CPointcPoint;//中心点 Draw(CDC*pDC);//重新定义Draw函数 virtual~CQuadrangle();在该类app中添加如下代码:CRegularHexagon::CRegularHexagon(){cp.x=0;//将中心点的横坐标初始为0cp.y=0;//将中心点的纵坐标初始为0Radius=0;//将外接圆的半径初始为0}CRegularHexagon::CRegularHexagon(intx,inty,intradius){ cp.x=x;//将传入的x值赋给中心点的横坐标 cp.y=y;//将传入的y值赋给中心点的纵坐标 Radius=radius;//将传入的radius值赋给外接圆半径}CRegularHexagon::Draw(CDC*pDC){ doublers=Radius*sin(30*PI/180);//将半径与30度正弦值的乘积赋给rs doublerc=Radius*cos(30*PI/180);//将半径与30度余弦值的乘积赋给rc doubleRs=Radius*sin(60*PI/180);//将半径与60度正弦值的乘积赋给Rs doubleRc=Radius*cos(60*PI/180);//将半径与60度余弦值的乘积赋给RcPOINTpts[]={{cp.x+rs,cp.y+rc},{cp.x-rs,cp.y+rc},{cp.x-Radius,cp.y},{cp.x-Rc,cp.y-Rs},{cp.x+Rc,cp.y-Rs},{cp.x+Radius,cp.y}};//定义点数组pts,储存正六边形的六个顶点 pDC->Polygon(pts,6);//利用多边形绘画函数画出正六边形}在CMyDraw2_0View的头文件中引入正六边形类,#include“RegularHexagon.h〞添加私有变量,创立正六边形类的指针变量:CRegularHexagon*regularhexagon;2.8直线类的创立及定义命名为CLine,在头文件中添加如下代码:public: CLine(); CLine(intsx,intsy,intex=0,intey=0);//带参数的构造函数,分别为直线起点的横坐标、纵坐标,终点的横坐标、纵坐标 Draw(CDC*pDC);//重新定义Draw函数 CPointp_start;//定义直线起点 CPointp_end;//定义直线终点 virtual~CLine();在该类app中添加如下代码:CLine::CLine(){p_start.x=0;//将起点横坐标初始为0p_start.y=0;//将起点纵坐标初始为0p_end.x=0;//将终点横坐标初始为0p_end.y=0;//将终点纵坐标初始为0}CLine::CLine(intsx,intsy,intex,intey){ p_start.x=sx;//将sx的值赋给起点的横坐标 p_start.y=sy;//将sy的值赋给起点的纵坐标 p_end.x=ex;//将ex的值赋给终点的横坐标 p_end.y=ey;//将ey的值赋给终点的纵坐标}CLine::Draw(CDC*pDC){ pDC->MoveTo(p_start);//利用MoveTo()函数画出直线起点 pDC->LineTo(p_end);//利用LineTo()函数从起点画直线到终点}在CMyDraw2_0View的头文件中引入直线类,#include“Line.h〞添加私有变量,创立直线类的指针变量:CLine*line;各根本形状类在CMyDraw2_0View类中的调用与绘图的实现(注:以矩形、圆形、正三角形为重点介绍)3.1矩形类的调用与与绘图的实现绘图的过程是:鼠标左键按下->鼠标移动->鼠标左键弹起在此,引入鼠标的三个响应函数,分别对应该三个过程:按下ctrl+w,弹出如以下列图对话框,并按如图操作,选择右侧的AddFunction(本应是黑色,由于已添加,变为灰色),将三个响应函数添加到CMyDraw2_0View类app中。现在,需要告诉鼠标,当鼠标左键按下时开场进展绘画,那么,需要添加一个变量,告诉鼠标是否进展绘画:为View类添加私有成员变量:boolmDown;在View类的构造函数中对该值进展初始化,代码如下:CMyDraw2_0View::CMyDraw2_0View(){ //TODO:addconstructioncodehere mDown=false;//将mDown初始为false,表示默认为不进展绘画}在鼠标左键按下的响应函数中添加如下代码:VoidCMyDraw2_0View::OnLButtonDown(UINTnFlags,CPointpoint){mDown=true;//将mDown标记为true,表示此时即将开场绘画}在鼠标左键弹起的响应函数中添加如下代码:voidCMyDraw2_0View::OnLButtonUp(UINTnFlags,CPointpoint){mDown=false;//将mDown重新标记为false,说明此时应停顿绘画}在鼠标移动时判断鼠标是否按下,如果按下则开场进展绘画:voidCMyDraw2_0View::OnMouseMove(UINTnFlags,CPointpoint){if(mDown){//此处添加绘画代码(下面会说到)}}到此,对鼠标是否进展绘画的判断已完成,接下来,需要告诉鼠标画出的图形应该是矩形,不妨设一个变量用来储存类型:在View类中添加私有成员变量:intShapeType;//该变量用来储存图形类型在View类构造函数中进展该变量的初始化:ShapeType=-1;//默认为-1,表示为标的随手画(下面会提到)为View类添加菜单中矩形的响应函数:同样按下Ctrl+W,在弹出的对话框中如下选择:图中,蓝色条中的字符为在资源编辑时定义的矩形的ID,同样选择AddFunctioin,在View类中出现如下代码:voidCMyDraw2_0View::OnMenuGraphRectangle(){ //TODO:Addyourcommandhandlercodehere}在该函数中添加如下代码:ShapeType=2;//用2来代表矩形这样,就能用数字来表示各个根本形状了有了这个变量后,在鼠标左键按下时,首先判断该变量是否为-1(因为初始为-1,对应的是随手画),假设不是,则对ShapeType的值进展判断,用switch函数进展相应的操作:在鼠标左键按下的相应函数中添加如下代码:if(ShapeType!=-1)//判断当前的ShapeType值是否为-1 { switch(ShapeType)//对当前传入的ShapeType值进展选择,分别进展队形的操作 {} }当然,画矩形需要给矩形类传入矩形的左上角坐标和右下角坐标,在绘图时对应的就是鼠标按下时的坐标(我们把它叫做起始点)、鼠标移动时的坐标(我们把它叫做终点),这样,需要用两个变量来存储这两个点:在View类中添加私有成员变量:CPointponit_start;//用来存储起点CPointpoint_end;//用来存储终点在鼠标左键按下的响应函数中添加以下代码:point_start=point;//将鼠标按下时的点存储在point_start中 point_end.x=0;//将鼠标移动时的点横坐标赋值为0 point_end.y=0;//将鼠标移动时的点纵坐标赋值为0最后,一切准备就绪,该进展矩形的绘画了:矩形对应的数字为2,在鼠标按下的相应函数中,在switch()函数中添加以下代码:case2:rectangle=newCRectangle(point_start.x,point_start.y);break;//new一个矩形对象,将该地址存储在rectangle中,并将鼠标按下时的点(起点)传入,作为矩形的左上角的点此时,当鼠标按下时,鼠标就能知道即将要进展的是矩形的绘画。在鼠标移动的响应函数中也要对ShapeType值作出判断,告诉鼠标该进展矩形的绘画,方法与前面类似:在该函数的开头添加如下代码:CDC*pDC=GetDC();//翻开图形设备接口,简单来说,就是用pDC来进展绘画在if(mDown){}中添加如下代码:switch(ShapeType){case2:pDC->SetROP2(R2_NOTXORPEN);//将颜色设置为反色 if(point_end.x!=0)//判断鼠标是否移动了 { rectangle->Draw(pDC);//调用矩形类中的Draw函数 } point_end=point;//将终点设置为鼠标当前所在的点 rectangle->width=point_end.x-point_start.x;//将终点与起点的横坐标之差赋给矩形类中的宽度width rectangle->height=point_end.y-point_start.y;//将终点与起点的纵坐标之差赋给矩形类中的高度height rectangle->Draw(pDC);调用矩形类中的Draw函数 break;}下面对以上代码进展解释:当鼠标按下时,终点point_end的值为0,判断为false,将鼠标此时的点赋给point_end,储存起来,画出矩形,当鼠标移动后,判断为true,此时画出的矩形左上角坐标为鼠标按下时的点,高度和宽度为之前的高度和宽度,由于前面已将颜色设置为反色,所以将鼠标移动之前画的矩形覆盖掉,不会再看见,所以看到的矩形为当前的矩形,之前的矩形已无法看见,否则将会看到一连串的矩形。3.2圆形类的调用在3.1中已经为绘图做好了准备工作,下面只需要用一个数字表示圆形类看,并在鼠标左键按下和鼠标移动的响应函数中的switch语句中添加相应代码即可:voidCMyDraw2_0View::OnMenuGraphCircle(){ //TODO:Addyourcommandhandlercodehere ShapeType=3;//用3来表示圆形}在OnLButtonDown()中的switch语句中添加如下代码:Case3:circle=newCCircle(point_start.x,point_start.y);break;//new一个圆形类对象,将地址储存在circle中,并将起点传入,作为圆形的中心点在OnMouseMove()中的switch语句中添加如下代码:case3:pDC->SetROP2(R2_NOTXORPEN);//将颜色设为反色 if(point_end.x!=0)//判断鼠标是否移动 { circle->Draw(pDC);//调用圆形类中的Draw()函数 } point_end=point;//将鼠标当前所在的点保存在ponit_end中 xx=point_end.x-point_start.x;//将终点与起点的横坐标之差赋给xx(由于很多地方都会用到该变量,我将它作为View类的私有成员变量) yy=point_end.y-point_start.y;//将终点与起点的纵坐标之差赋给yy(同上) circle->Radius=(int)sqrt(xx*xx+yy*yy);//将两点间的距离作为圆的半径 circle->Draw(pDC);//调用圆形类中的Draw函数 break;接下来,一样作用的代码不再做注释3.3正三角形类的调用voidCMyDraw2_0View::OnMenuGraphPolygonDelta(){ //TODO:Addyourcommandhandlercodehere ShapeType=5;//用5来表示正三角形}在OnLButtonDown()中的switch语句中添加如下代码:case5:delta=newCDelta(point_start.x,point_start.y);break;//new一个正三角形类对象,将地址保存在delta中,并将起点传入,作为正三角形的中心点在OnMouseMove()中的switch语句中添加如下代码:case5:pDC->SetROP2(R2_NOTXORPEN); if(point_end.x!=0) { delta->Draw(pDC); } point_end=point; xx=point_end.x-point_start.x; yy=point_end.y-point_start.y; delta->Radius=(int)sqrt(xx*xx+yy*yy); delta->theta=(double)(point.x-point_start.x)/delta->Radius*PI*2;//由于theta的取值范围是0~360度,类型为double,假设直接用数学函数asin(),只能取到-90度到90度,所以,当鼠标绕着中心转动的时候,会有余弦的函数cos(),该值为point.x-point_start.x,取值范围是-1~1,只要让该值与2*PI相乘,就能得到-2*PI~2*PI的值,就能符合theta的取值(注:代码中的强制转型(double)为关键,否则所得到的值会被近似为0) delta->Draw(pDC); break;接下来,将根本类型调用的剩余代码给出:3.4根本类型调用的剩余代码用数字表示各根本形状:voidCMyDraw2_0View::OnMenuGraphLine(){ //TODO:Addyourcommandhandlercodehere ShapeType=1;}voidCMyDraw2_0View::OnMenuGraphEllipse(){ //TODO:Addyourcommandhandlercodehere ShapeType=4;}voidCMyDraw2_0View::OnMenuGraphPolygonQuadrangle(){ //TODO:Addyourcommandhandlercodehere ShapeType=6;}voidCMyDraw2_0View::OnMenuGraphPolygonPentangle(){ //TODO:Addyourcommandhandlercodehere ShapeType=7;}voidCMyDraw2_0View::OnMenuGraphPolygonRegularHexagon(){ //TODO:Addyourcommandhandlercodehere ShapeType=8;}在OnLButtonDown中:case1:line=newCLine(point_start.x,point_start.y);break;case4:ellipse=newCEllipse(point_start.x,point_start.y);break;case6:quadrangle=newCQuadrangle(point_start.x,point_start.y);break;case7:pentangle=newCPentangle(point_start.x,point_start.y);break;case8:regularhexagon=newCRegularHexagon(point_start.x,point_start.y);break在OnMouseMove中:case1: pDC->SetROP2(R2_NOTXORPEN); if(point_end.x!=0) { line->Draw(pDC); } point_end=point; line->p_end=point; line->Draw(pDC); break; case6:pDC->SetROP2(R2_NOTXORPEN); if(point_end.x!=0) { quadrangle->Draw(pDC); } point_end=point; xx=point_end.x-point_start.x; yy=point_end.y-point_start.y; quadrangle->Radius=(int)sqrt(xx*xx+yy*yy); quadrangle->Draw(pDC); break; case7:pDC->SetROP2(R2_NOTXORPEN); if(point_end.x!=0) { pentangle->Draw(pDC); } point_end=point; xx=point_end.x-point_start.x; yy=point_end.y-point_start.y; pentangle->Radius=(int)sqrt(xx*xx+yy*yy); pentangle->Draw(pDC); break; case8:pDC->SetROP2(R2_NOTXORPEN); if(point_end.x!=0) { regularhexagon->Draw(pDC); } point_end=point; xx=point_end.x-point_start.x; yy=point_end.y-point_start.y; regularhexagon->Radius=(int)sqrt(xx*xx+yy*yy); regularhexagon->Draw(pDC); }最后,还有一种画法,就是〞随手画〞我们已经判断过ShapeType!=-1时执行以上代码,而ShapeType默认为-1,所以如果要随手画,就要将ShapeType值重新变为-1,为画笔菜单中的铅笔添加响应函数,并将ShapeType值变为-1:voidCMyDraw2_0View::OnPencil(){ //TODO:Addyourcommandhandlercodehere ShapeType=-1;}并在OnMouseMove中,再增加以下代码:if(-1==ShapeType) { pDC->MoveTo(point_start);//将画出起点 pDC->LineTo(point);//画出起点到终点的线条 point_start=point;//将终点设置为上一个点 }以上即为绘图(不包括改变画笔及画硬币、工具栏)的所有代码,接下来,开场讲解画笔颜色及大小的调整画笔的使用、颜色及大小的调整在MFC里有一个CPen类,用来设定画笔的属性,使用方法为:CPen自定义名称(线条类型,大小,颜色〕所以,我们可以在鼠标移动的时候设定画笔属性:在翻开图形设备接口(即CDC*pDC)后,开场设定,添加如下代码:CPenpen(PS_SOLID,1,RGB(0,0,0));//其中,画笔类型为实现,大小为1,颜色为黑色pDC->SelectObject(&pen);//将pen传给pDC,使其能够使用定义的画笔既然可以调用,那么如果想要由自己去改变画笔属性,可以定义两个变量,用来保存画笔大小和颜色:为View类添加私有成员变量:intpen_width;//用来保存画笔大小COLORREFpen_color;//该变量类型为COLORREF,可以用来保存颜色的RGB值在View类构造函数中初始两个变量:pen_color=RGB(0,0,0);//颜色默认为黑色 pen_width=1;//画笔大小默认为1所以,在设定画笔属性时,可以这样设定:CPenpen(PS_SOLID,pen_width,pen_color);//pen_width和pen_color可以随意改变与根本形状类的情况一样,可以在用户选择颜色和大小后,将pen_color和pen_width设置为对应的RGB值和数字以红色和大小2为例:为画笔菜单里的红色选项创立响应函数,并将pen_color设置为对应RGB值:voidCMyDraw2_0View::OnMenuCpenColorRed(){ //TODO:Addyourcommandhandlercodehere pen_color=RGB(255,0,0);}为画笔菜单里的2选项创立响应函数,并将pen_width设置为对应数字:voidCMyDraw2_0View::OnMenuCepnWidthTwo(){ //TODO:Addyourcommandhandlercodehere pen_width=2;}接下来,直接给出颜色及大小调整的剩余代码:颜色的设定:voidCMyDraw2_0View::OnMenuCpenColorBlack(){ //TODO:Addyourcommandhandlercodehere pen_color=RGB(0,0,0);//将颜色设置为黑色}voidCMyDraw2_0View::OnMenuCpenColorGreen(){ //TODO:Addyourcommandhandlercodehere pen_color=RGB(0,255,0);//将颜色设置为绿色}voidCMyDraw2_0View::OnMenuCpenColorBlue(){ //TODO:Addyourcommandhandlercodehere pen_color=RGB(0,0,255);//将颜色设置为蓝色}voidCMyDraw2_0View::OnMenuCpenColorOrange(){ //TODO:Addyourcommandhandlercodehere pen_color=RGB(255,97,0);//将颜色设置为橙色}voidCMyDraw2_0View::OnMenuCpenColorYellow(){ //TODO:Addyourcommandhandlercodehere pen_color=RGB(255,255,0);//将颜色设置为黄色}voidCMyDraw2_0View::OnMenuCpenColorCyan(){ //TODO:Addyourcommandhandlercodehere pen_color=RGB(0,255,255);//将颜色设置为青色}voidCMyDraw2_0View::OnMenuCpenColorPurple(){ //TODO:Addyourcommandhandlercodehere pen_color=RGB(153,51,102);//将颜色设置为紫色}voidCMyDraw2_0View::OnMenuCpenColorPink(){ //TODO:Addyourcommandhandlercodehere pen_color=RGB(255,0,156);//将颜色设置为粉色}大小的设定:voidCMyDraw2_0View::OnMenuCepnWidthOne(){ //TODO:Addyourcommandhandlercodehere pen_width=1;//大小设置为1}voidCMyDraw2_0View::OnMenuCepnWidthThree(){ //TODO:Addyourcommandhandlercodehere pen_width=3;//大小设置为3}voidCMyDraw2_0View::OnMenuCepnWidthFour(){ //TODO:Addyourcommandhandlercodehere pen_width=4;//大小设置为4}voidCMyDraw2_0View::OnMenuCepnWidthFive(){ //TODO:Addyourcommandhandlercodehere pen_width=5;//大小设置为5}voidCMyDraw2_0View::OnMenuCepnWidthSix(){ //TODO:Addyourcommandhandlercodehere pen_width=6;//大小设置为6}voidCMyDraw2_0View::OnMenuCepnWidthSeven(){ //TODO:Addyourcommandhandlercodehere pen_width=7;//大小设置为7}到此,就能够画出定义的各种形状,还能选择定义的颜色,当然,毕竟颜色有限,为了能够随意改变颜色,还添加了一个颜色选项,名为〞自定义〞,用来自定义颜色,下面进展详细讲解:由于需要用户自己输入RGB值,所以需要一个对话框来完成信息的交互:在ResourceView中右键Dialog,选择〞插入Dialog〞,对出现的原始对话框如图进展编辑:将ID设置为IDD_DIALOG_COLOR,双击对话框,将会弹出信息框,询问是否为该对话框创立新的类,如图选择,会弹出如下对话框,如以下列图进展选择和命名,在ClassView中会出现CDialogColor的类,在该类中添加共有成员变量:public:intR;intG;intB;回到ResourceView中的对话框编辑界面,双击对话框中的〞编辑〞按钮,分别创立响应函数,在响应函数中如下去写:voidCDialogColor::OnChangeColorR(){ //TODO:IfthisisaRICHEDITcontrol,thecontrolwillnot //sendthisnotificationunlessyouoverridetheCDialog::OnInitDialog() //functionandcallCRichEditCtrl().SetEventMask() //withtheENM_CHANGEflagORedintothemask. //TODO:Addyourcontrolnotificationhandlercodehere CStringstrR;//定义String类型变量strR,用来保存编辑框中传入的值 GetDlgItemText(IDC_COLOR_R,strR);//通过GetDlgItemText函数获得编辑框中传入的值并赋给strR,其中的参数分别为编辑框的ID、变量strR R=atof(strR);//将strR转化为浮点数,并赋值给R}voidCDialogColor::OnChangeColorG(){ //TODO:IfthisisaRICHEDITcontrol,thecontrolwillnot //sendthisnotificationunlessyouoverridetheCDialog::OnInitDialog() //functionandcallCRichEditCtrl().SetEventMask() //withtheENM_CHANGEflagORedintothemask. //TODO:Addyourcontrolnotificationhandlercodehere CStringstrG; GetDlgItemText(IDC_COLOR_G,strG); G=atof(strG);}voidCDialogColor::OnChangeColorB(){ //TODO:IfthisisaRICHEDITcontrol,thecontrolwillnot //sendthisnotificationunlessyouoverridetheCDialog::OnInitDialog() //functionandcallCRichEditCtrl().SetEventMask() //withtheENM_CHANGEflagORedintothemask. //TODO:Addyourcontrolnotificationhandlercodehere CStringstrB; GetDlgItemText(IDC_COLOR_B,strB); B=atof(strB);}通过以上代码,就可以获取对话框中输入的值了,就可以在View类中使用它们:为View类添加私有成员变量:intR;intG;intB;在自定义的响应函数中添加如下代码:voidCMyDraw2_0View::OnMenuPenColorCustom(){ //TODO:Addyourcommandhandlercodehere CDialogColorDlgColor;创立CDialogColor的引用 DlgColor.DoModal();调用DoModal()函数弹出对话框 R=DlgColor.R;//将CDialogColor中的R赋给View类的R G=DlgColor.G;//将CDialogColor中的G赋给View类的G B=DlgColor.B;//将CDialogColor中的B赋给View类的B pen_color=RGB(R,G,B);//将传入的值作为RGB值}画硬币画硬币菜单下有四个选项:画、增加、减少、去除显然,是在点击〞画〞之后才开场在窗口上显示画出的硬币,由于画硬币的代码直接写在View类的OnDraw中,所以需要一个标记,判断是否需要画:为View类添加私有成员变量:booldraw;在View类构造函数中初始化该变量:draw=false;在〞画〞的响应函数中将其标记为true:draw=true;这样,在OnDraw函数中就会根据draw的值判断是否开场画硬币。画硬币还需要知道硬币的数量,而且,在画的时候,使用椭圆代替硬币,变化的只是椭圆的两个纵坐标,所以,还需要为View类添加三个私有成员变量:intCoinsNumber;//硬币的数量 intcoin_ly;//椭圆左上角的纵坐标 intcoin_ry;//椭圆右上角的纵坐标在构造函数中初始硬币数量:CoinsNumber=10;在OnDraw函数中,先定义第一个硬币的左、右纵坐标:coin_ly=300;coin_ry=330;然后判断是否开场画硬币,当条件为真时开场画硬币,代码如下:if(draw){for(inti=0;i<CoinsNumber;i++)//利用for循环,画出相应数量的椭圆 { pDC->Ellipse(100,coin_ly,300,coin_ry);//画出椭圆 coin_ly-=10;//循环一次就将左上角的纵坐标-10,表示下一个椭圆的位置上移10 coin_ry-=10;//循环一次就将右下角的纵坐标-10,表示下一个椭圆的位置上移10 }}此时,如果在菜单里选择〞画〞选项,就需要调用OnDraw()函数,在响应函数中添加如下代码:CDC*pDC=GetDC(); OnDraw(pDC);在此根基上,增加对硬币数量的增减操作:很明显,增减硬币操作是在画硬币之后才会执行,所以需要一个标记来判断是否已经画出硬币:为View类添加一个私有成员变量:boolmenu_draw_coin;//用来标记菜单里〞画〞选项是否执行在View类构造函数里初始化该变量:menu_draw_coin=false;中选择〞画〞时,将该变量标记为true:menu_draw_coin=true;已经有了标记后,只需判断是否已经执行〞画〞命令,再对硬币的数量进展增减,代码如下:voidCMyDraw2_0View::OnMenuDrawcoinAdd(){ if(menu_draw_coin)//判断是否已经执行过〞画〞命令 { draw=true;//将draw标记为true,以便OnDraw函数中的画硬币顺利执行 CDC*pDC=GetDC();//翻开图形设备接口 //TODO:Addyourcommandhandlercodehere if(CoinsNumber<=30)//为硬币数量设置最大值 CoinsNumber++;//将硬币数量+1 GetDocument()->UpdateAllViews(NULL);//刷新视图 ReleaseDC(pDC);//释放 }}voidCMyDraw2_0View::OnMenuDrawcoinReduce(){ if(menu_draw_coin)//判断是否已经执行过〞画〞命令 { draw=true;;//将draw标记为true,以便OnDraw函数中的画硬币顺利执行 CDC*pDC=GetDC();//翻开图形设备接口 //TODO:Addyourcommandhandlercodehere if(CoinsNumber>0)//硬

温馨提示

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

评论

0/150

提交评论