# 基于MFC实现的图形绘图编辑系统
# 一、课程设计目的
- 学完《C语言程序设计》和《面向对象可视化编程》两门课程之后,进入到实践环节,通过一个简单的MFC的绘图程序来运用自己所学的知识,学会解决编程中遇到的问题。
- 本课程设计可以提供一个稍微具有规模的程序开发的例子,让同学们可以体会到程序的构思、编码以及调试的完整过程,最后并总结课程设计的过程。
- 通过本次课程设计,增强了自己对程序设计的认识,在不足的方面加强学习。
# 二、课程设计的内容与设计思路
## 2.1课程设计内容
- 编写一个简单的图形编辑MFC程序,可以添加,修改与删除图形元素,以形成图形画面,如图2-1所示
![](http://www.writebug.com/myres/static/uploads/2021/10/19/60468c7d768ace1e839ed6a7c1e67c46.writebug)
- 图上的黑点给图元的原点,w为宽度width,h为高度height,r为半径radius,a为字符角度angle。这些为这些图元需要保存的参数,另外,每个图元是否填充,用什么模式填充
- 采用单文档方式,文档中存储图形画面的各个图元数据,视图负责图形的绘制
- 文档支持图形的序列化(连载),提供新建、打开、保存等操作
- 视图除了绘制图形,还提供图形交互,能够按住Ctrl键再鼠标左键单击来创建图元,鼠标左键双击编辑修改图元属性,鼠标右键双击删除图元
- 图元创建与修改时的参数由参数对话框来编辑,参见对话框示例图2-2,创建时以鼠标左击时光标的所在位置作为基点来创建图元
![](http://www.writebug.com/myres/static/uploads/2021/10/19/98b84a0f3bde2971236472fc936d9c06.writebug)
## 2.2 设计思路
使用图元基础类shape作为所有六个图元类的基类,设计派生各个具体的图形类,要求支持上述功能,各个类之间的关系如图2-3 所示。
![](http://www.writebug.com/myres/static/uploads/2021/10/19/8eb5ff69e1495d1c514cf6513e2b3dad.writebug)
# 三、程序实现过程与细节
## 3.1 程序涉及到的函数列表及程序流程图
**函数定义与功能一览表**
| 函数 序号 | 函数名 | 函数定义 | 函数定义所在文件 | 函数功能 |
| ------ | ---------------------- | ---------------------------------------- | ---------------------------------------- | ---------- |
| 1 | OnInitDialog() | BOOL WAttribute::OnInitDialog() | WAttribute.Cpp | 初始化对话框 |
| 2 | OnCbnSelchangeCombo() | Void WAttribute::OnCbnSelchangeCombo() | WAttribute.Cpp | 选择图形类型 |
| 3 | OnBnClickedLinecolor() | void WAttribute::OnBnClickedLinecolor() | WAttribute.Cpp | 选择颜色 |
| 4 | OnBnClickedOk() | void WAttribute::OnBnClickedOk() | WAttribute.Cpp | ok控件消息 |
| 5 | ~CWDemoDoc() | CWDemoDoc::~CWDemoDoc() | WDemoDoc.cpp | 析构动态数组 |
| 6 | Serialize() | void CWDemoDoc::Serialize(CArchive& ar) | WDemoDoc.cpp | 序列化函数 |
| 7 | OnLButtonDown() | void CWDemoView::OnLButtonDown(UINT nFlags, CPoint point) | WDemoView.cpp | 左键功能函数 |
| 8 | OnDraw() | void CWDemoView::OnDraw(CDC* pDC) | WDemoView.cpp | 绘图函数 |
| 9 | OnRButtonDblClk() | Void CWDemoView::OnRButtonDblClk(UINT nFlags, CPoint point) | WDemoView.cpp | 右键功能函数 |
| 10 | WShape() | WShape::WShape() | WShape.cpp | 图元基类默认构造函数 |
| 11 | WSquare() | WSquare::WSquare(int x, int y, int w) | WSquare.cpp | 正方形类有参构造函数 |
| 12 | WRectangle() | WRectangle::WRectangle(int x, int y, int w, int h) | WRectangle.cpp | 矩形类有参构造函数 |
| 13 | Wcircle() | WCircle::WCircle(int x, int y, int r) | WCircle.cpp | 圆形类有参构造函数 |
| 14 | WEllipse() | WEllipse::WEllipse(int x, int y, int hr, int vr) | WEllipse.cpp | 椭圆形类有参构造函数 |
| 15 | WTriangle | WTriangle::WTriangle(int x, int y, int length) | WTriangle.cpp | 三角形类有参构造函数 |
| 16 | WText() | WText::WText(int x, int y, CString content) | WText.cpp | 文本类有参构造函数 |
| 17 | Draw() | Void WSquare:: Draw(CDC * pDC) Void WRectangle:: Draw(CDC * pDC) Void WCircle:: Draw(CDC * pDC) Void WEllipse:: Draw(CDC * pDC) void WTriangle::Draw(CDC * pDC) void WText::Draw(CDC * pDC) | WSquare.cpp WRectangle.cpp WCircle.cpp WEllipse.cpp WTriangle.cpp WText.cpp | 各种图形的绘制函数 |
| 18 | Serialize() | void WSquare::Serialize(CArchive & ar) void WRectangle::Serialize(CArchive & ar) void WCircle::Serialize(CArchive & ar) void WEllipse::Serialize(CArchive & ar) void WTriangle::Serialize(CArchive & ar) void WText::Serialize(CArchive & ar) | WSquare.cpp WRectangle.cpp WCircle.cpp WEllipse.cpp WTriangle.cpp WText.cpp | 各种图形的序列化函数 |
| 19 | IsMatched() | bool WSquare::IsMatched(CPoint pnt) bool WRectangle::IsMatched(CPoint pnt) bool WCircle::IsMatched(CPoint pnt) bool WEllipse::IsMatched(CPoint pnt) bool WTriangle::IsMatched(CPoint pnt) bool WText::IsMatched(CPoint pnt) | WSquare.cpp WRectangle.cpp WCircle.cpp WEllipse.cpp WTriangle.cpp WText.cpp | 图元匹配函数 |
| 20 | SetAttribute() | void WSquare::SetAttribute(int nX, int nY, COLORREF nBoderColor, int nBoderType, int nBoderWidth, COLORREF nFillColor, int nFillType) … void WText::SetAttribute(int nX, int nY, COLORREF nBoderColor, int nBoderType, int nBoderWidth, COLORREF nFillColor, int nFillType) | WSquare.cpp WRectangle.cpp WCircle.cpp WEllipse.cpp WTriangle.cpp WText.cpp | 重置图元属性值函数 |
**程序流程图**
![](http://www.writebug.com/myres/static/uploads/2021/10/19/431d05fc02addd3e11a149b98c583efb.writebug)
## 3.2 课程设计实现过程
### 3.2.1 选择高级视图
由于老师平时上课时,使用的都是经典的基础视图,而课程设计文档中的视图是高级视图,对比运行的视图,我尝试着把程序的视图设为和课程设计文档里面一样的(可参见图4-1)
### 3.2.2 设计类和对话框
#### 3.2.2.1 设计类
![](http://www.writebug.com/myres/static/uploads/2021/10/19/c757d90c399f0db871055062ea1846a4.writebug)
自己创建一个WShape(以W开头便于和MFC的类区分)图元类,派生图元类单独创建.h和.cpp文件,便于管理,虽然切换有些麻烦,但后期修改很方面,我没有像示例程序里面那样把所有的类都放在shape文件里面。
**基类是WShape**
- 数据成员:
- 原点坐标(鼠标点击的点)
- 旋转角度(单独为文本类设计,其他图形不使用)
- 和线以及填充有关的属性字段
- 成员函数
- 有参数的构造函数
- 绘制图元的函数
- 判断鼠标点击的位置是否在图形内部的函数,是否打开属性设计窗口
- 序列化数据的函数
- 重新设置图元的属性的函数
注意:要在每个派生类的.h头文件里面声明该类型支持序列化,并在.cpp源文件里面指定序列化的版本。
例如:
**矩形类**
```c++
DE