mfc简单绘图程序.docx
- 文档编号:28394210
- 上传时间:2023-07-13
- 格式:DOCX
- 页数:55
- 大小:214.75KB
mfc简单绘图程序.docx
《mfc简单绘图程序.docx》由会员分享,可在线阅读,更多相关《mfc简单绘图程序.docx(55页珍藏版)》请在冰豆网上搜索。
mfc简单绘图程序
MFC
简
单
的
绘
图
程
序
——王帅
摘要2
关键字2
Notableofcontentsentriesfound.
摘要:
本绘图程序能够进行基本图形的绘画,如直线,圆,矩形,三角形等等,并且在此基础上添加了多边形的绘画,如正五边形等。
除此之外,还能够进行随手画,即用鼠标随意画线条。
为了更好的绘图,还添加了对画笔粗细的调整,以及对画笔颜色的调整,除了特定的颜色,颜色还可根据输入的RGB值随意更改。
还有一些老师的要求,加入了画硬币、显示硬币数目即鼠标坐标等信息。
本程序主要采用面向对象写法。
关键字:
程序设计,MFC,绘图
1.引言
设计目的
本绘图程序的设计不仅仅局限于老师课堂的要求,通过C++的编写实现绘图要求,我还想要在此基础上,加入自己的一些想法,想要更好地了解MFC,更好地去实现自己的想法。
2.功能说明
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.功能的实现
3.1视图设计
利用MFC生成画图应用程序框架具体步骤如下:
(1)执行VC程序,选择File|New命令,弹出New对话框.单击Projects标签,转到Projects选项卡,选择MFCAppWizard(exe)选项,然后在Projectname文本框中输入MyDraw2_0(原来也做过一个,不过并没有以面向对象的写法去写,这个就当作是我的第二个版本),文本框是指项目的本地路径。
(2)由于本程序是实现画线,要在视图中完成,所以首先创建一个基于单文档的应用程序
3.2编辑资源
(1)利用ResourceView中的Menu编辑器在菜单栏添加菜单,该流程图如下3.2所示:
图3.2
(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中添加了增加和减少硬币的方法。
工具栏中只要和为各个图标添加函数,作用和菜单栏中的图形一栏中对应即可。
最后还有硬币的数量和鼠标坐标放在状态栏中显示,下面开始进行函数代码的实现。
(2)代码的实现:
1.为基本形状创建一个基类,命名为CShape。
在ClassViewz中右键点击MyDraw2_0classes->newclass,在弹出窗口的顶部下拉框中选择GenericClass,如图所示
在头文件中添加虚函数Draw(CDC*pDC)
public:
CShape();
virtualDraw(CDC*pDc)=0;//添加的虚函数
virtual~CShape();
2.基本形状类的创建(注:
以矩形、圆形、正五边形、正三边形为重点介绍)
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值设置为0
point_LeftUp.y=0;//左上角坐标x值设置为0
width=0;//矩形的宽度初始为0
height=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_)
#defineAFX_MYDRAW2_0VIEW_H__3809529C_6744_4AD2_80A4_D44683D0A5AF__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;//圆心的横坐标初始为0
center_point.y=0;//圆心的纵坐标初始为0
Radius=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_point.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;//圆心横坐标初始为0
cP.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-R
cP.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;//圆心的横坐标初始为0
cp.y=0;//圆心的纵坐标初始为0
Radius=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;
POINTpts[]={{dx11.x,dx11.y},{dx22.x,dx22.y},{dx33.x,dx33.y}};//定义点数组,存储正三角形的三个点
pDC->Polygon(pts,3);//利用画多边形的函数Polygon()画正三角形,pts为储存的三个点,3为点的个数
}
R
接下来对Draw函数里的变量以及运算进行解释:
如图所示,正三角形的中心到各顶点的距离为半径,
设中心点的坐标为(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);//带参数的构造函数,值分别为外接矩形左上角的横坐标、纵坐标、宽度、高度
intwid
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- mfc 简单 绘图 程序