北邮程序设计实践报告mfc画图.docx
《北邮程序设计实践报告mfc画图.docx》由会员分享,可在线阅读,更多相关《北邮程序设计实践报告mfc画图.docx(23页珍藏版)》请在冰豆网上搜索。
北邮程序设计实践报告mfc画图
程序设计实践
设
计
报
告
课题名称:
简单画图程序的设计与实现
学生姓名:
班级:
班内序号:
学号:
日期:
课题概述
1.1课题目标和主要内容:
该软件功能与Windows下附件中的画图软件有相似功能。
本程序是在VC2010平台上用MFC所编。
绘制方面的功能主要包括绘制各种图元,包括直线、矩形、椭圆、扇形、连续线,用笔自由绘图。
绘图时可以选择各种颜色,各种线型和线宽。
1.2系统的主要功能
设计一个单文档类型的MFCAppWizard(exe)工程,此程序将实现简单的绘图功能,包括点、直线、矩形、椭圆、扇形和连续线的绘制。
并且能实现绘图的控制,包括线宽、线型和颜色和字体的设置。
2.系统设计
2.1系统总体框架
总体设计
设计图如图6
2.2系统详细设计
1.首先,新建一个单文档类型的MFCAppWizard(exe)工程,工程取名为:
SHOW。
为此程序添加一个子菜单,菜单名称为“绘图”,并为其添加六个菜单项,分别用来控制不同图形的绘制。
当用户选择其中的一个菜单项后,程序将按照当前的选择进行相应图形的绘制。
在程序运行以后,当用户单击某个菜单项时,应该把用户的选择保存起来,以便随后的绘图操作使用。
因此在CSHOWView类中添加一个私有变量dType;用来保存用户的选择,该变量的定义如下所述:
private:
DrawTypedType;
接着,在视类的构造函数中将此变量初始化为0,程序代码如下:
利用switch/case语句,来分别完成相应图形的绘制。
当用户选择【绘图】菜单下的不同子菜单项时,将变量dType设置为不同的值。
程序代码如下:
voidCSHOWView:
:
OnShowSline()
{
//TODO:
Addyourcommandhandlercodehere
//MessageBox("直¡À线?
Clicked!
");
dType=SLine;
}
voidCSHOWView:
:
OnShowCline()
{
//TODO:
Addyourcommandhandlercodehere
dType=CLine;
}
voidCSHOWView:
:
OnShowNosector()
{
//TODO:
Addyourcommandhandlercodehere
dType=NoSector;
}
voidCSHOWView:
:
OnShowSector()
{
//TODO:
Addyourcommandhandlercodehere
dType=Sector;
}
voidCSHOWView:
:
OnShowRect()
{
//TODO:
Addyourcommandhandlercodehere
dType=Recta;
}
voidCSHOWView:
:
OnShowEcllipse()
{
//TODO:
Addyourcommandhandlercodehere
dType=Ecllipse;
}
2.直线、矩形、椭圆扇形的绘制
对于直线、矩形和椭圆,在绘制时都可有两点来确定其图形。
当鼠标左击时得到一个点,当鼠标左键松开时得到另外一个点。
为视类CSHOWView分别捕获鼠标左键按下和弹起这两个消息。
另外当鼠标左键按下时,需要将鼠标当前按下点保存,因此我们为CSHOWView再增加一个CPoint类型的私有成员变量:
m_ptOrigin,在视类的构造函数中将此变量初始化为0。
在鼠标按下消息响应函数中,保存该点,代码如下:
voidCSHOWView:
:
OnLButtonDown(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
//m_ptOrigin=point;
switch(dType)
{
caseSLine:
m_bDraw=TRUE;
m_ptOrigin=point;
break;
caseCLine:
m_bDraw=TRUE;
m_ptOrigin=point;
break;
caseNoSector:
m_bDraw=TRUE;
m_ptOrigin=point;
break;
caseSector:
m_bDraw=TRUE;
m_ptOrigin=point;
m_ptNext=point;
break;
caseRecta:
m_bDraw=TRUE;
m_ptOrigin=point;
break;
caseEcllipse:
m_bDraw=TRUE;
m_ptOrigin=point;
break;
default:
break;
}
CView:
:
OnLButtonDown(nFlags,point);
}
3.连续线和扇形的绘制
Windows系统为我们提供了一个画图程序,在该程序中,利用画笔可以绘制连续的线条,下面我们设计绘制连续线和扇形。
为了绘制连续的线条,首先要得到线条的起点,这在前面已经实现。
然后需要捕获鼠标移动过程中的每一个点,这可以通过捕获鼠标移动消息(WM_MOUSEMOVE)来实现。
在此消息响应函数中,在依次捕获的各个点之间绘制一条条非常短的线段,从而就可以绘制出一条连续的线条。
遵照这一思路,我们开始增加程序的功能。
首先为视类增加鼠标移动消息(WM_MOUSEMOVE)的响应函数(OnMouseMove)。
这样,只要鼠标在应用程序窗口中移动时都会进入到这个消息响应函数中。
但这并不是我们所期望的,我们希望在鼠标左键按下后开始绘图。
因此,我们需要有一个变量来表示鼠标左键是否按下这一状态,然后在鼠标移动消息响应函数中对这一变量进行判断。
当此变量为真,即鼠标左键已经按下去,我们开始绘图。
于是,为视类添加一个BOOL型的私有变量m_bDraw,当鼠标左键按下去时,此变量为真;当鼠标左键弹起时,此变量为假,这时,我们就不再绘制线条了。
该变量在视类头文件中的定义代码如下:
Private:
BOOLm_bDraw;
接下来在视类的构造函数中,将此变量初始化为FALSE。
m_bdraw=FALSE;
当鼠标左键按下去时,在视类的OnLButtonDown函数中将此变量初始化为TRUE。
m_bdraw=TRUE;
当鼠标左键弹起时,在视类的OnLButton函数中将此变量初始化为假。
m_bdraw=FALSE;
然后在OnMouseMove函数中首先对m_bdraw变量进行判断,如果其值为真,说明鼠标左键已经按下去了,这时就可开始进行画线操作。
还有一点需要注意,因为每绘制一条线段后,下次应该从这条线段的终点开始继续绘制。
因此,绘制完当前线段后,应该修改线段的起点,将当前线段的终点作为下一条线段的起点,
如果在上面绘制连续线条的程序中,保持每段小直线的起点不变,即以鼠标左键按下时的起点为起点不变,分别绘制到鼠标移动点的直线,这时就会出现扇形的效果。
程序代码如下:
voidCSHOWView:
:
OnMouseMove(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
CPenpen(m_nLineStyle,m_nLineWidth,m_clr);
CClientDCdc(this);
CPen*pOldPen=dc.SelectObject(&pen);
if(m_bDraw)
{
switch(dType)
{
caseCLine:
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
m_ptOrigin=point;
break;
caseNoSector:
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
break;
caseSector:
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
dc.LineTo(m_ptNext);
m_ptNext=point;
break;
default:
break;
}
}
dc.SelectObject(pOldPen);
CView:
:
OnMouseMove(nFlags,point);
}
4.颜色
颜色对话框看起来比较复杂。
实际上,MFC为我们提供了一个类:
CColorDialog,可以很方便的创建这样的一个颜色对话框。
voidCSHOWView:
:
OnShowColor()
{
//TODO:
Addyourcommandhandlercodehere
dType=ColorSet;
CColorDialogdlg;
if(IDOK==dlg.DoModal())
m_clr=dlg.m_cc.rgbResult;
}
5.设置线形线宽
为程序添加一个设置对话框,允许用户指定画笔的类型、线宽,并让随后的绘图操作就使用用户指定的新设置值来进行绘制。
代码如下:
voidCSHOWView:
:
OnShowLstylewidth()
{
//TODO:
Addyourcommandhandlercodehere
CLSetDlgdlg;
dlg.m_nLineWidth=m_nLineWidth;
dlg.m_nLineStyle=m_nLineStyle;
dlg.m_clr=m_clr;
if(IDOK==dlg.DoModal())
{m_nLineWidth=dlg.m_nLineWidth;
m_nLineStyle=dlg.m_nLineStyle;
}
}
6.设置字体
为程序添加一个设置对话框,允许用户指定字体,并让随后的绘图操作就使用用户指定的新设置值来进行绘制。
代码如下:
voidCSHOWView:
:
OnShowFont()
{
//TODO:
Addyourcommandhandlercodehere
dType=FontSet;
CFontDialogdlg;
if(IDOK==dlg.DoModal())
{
if(m_font.m_hObject)
m_font.DeleteObject();
m_font.CreateFontIndirect(dlg.m_cf.lpLogFont);
m_strFontName=dlg.m_cf.lpLogFont->lfFaceName;
}
Invalidate();
}
2.3程序运行结果
3.总结
通过这次学年设计,我了解vc++是Windows平台上的C++编程环境,难度比较大。
MFC是Win32API的包装类,需要理解文档视图类的结构,窗口类的结构,消息流向等等;基于我们这次用VC++编写了一个简单的画图板,功能不是很多,但是从中的到不少收获。
主要有:
1.对项目和文档的了解,我们在编写程序时,要对不同的文件进行编写。
其中项目就是文件的集合,包括头文件、源代码文件、资源文件。
文档窗口也称编辑窗口,是用户进行输入或编辑头文件、源文件、资源的区域。
在编辑文件时,为了增加程序的可读性,系统用绿色显示注释语句,用蓝色显示关键字。
2.菜单:
我们绘制画图板时,就要建立一个“绘图”菜单。
对于“绘图”菜单下还有几个子菜单项,通过建立菜单同时让它实现菜单上的命令,这就要我们对每个菜单项进行设置,诸如,ID、标题、快捷键、热键等。
还有一些属性设置,设置不好,容易出错,所以每次建立菜单,都需谨慎设置,记住每个菜单对应的参数。
3.对于CView视图,经过查询主要是负责内存数据与用户的交互。
包括数据的显示、用户操作的响应(如菜单的选取、鼠标的响应)。
最重要的是OnDraw(重画窗口),通常用CWnd:
:
Invalidate()来启动它。
另外,它通过消息映射表处理菜单、工具条、快捷键和其他用户消息。
最后通过学习VC++,从中受益匪浅,更多的知识,还有待于我们去挖掘实现更多有趣的东西,同样它也是一个很强大的软件。
参考文献
【1】《VC++深入详解》孙鑫余安萍编著电子工业出版社出版
【2】《VC++程序设计基础教程》谭浩强主编宋金珂高丽华张迎新编著清华大学出版社出版
附录:
简易画图板主要程序代码
//SHOWView.cpp:
implementationoftheCSHOWViewclass
//
#include"stdafx.h"
#include"SHOW.h"
#include"SHOWDoc.h"
#include"SHOWView.h"
#include"LSetDlg.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//CSHOWView
IMPLEMENT_DYNCREATE(CSHOWView,CView)
BEGIN_MESSAGE_MAP(CSHOWView,CView)
//{{AFX_MSG_MAP(CSHOWView)
ON_COMMAND(ID_SHOW_SLINE,OnShowSline)
ON_COMMAND(ID_SHOW_CLINE,OnShowCline)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_COMMAND(ID_SHOW_NOSECTOR,OnShowNosector)
ON_COMMAND(ID_SHOW_SECTOR,OnShowSector)
ON_COMMAND(ID_SHOW_RECT,OnShowRect)
ON_COMMAND(ID_SHOW_ECLLIPSE,OnShowEcllipse)
ON_COMMAND(ID_SHOW_COLOR,OnShowColor)
ON_COMMAND(ID_SHOW_FONT,OnShowFont)
ON_COMMAND(ID_SHOW_LSTYLEWIDTH,OnShowLstylewidth)
//}}AFX_MSG_MAP
//Standardprintingcommands
ON_COMMAND(ID_FILE_PRINT,CView:
:
OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT,CView:
:
OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW,CView:
:
OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CSHOWViewconstruction/destruction
CSHOWView:
:
CSHOWView()
{
//TODO:
addconstructioncodehere
m_bDraw=FALSE;
m_clr=RGB(255,0,0);
m_strFontName="";
m_nLineWidth=0;
m_nLineStyle=0;
}
CSHOWView:
:
~CSHOWView()
{
}
BOOLCSHOWView:
:
PreCreateWindow(CREATESTRUCT&cs)
{
//TODO:
ModifytheWindowclassorstylesherebymodifying
//theCREATESTRUCTcs
returnCView:
:
PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
//CSHOWViewdrawing
voidCSHOWView:
:
OnDraw(CDC*pDC)
{
CSHOWDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//TODO:
adddrawcodefornativedatahere
//CClientDCdc(this);
CFont*pOldFont=pDC->SelectObject(&m_font);
pDC->TextOut(0,0,m_strFontName);
pDC->SelectObject(pOldFont);
}
/////////////////////////////////////////////////////////////////////////////
//CSHOWViewprinting
BOOLCSHOWView:
:
OnPreparePrinting(CPrintInfo*pInfo)
{
//defaultpreparation
returnDoPreparePrinting(pInfo);
}
voidCSHOWView:
:
OnBeginPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{
//TODO:
addextrainitializationbeforeprinting
}
voidCSHOWView:
:
OnEndPrinting(CDC*/*pDC*/,CPrintInfo*/*pInfo*/)
{
//TODO:
addcleanupafterprinting
}
/////////////////////////////////////////////////////////////////////////////
//CSHOWViewdiagnostics
#ifdef_DEBUG
voidCSHOWView:
:
AssertValid()const
{
CView:
:
AssertValid();
}
voidCSHOWView:
:
Dump(CDumpContext&dc)const
{
CView:
:
Dump(dc);
}
CSHOWDoc*CSHOWView:
:
GetDocument()//non-debugversionisinline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSHOWDoc)));
return(CSHOWDoc*)m_pDocument;
}
#endif//_DEBUG
/////////////////////////////////////////////////////////////////////////////
//CSHOWViewmessagehandlers
voidCSHOWView:
:
OnShowSline()
{
//TODO:
Addyourcommandhandlercodehere
//MessageBox("直线Clicked!
");
dType=SLine;
}
voidCSHOWView:
:
OnShowCline()
{
//TODO:
Addyourcommandhandlercodehere
dType=CLine;
}
voidCSHOWView:
:
OnLButtonDown(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
//m_ptOrigin=point;
switch(dType)
{
caseSLine:
m_bDraw=TRUE;
m_ptOrigin=point;
break;
caseCLine:
m_bDraw=TRUE;
m_ptOrigin=point;
break;
caseNoSector:
m_bDraw=TRUE;
m_ptOrigin=point;
break;
caseSector:
m_bDraw=TRUE;
m_ptOrigin=point;
m_ptNext=point;
break;
caseRecta:
m_bDraw=TRUE;
m_ptOrigin=point;
break;
caseEcllipse:
m_bDraw=TRUE;
m_ptOrigin=point;
break;
default:
break;
}
CView:
:
OnLButtonDown(nFlags,point);
}
voidCSHOWView:
:
OnLButtonUp(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
CPenpen(m_nLineStyle,m_nLineWidth,m_clr);
CClientDCdc(this);
CPen*pOldPen=dc.SelectObject(&pen);
CBitmapbitmap;
bitmap.LoadBitmap(IDB_BITMAP1);
CBrushbrush(&bitmap);
CBrush*pBrush=CBrush:
:
FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
CBrush*pOldBrush=dc.SelectObject(pBrush);
switch(dType)
{
caseSLine:
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);