面向对象程序设计实训
题目:简单的绘图程序院系专业:__学院__专业
姓名:学号:________
同组其他学生(学号):
简单绘图程序说明
1、功能分析
目前这个软件的主要功能有如下:
1、画直线:通过OnLine()函数实现。
2、画矩形:通过OnRectangle()函数实现。
3、画圆角矩形:通过OnRoundrect()函数实现。
4、画椭圆:通过OnEllipse()函数实现。
5、铅笔工具:可以画任意线条。通过直接在OnMouseMove(UINTnFlags,CPointpoint)函数里面添加代码实现。
6、右键弹出菜单:可以在客户中点击鼠标右键,快速选择常用菜单。通过OnConte_tMenu函数实现。
7、状态栏显示鼠标移动的坐标:在程序的右下角显示,通过调用setWidnowTe_t和GetParent()实现。
8、画图颜色选择:可以画任何颜色的线条,通过OnColor()函数实现。
9、线条类型及线宽的设置:可以将画出的线条设置成实线、虚线、点线、点划线,双点划线,还可以设置线条的粗细,,通过实例这一功能立刻显示所选择线条的粗细及线型。通过新建CLineSettingDlg类,其中OnSelchangeLineStyle()函数实现线型的改变,OnChangeEditLineWidth()函数实现线宽的改变。再在CDrawView类中调用OnLineSetting()函数实现画笔的对话框,CLineSettingDlg类中的OnPaint()函数是实现示例功能的。
10、窗口的重绘时不擦除原来的内容:新建CShape类用来保存线条的颜色,线宽,填充色等属性,在窗口大小发生变化时有OnDraw(CDCpDC)函数进行重绘工作,重绘中调用了各个绘图函数的Draw(CDCpDC)函数。
11、所绘图形的保存于读取,通过Serialize(CArchivear)函数进行序列化操作,将所绘图形的信息通过文件的形式保存起来。
2、系统总体框架
图1总体框架
3、模块设计与分析
3.1画图模块:该模块的大部份功能都写在了CDrawView类里面。该模块也是此次程序的重点模块之一,主要负责画一些简单图形,例如:直线、矩形、圆角矩形、椭圆、任意曲线(铅笔)等等;有线型、线宽的设置;还有画笔颜色和填充色的选择,可以画各种各样颜色的线条;还包含的右键菜单设置的函数。3.2窗口模块:这部分大多数都是编译器自动生成,只做了一些修改,例如:使程序一开始运行便最大话,还是自定义程序的标题。
3.3菜单模块:该部分同样大部分都是编译器自动生成的,自己增添了一部分菜单例如:绘图工具、颜色设置、线条设置等等。还有右键弹出菜单,有颜色及线条设置等等,让使用者可以进行快速的操作。
3.4工具栏与状态栏模块:除了编译器自动生成的之外,还加入了画直线、矩形、圆角矩形、椭圆、铅笔等工具的快速选择,状态栏可以显示鼠标移动的坐标。
4、类的设计与分析
4.1、CAboutDlg类
由编译器生成,只做了一处的修改:
m_pMainWnd->SetWindowTe_t(_T("简单绘图工具"));
/设定主框架窗口标题
4.2、CDrawView类由编译器自动生成的类
部分源代码:
voidCDrawView::OnLButtonDown(UINTnFlags,CPointpoint){
/TODO:Addyourmessagehandlercodehereand/orcalldefaultif(m_flag==0)
SetCapture();
::SetCursor(m_hCross);
m_ptOrigin=point;
m_lMouseDown=true;
else
m_ptOrigin=point;
m_ptOld=point;/临时点
m_lMouseDown=true;/鼠标左键被按下
SetCapture();/将鼠标消息发送到视窗口
CRectrect;
GetClientRect(rect);/得到客户窗口的大小
ClientToScreen(rect);/将当前窗口坐标转换成屏幕坐标ClipCursor(rect);/把鼠标限定在其参数指定的矩形区域内
SetCursor(m_hCross);/获得十字光标
CScrollView::OnLButtonDown(nFlags,point);
/响应鼠标移动消息,将起点与临时点之间的线擦除/
voidXXXwView::OnMouseMove(UINTnFlags,CPointpoint)
/TODO:Addyourmessagehandlercodehereand/orcalldefaultCStringstr;
XXX("_=%d,y=%d",point._,point.y);
/得到框架类窗口的指针GetParent(),然后指针强制转换为框架类的类型(CMainFrame)
/调用状态栏类的成员函数setWidnowTe_t
((CMainFrame)GetParent())->XXX(str);if(m_lMouseDown)
{/初始化
CClientDCdc(this);
CPenpen(m_vLineStyle,m_vLineWidth,m_color);
XXX(pen);
CBrushbrush;/定义画刷
CPenpOldPen=XXX(pen);/将画笔选入DC,并保存以前所用的画笔
XXXolidBrush(m_fColor);/创建画刷
XXX(brush);/获取画刷
if(m_flag==0)
CClientDCdc(this);
CPenpen(m_vLineStyle,m_vLineWidth,m_color);
XXX(pen);
CDrawDocpDoc=GetDocument();
ASSERT_VALID(pDoc);
CPointptOrg,ptStart,ptEnd;
ptOrg=GetScrollPosition();/获得当前工作区原点的坐标
ptStart=m_ptOrigin+ptOrg;/加上原点的坐标来修正线段的坐标
ptEnd=point+ptOrg;
CCLinepCLine=newCCLine(ptStart,ptEnd,m_vLineStyle,m_vLineWidth,m_color,m_fColor);
pDoc->XXX(pCLine);
pDoc->SetModifiedFlag();
XXX(m_ptOrigin);
XXX(point);
m_ptOrigin=point;
switch(m_flag)
case1:/画直线
XXX(R2_NOT);/当前绘制的像素值设为屏幕像素值的反,这样可以覆盖掉上次的绘图,(自动擦除上次绘制的图形)
XXX(NULL_BRUSH);/使图线不遮去原有背景XXX(m_ptOrigin);/这两行代码擦除从起点到
XXX(m_ptOld);/上次鼠标移动到的位置之间的临时线XXX(pen);
XXX(m_ptOrigin);/这两行代码从起点到鼠标当前位置画线
XXX(point);/
break;
case2:/画矩形
XXX(R2_NOT);
XXX(NULL_BRUSH);
XXX(CRect(m_ptOrigin,m_ptOld));
XXX(pen);
XXX(CRect(m_ptOrigin,point));
break;
case3:/画圆角矩形
XXX(R2_NOT);
XXX(NULL_BRUSH);
XXX(CRect(m_ptOrigin,m_ptOld),CPoint(15,15));XXX(CRect(m_ptOrigin,point),CPoint(15,15));break;
case4:/画椭圆
XXX(R2_NOT);
XXX(NULL_BRUSH);
XXX(CRect(m_ptOrigin,m_ptOld));
XXX(CRect(m_ptOrigin,point));
break;
case5:/画圆,将椭圆的长轴长度与短轴长度相同即可XXX(R2_NOT);
XXX(NULL_BRUSH);
XXX(m_ptOrigin._,m_ptOrigin.y,m_ptOld._,m_ptOrigin.y+m_ptOld._-m_ptOrigin._);
XXX(m_ptOrigin._,m_ptOrigin.y,point._,m_ptOrigin.y+point._-m_ptOrigin._);
break;
}/switch结束
XXX(pOldPen);/恢复先前的画笔
m_ptOld=point;
}/if结束
CScrollView::OnMouseMove(nFlags,point);
voidCDrawView::OnLButtonUp(UINTnFlags,CPointpoint)
/TODO:Addyourmessagehandlercodehereand/orcalldefaultif(m_flag==0)
if(m_lMouseDown)
m_lMouseDown=false;
ReleaseCapture();
ClipCursor(NULL);
else
if(m_lMouseDown)
m_lMouseDown=false;
CClientDCdc(this);
CPenpen(m_vLineStyle,m_vLineWidth,m_color);
XXX(pen);
CBrushbrush;/定义画刷
XXX(m_fColor);/创建画刷XXX(brush);/获取画刷
CPenpOldPen=XXX(pen);
ReleaseCapture();
ClipCursor(NULL);
switch(m_flag)
case1:/画直线
XXX(R2_COPYPEN);/使用当前的画笔的颜色
XXX(m_ptOrigin);/这两行代码从起点到鼠标当前位置画线
XXX(point);/
break;
case2:/画矩形
XXX(CRect(m_ptOrigin,point));
break;
case3:/画圆角矩形
XXX(CRect(m_ptOrigin,point),CPoint(10,15));break;
case4:/画椭圆
XXX(R2_COPYPEN);
XXX(CRect(m_ptOrigin,point));
break;
case5:/画圆
XXX(R2_COPYPEN);
XXX(m_ptOrigin._,m_ptOrigin.y,point._,m_ptOrigin.y+point._-m_ptOrigin._);
break;
}/switch结束
/实现文件保存,将各图形类的地址保存在CObArraym_obArray数组中
CDrawDocpDoc=GetDocument();/得到文档类指针CShapepShape;
CPointptOrg;
ptOrg=GetScrollPosition();/获得当前工作区原点的坐标
m_ptOrigin=m_ptOrigin+ptOrg;/加上原点的坐
标来修正线段的坐标
point=point+ptOrg;
switch(m_flag)
case1:
pShape=newCLine(m_ptOrigin,point,m_vLineStyle,m_vLineWidth,m_color,m_fColor);
break;
case2:
pShape=newCRectangle(m_ptOrigin,point,m_vLineStyle,m_vLineWidth,m_color,m_fColor);
break;
case3:
pShape=newCRoundRect(m_ptOrigin,point,m_vLineStyle,m_vLineWidth,m_color,m_fColor);
break;
case4:
pShape=newCEllipse(m_ptOrigin,point,m_vLineStyle,m_vLineWidth,m_color,m_fColor);
break;
case5:
pShape=newCCircle(m_ptOrigin,point,m_vLineStyle,m_vLineWidth,m_color,m_fColor);
break;
pDoc->XXX(pShape);
pDoc->SetModifiedFlag();
}/if结束
m_lMouseDown=false;
CScrollView::OnLButtonUp(nFlags,point);
4.3、CMainFrame类
主要由编译器生成,做了小部分修改:
/工具条的风格
if(!XXX(this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_LEFT
|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||
!XXX(IDR_SHAPETOOLBAR))
TRACE0("Failedtocreatetoolbar
");
return-1;/failtocreate
intnCount=s_ShapeToXXX().GetButtonCount();/设置工具条按钮能被按下并且弹起
for(inti=0;iXXX(i,TBBS_CHECKGROUP);
XXX(CBRS_ALIGN_ANY);/以下两行使形状工具条和标准工具条具有停靠能力,并且可以停靠在任何地方
XXX(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(m_wndToolBar);
DockControlBar(s_ShapeToolBar,AF__IDW_DOCKBAR_LEFT,NULL);/使形状工具条停靠在客户区左边。
用于改变工具条停靠的地方。
4.4、CLineSettingDlg类
由自己创建,主要是响应菜单中的各个设置选项,该类实现的功能比较少。
voidCLineSettingDlg::OnPaint()
CPaintDCdc(this);/deviceconte_tforpainting
/TODO:Addyourmessagehandlercodehere
UpdateData();
CPenpen(m_LineStyle,m_LineWidth,m_color);/创建画笔
XXX(pen);
CRectrect;
GetDlgItem(IDC_SAMPLE)->GetWindowRect(rect);
ScreenToClient(rect);
XXX(XXX,(XXX.bottom)/2);
XXX(XXX,(XXX.bottom)/2);
/DonotcallCDialog::OnPaint()forpaintingmessages}
voidCLineSettingDlg::OnSelchangeLineStyle()
/TODO:Addyourcontrolnotificationhandlercodehere
intinde_=((CComboBo_)GetDlgItem(IDC_LINESTYLE))->GetCurSel();m_LineStyle=inde_;
Invalidate();
voidCLineSettingDlg::OnChangeEditLineWidth()
/TODO:IfthisisaRICHEDITcontrol,thecontrolwillnot
/sendthisnotificationunlessyouoverridetheCDialog::OnInitDialog()
/functionandcallCRichEditCtrl().SetEventMask()
/withtheENM_CHANGEflagORedintothemask.
/TODO:AddyourcontrolnotificationhandlercodehereInvalidate();
4.5、Chape类
由自己创建,主要用于保存线条的颜色,线宽,填充色等属性,在窗口重绘时
部分源代码:
CShape::CShape(CPointp1,CPointp2,UINTps,intpw,COLORREFcl,COLORREFc2)
this->m_ptOrigin=p1;
this->m_ptEnd=p2;
this->m_LineStyle=ps;
this->m_LineWidth=pw;
this->m_color=cl;
this->m_fColor=c2;
4.6、CLine,CCLine,CCircle,CEllipse,CRectangle,CRoundRect类由自己创建,由自己创建,它们都是由Chape类派生出来,用于绘制各种不同类型的图形,颜色,线条等属性均取自于Chape类。
部分源代码:
voidCLine::Draw(CDCpDC)
CPenpen(m_LineStyle,m_LineWidth,m_color);
pDC->SelectObject(pen);
CBrushbrush(m_fColor);
pDC->SelectObject(brush);
pDC->MoveTo(m_ptOrigin._,m_ptOrigin.y);
pDC->LineTo(m_ptEnd._,m_ptEnd.y);
voidCEllipse::Draw(CDCpDC)
CPenpen(m_LineStyle,m_LineWidth,m_color);
pDC->SelectObject(pen);
CBrushbrush(m_fColor);
pDC->SelectObject(brush);
pDC->Ellipse(CRect(m_ptOrigin,m_ptEnd));
voidCCircle::Draw(CDCpDC)
CPenpen(m_LineStyle,m_LineWidth,m_color);
pDC->SelectObject(pen);
CBrushbrush(m_fColor);
pDC->SelectObject(brush);
pDC->Ellipse(m_ptOrigin._,m_ptOrigin.y,m_ptEnd._,m_ptOrigin.y+m_ptEnd._-m_ptOrigin._);
流程图:
画画画铅直矩椭笔线形圆
6、功能测试
图6-1铅笔工具测试图
图6-2画直线测试图
图6-3画矩形测试图
图6-4画椭圆测试图
图6-5颜色及填充色设置测试图
8、关键源代码
1)在“MainFrm.h”中,在classCMainFrame:publicCFrameWnd里的protected下定义:
CToolBarm_wndToolBar;/工具栏在public下定义:CStatusBarm_wndStatusBar;
/此函数可实现在状态栏显示光标所在位置的坐标
CStringstr;
XXX("_=%d,y=%d",point._,point.y);
/得到框架类窗口的指针GetParent(),然后指针强制转换为框架类的类型(CMainFrame)
/调用状态栏类的成员函数setWidnowTe_t
((CMainFrame)GetParent())->XXX(str);
9、使用手册
由于本程序使用比较简单,现在只作一些的使用介绍.下面是程序打开的初始界面
图6-6程序主体图
菜单与工具栏,工具栏可以快捷选择要使用的画笔
图6-7菜单栏及工具栏
此功能与工具栏的一样,只是工具栏那里会比较方便选择
图6-8绘图工具栏
线条类型对话框,颜色设置请参考图6-8颜色设置测试图
图6-12线宽、线型设置
图6-13右键弹出菜单