程序运行界面:
1.
2.
设计概要: 1 引言
1.1编写目的
对C++学习收获的一次测试,以及对自己学习能力的一中考验。
1.2背景
说明:
a.软件名称:涂鸦(DooDle);
b.此画图软件由Bring.Zhang独立完成设计与实现。
1.3定义
此画图软件定义了自己的文件存储格式*.dle,只能打开.dle格式的文件
1.4参考资料
a. 《Visual C++ 6.0编程实用技术与案例》陈元琰等编著
b.《深入浅出MFC》 简体中文版(侯俊杰);
c.<<VC++技术内幕>> 潘爱民。
2 总体设计
2.1需求规定
设计目标:设计一个简单的图形编辑器(类似于一个简单的windows画图程序),具有基本图形形状的绘制、涂色等功能,并能够保存和打开自定义格式图形文件。要求使用MFC编程。
功能设计要求:
a.
图形编辑功能
(1)
能够在画图区域中实现对矩形、圆、椭圆、直线等各种基本图元的绘制。
(2)
能够对所绘制的各种图元内部任意选择颜色进行涂色
(3)
能够对各种图形编辑操作实现undo(撤消)功能
b.
文件保存与打开功能
(1)
能够将在图形编辑区中所输入的各种图形对象存储到文件中。
(2)
能够打开所保存的自定义格式的图形文件,并在文件打开时将文件中存储的所有图形对象显示出来。
c.
测试程序
2.2运行环境
此画图软件是在visual stdio 2005环境下编写的,并成功通过编译。
2.3基本设计流程
a.运用MFC AppWizard建立画图程序的基本框架(SDI);
b.设计所用图元类(具体设计见总体框架);
c.实现动态画图操作;
d.实现画图文件的文件操作。
2.2运行环境
此画图软件是在visual stdio 2005环境下编写的,并成功通过编译。
2.3基本设计流程
a.运用MFC AppWizard建立画图程序的基本框架(SDI);
b.设计所用图元类(具体设计见总体框架);
c.实现动态画图操作;
d.实现画图文件的文件操作。
2.4系统总框图
2.5模块的设计分析
a.图元特性设计:
图元基类:
class CShape:public CObject
...{
protected:
COLORREF m_pColor; //线条颜色
int m_pWidth;//线条宽度
int m_pStyle;//线条样式
CShape()...{}
DECLARE_SERIAL(CShape)
public:
virtual
void Drawing(CDC* pDC)...{}//画图操作
virtual
void Serialize(CArchive& ar);//
virtual
~CShape();
};
其它图元都是从此基类继承得到的
b.动态画图:
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&point);//滚动条坐标转换代码
dc.SelectStockObject(NULL_BRUSH);
SetCursor(m_HCursor);
if(m_Drag)...{
CDooDleDoc* pDoc = GetDocument();
CPen NewPen,*pOldPen;
switch(pDoc->m_pStyle)
...{
case PEN_STYLE_SOLID:
NewPen.CreatePen(PS_SOLID,pDoc->m_pWidth,pDoc->m_pColor);
Break;
//…………….
}
pOldPen = dc.SelectObject(&NewPen);
dc.SetROP2(R2_NOT);
if(pDoc->CurrentDraw == DRAW_LINE)...{//直线
dc.MoveTo(m_pOrigin);
dc.LineTo(m_pPrev);//擦掉上一次画的线
dc.MoveTo(m_pOrigin);
dc.LineTo(point);//画线
}
if(pDoc->CurrentDraw == DRAW_RECTANGLE)...{//矩形
//……………………….
鼠标移动是画图操作的主要动作之一,处理鼠标移动事件在程序中尤为重要。 c.撤消功能
void CDooDleDoc::OnEditUndo()
...{
// TODO: Add your command handler code here
int index = m_ObArray.GetUpperBound();
if(index>=0
&& m_pModifiedCount >
0)...{ //m_pModifiedCount为撤消标志
delete m_ObArray.GetAt(index);
m_ObArray.RemoveAt(index);
m_pModifiedCount--;
}
UpdateAllViews(NULL);
SetModifiedFlag();
}
d.文件操作 2.6 设计与算法
个人认为此画图程序最有提处的设计在于其结构的清晰,可读性较好。
下面从程序的存储说起:
void CDooDleDoc::Serialize(CArchive& ar) //序列化
...{
if (ar.IsStoring())
...{
// TODO: add storing code here
m_ObArray.Serialize(ar);
}
else
...{
// TODO: add loading code here
m_ObArray.Serialize(ar);
}
}
m_ObArray的类型为CObArray,是一个类似容器的封装MFC中的预定义类。而m_ObArray存储的CShape(图元基类),Serialize是virtual类型的,因此保存文件时程序会动态调用Serialize函数。以椭圆为例:
void CEllipse::Serialize(CArchive& ar)
...{
if(ar.IsStoring())...{
ar<<m_pFirstCorner.x<<m_pFirstCorner.y<<m_pSecondCorner.x
<<m_pSecondCorner.y;
}
else...{
ar>>m_pFirstCorner.x>>m_pFirstCorner.y>>m_pSecondCorner.x
>>m_pSecondCorner.y;
}
CShape::Serialize(ar);
}
同样将各种画出图形存储时也是非常的方便。
void CDooDleDoc::AddShape(CShape* pShape)
...{
//CLine* pLine = new CLine(pStart,pEnd,Width,Style,Color);
m_ObArray.Add(pShape);
SetModifiedFlag();
m_pModifiedCount++;
}
3.设计总结
3.1.存在的问题与不足及对策
在处理曲线、圆弧和多边型绘画成型的问题存在缺陷,本程序中曲线和圆弧的画图方法是鼠标单击4次后右击,相应的图形才会出现,多边型单击次数大于两次后右击,才会出现图形,不够实用、方便。相信随着MFC学习的深入将会解决这个以及与次类似的问题
3.2.收获
经过一周的MFC学习和编程,对MFC有了大致的了解,能够编写一般的MFC应用程序。对事件驱动程序运行的过程也有较深刻的印象。
4 使用说明(操作手册)
4.1打开(.dle)格式文件
4.2画图
在工具栏或绘图惨淡中选择适当的图形,可以在选项菜单中选择线条类型和颜色
4.3保存
5 附录
void CDooDleView::OnLButtonUp(UINT nFlags, CPoint point)
...{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&point);//滚动条坐标转换代码
dc.SelectStockObject(NULL_BRUSH);
if(m_Drag)...{
m_Drag =
0;
ReleaseCapture();
ClipCursor(NULL);
CDooDleDoc* pDoc = GetDocument();
CShape* pShape;
if(pDoc->CurrentDraw == DRAW_LINE)...{//直线
pShape =
new CLine(m_pOrigin,point,pDoc->m_pWidth,pDoc->m_pStyle,pDoc->m_pColor);//所画直线数据
}
if(pDoc->CurrentDraw == DRAW_RECTANGLE)...{//矩形
pShape =
new CRectangle(m_pOrigin,point,pDoc->m_pWidth,pDoc->m_pStyle,pDoc->m_pColor);
}
if(pDoc->CurrentDraw == DRAW_ROUNDRECT)...{//圆矩形
int r = (abs(m_pOrigin.x-point.x)+abs(m_pOrigin.y-point.y))/6;
pShape =
new CRoundRect(m_pOrigin,point,r,pDoc->m_pWidth,pDoc->m_pStyle,pDoc->m_pColor);
}
if(pDoc->CurrentDraw == DRAW_FILLRECT)...{//填充矩形
pShape =
new CFillRect(m_pOrigin,point,pDoc->m_pWidth,pDoc->m_pStyle,pDoc->m_pColor,
pDoc->m_pFColor,pDoc->m_pHatch,pDoc->m_pHatchFlag);
}
if(pDoc->CurrentDraw == DRAW_CIRCLE)...{//圆
pShape =
new CCircle(m_pOrigin,m_pPrev,pDoc->m_pWidth,pDoc->m_pStyle,pDoc->m_pColor);
}
if(pDoc->CurrentDraw == DRAW_ELLIPSE)...{//椭圆
pShape =
new CEllipse(m_pOrigin,m_pPrev,pDoc->m_pWidth,pDoc->m_pStyle,pDoc->m_pColor);
}
pDoc->AddShape(pShape);//保存图形数据
pDoc->UpdateAllViews(NULL);
}
CScrollView::OnLButtonUp(nFlags, point);
}
欢迎大家评论! |