MFC课程设计实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《面向对象可视化对象编程》课程设计
总结报告
班级:
学号:
姓名:
2016.12.12-2016.12.23
目录
一、课程设计的目的 (3)
二、课程设计的内容与设计思路 (3)
1.课设内容 (3)
2.设计思路 (4)
三、程序实现过程与细节 (5)
1.涉及的主要函数列表 (5)
2.工程的新建 (7)
3.建立图元属性对话框 (8)
4.控件的关联 (9)
5.枚举型 (10)
6.定义动态数组 (12)
7.建立Shape类及其子类 (12)
8.OnDraw() (16)
9. 鼠标左键消息响应函数 (17)
10.鼠标右键双击消息响应函数 (18)
11.颜色按钮 (18)
12.获取鼠标点击处的逻辑坐标 (19)
13.对话框中控件的显示与隐藏 (20)
14.文档的存取 (21)
四、运行效果 (21)
1.编译运行,按下Ctrl+鼠标左键 (21)
2.选择文本,弹出角度框 (22)
3.创建正方形、圆形、文本 (22)
4.创建三角形和椭圆 (23)
5.单击鼠标左键修改正方形和文本属性 (23)
6.右键双击删除三角形 (24)
7.保存退出 (25)
五、设计小结 (25)
六、主要代码清单 (25)
1.Shape.h (25)
2.Shape.cpp (29)
3.LwhView.cpp (44)
一、课程设计的目的
1.参加本课程设计的同学已经学习了《C语言程序设计》和《面向对象可视化编程》两门课程,现在需要通过一个相对实际性的开发过程来巩固与鉴定一下学习成效,可以查看离实际需要还有哪些部分没有完全掌握,需要加强检测;
2.本课程设计可以提供一个稍微具有规模的程序开发的例子,让同学们可以体会到程序的构思、编码以及调试的完整过程,最后并总结课程设计的过程;
3.通过本次课程设计,可以对自身做一个评估,看看在哪方面不足从而加强学习;
二、课程设计的内容与设计思路
1.课设内容
要求:采用单文档方式,文档中存储图形画面的各个图元数据,视图负责图形的绘制。
文档支持图形的序列化(连载),提供新建、打开、保存等操作。
视图除了绘制图形,还提供图形交互,能够按住Ctrl键再鼠标左键单击来创建图元,鼠标左键双击编辑修改图元属性,鼠标右键双击删除图元。
图元创建与修改时的参数由参数对话框来编辑。
创建时以鼠标左击时光标的所在位置作为基点来创建图元。
w
w
h
r
h
w
w
Square
Rectangle
Triangle
Circle Ellipse
Y a n
g t z
e U
n i v
e r s
i t y
a
Text
h
2.设计思路
我们的最终目的是显示一个单文档窗口,且可利用从对话框中输入的数据绘制图形。
所以,首先建立一个单文档程序,再添加对话框,用来创建与修改图形参数,之后给对话框中的各复选框,编辑框,按钮添加消息响应函数,进行控件关联,并利用枚举型使参数传递。
定义一个动态数组以存储从对话框中获取的数据,之后添加Shape类,用来绘图,由Shape类定义一个指针指向动态数组,便可从中读出之前存储的数据进行绘图,从而达到目的,思路图参考如图1,2:
图1.Shape的六个派生类
图2.工程思路图解
三、程序实现过程与细节
1.涉及的主要函数列表
附表1
函数定义与功能一览表
序号函数名函数定义
定义所在文
件名
函数功能
1 OnInitDialog() BOOL CType::OnInitDialog() Type.cpp 对对话框进行初始化处理
2 OnOk()void CType::OnOK() Type.cpp 按确定按钮时调用
3 OnFillColorButton() void CType::OnFillColorButton() Type.cpp
按下按钮,弹出颜色选择对话框
4 OnLinelColorButton() void CType::OnLineColorButton() Type.cpp
按下按钮,弹出颜色选择对话框
5 OnDraw() void CLwhView::OnDraw(CDC* pDC) LwhView.cpp 应用程序窗口的客户区进行
图3.主要函数OnLButtonDown()
2.工程的新建
打开Microsoft Visual C++ 6.0 —> 点击File —> New 在Projects中选择MFC AppWizard (exe) ;在Project name中输入工程的名字Lwh,在Location中选择工程存放的路径。
填完后点击OK按钮。
填完后点击OK按钮,在弹出来的对话框中我们选择Single document,再点击Finish,完成工程的创建。
之后编译运行,结果参见图3。
图4.新建工程结果示意图
3.建立图元属性对话框
点击ResouceView,右击Dialog—>插入Dialog,这时会弹出来一个对话框,双击“确定”按钮,选择“Create a new class”,点击OK,设置类名为CType—>OK,之后设置对话框属性为IDD_TYType,参见图4,绘制对话框,参见附表2.属性表给各复选框、编辑框、按钮修改属性。
附表2
属性表
图5.构造对话框结果示意图
4.控件的关联
要实现这个步骤,首先要明白在MFC中变量的声明定义,对于控件关联型的数值变量,value类型(double,int,CString等等),在生成时向导帮你做了3件事:
1)在.h文件中进行声明;
2)在.cpp中的构造函数中,进行了初始化;
3)在.cpp文件中的DoDataExchange()中进行控件关联;
DDX_Text(pDX, IDOK, m_btnTest);
所以,要进行控件关联,要做的也是这三件事(可在ClassWizard中进行添加,则系统自动生成。
下面介绍手动添加,以图元类型IDC_m_ComBox_TuYuanType 为例)
1)在Type.h中声明:
protected:
CComboBox m_ComBox_TuYuanType;
2)在Type.cpp中进行初始化:
BOOL CType::OnInitDialog() (在ClassWizard中添加)
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
m_ComBox_TuYuanType.AddString("正方形");
m_ComBox_TuYuanType.AddString("矩形");
m_ComBox_TuYuanType.AddString("三角形");
m_ComBox_TuYuanType.AddString("圆");
m_ComBox_TuYuanType.AddString("椭圆");
m_ComBox_TuYuanType.AddString("文本");
m_ComBox_TuYuanType.SetCurSel(0);
}
3)在Type.cpp中进行控件关联(DoDataExchange()中):
DDX_Control(pDX, IDC_ComBox_TuYuanType, m_ComBox_TuYuanType);
5.枚举型
枚举类型定义的一般形式为:enum 枚举名{ 枚举值表 }。
在枚举值表中应罗列出所有可用值。
这些值也称为枚举元素。
注意枚举值是常量,不是变量,不能再对它赋值。
枚举元素本身由系统定义了一个表示序号的数值,从0开始顺序定义为0,1,2……
1)定义(Type.h)
public:
EnumTuYuanTyp m_TuYuanTyp;
2)枚举(Type.h)
enum EnumTuYuanTyp
{
EnumTuYuanTyp_Square,//正方形
EnumTuYuanTyp_Rectangle,//矩形
EnumTuYuanTyp_Triangle,//三角形
EnumTuYuanTyp_Circle,// 圆
EnumTuYuanTyp_Ellipse,// 椭圆
EnumTuYuanTyp_Text// 文本
};
3)利用枚举型传参(Type.cpp)
void CType::OnOK()
{
UpdateData();
// TODO: Add extra validation here
int iSel=m_ComBox_TuYuanType.GetCurSel();//得到当前选择的索引值 switch(iSel)
{
case 0:
m_TuYuanTyp=EnumTuYuanTyp_Square;
break;
case 1:
m_TuYuanTyp=EnumTuYuanTyp_Rectangle;
break;
case 2:
m_TuYuanTyp=EnumTuYuanTyp_Triangle;
break;
case 3:
m_TuYuanTyp=EnumTuYuanTyp_Circle;
break;
case 4:
m_TuYuanTyp=EnumTuYuanTyp_Ellipse;
break;
case 5:
m_TuYuanTyp=EnumTuYuanTyp_Text;
break;
default:
ASSERT(0);
}
CDialog::OnOK();
}
6.定义动态数组
1)定义(LwhDoc.h)
public:
CObArray m_Elements;
2)清除(LwhDoc.cpp)
//清除图元地址,释放空间
CLwhDoc::~CLwhDoc()
{
for(int i=0;i<m_Elements.GetSize();i++)
{
delete m_Elements[i];
m_Elements[i]=NULL;
}
m_Elements.RemoveAll();
}
7.建立Shape类及其子类
一个类要支持支持序列化Serialize,必须从CObject派生,并且在类的声明(.h文件)中包含DECLARE_SERIAL申明,在类的实现(.cpp)中包含IMPLEMENT_SERIAL申明。
所以,要建立支持序列化的Shape类,首先选择
ClassView,鼠标右键单击工程名,选择New Class,在类的类型中选择Generic Class,输入类名CShape,并在下方Derived From中输入CObject,继承类型为public,点击确定,系统会生成相应的Shape.cpp文件和Shape.h文件。
在Shape.h中定义其成员变量和成员函数,注意OnDraw函数应定义为纯虚函数(参见附表 1.函数定义与功能一览表)。
然后由Shape类派生其六个子类CSquare,CRectangle,CTriangle,CCircle,CEllipse,CText,继承方式均为public,在子类中也定义其成员函数及变量(以CSquare为例)
class CShape : public CObject
{
public:
CShape();
virtual ~CShape();
virtual void Draw(CDC*pDC)=0;//绘制图元
virtual bool IsMatched(CPoint pnt)=0;//点是否落在图形内部
virtual void Serialize(CArchive& ar) = 0;
int OrgX;
int OrgY;
int width;
int high;
int linewidth;
int R1,R2,G1,G2,B1,B2;
};
class CSquare:public CShape
{
public:
CSquare();
CSquare(int x,int y,int w,int line,int r1,int g1,int b1,int r2,int b2,int g2);
void Draw(CDC*pDC);//绘制
bool IsMatched(CPoint pnt);//重载点pnt是否落在图元内
virtual void Serialize(CArchive& ar );//序列化正方形图元
private:
DECLARE_SERIAL(CSquare)//声明类CSquare支持序列化
};
在Shape.cpp中对Shape类极其子类进行序列化,并写入子类的成员函数,完成绘图和进行图元匹配功能(以CSquare为例)
IMPLEMENT_SERIAL(CSquare, CObject, 1)//实现类CSquare的序列化,指定版本为1
void CSquare::Serialize(CArchive &ar)
{
if (ar.IsStoring())
{
ar << OrgX<< OrgY;//原点坐标
ar <<width;
ar<< linewidth;//线宽
}
else
{
ar >> OrgX >>OrgY;//原点坐标
ar >>width;
ar >> linewidth;//线宽
}
}
CSquare::CSquare()//缺省构造函数,初始化
{
OrgX = 400;//原点坐标
OrgY = 400;
linewidth= 1;//线宽
width = 100;
}
CSquare::CSquare(int x, int y, int w,int line,int r1,int g1,int b1,int r2,int b2,int g2)
{
OrgX = x;//原点坐标
OrgY = y;
linewidth=line;
width = w;
R1=r1;
R2=r2;
G1=g1;
G2=g2;
B1=b1;
B2=b2;
}
void CSquare::Draw(CDC*pDC)//绘制函数
{
CPen pen, *pOldPen;
pen.CreatePen(PS_SOLID, linewidth,RGB(R1,G1,B1));
pOldPen = (CPen*)pDC->SelectObject(&pen);
CBrush brush, *pOldBrush;
brush.CreateHatchBrush(HS_DIAGCROSS, RGB(R2,G2,B2));
pOldBrush = (CBrush*)pDC->SelectObject(&brush);
pDC->Rectangle(OrgX - width / 2, OrgY -width / 2, OrgX + width / 2, OrgY + width / 2);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
}
bool CSquare::IsMatched(CPoint pnt)//图元匹配函数
{
if ((OrgX-width/2 <= pnt.x && pnt.x <= OrgX + width/2) && (OrgY - width/2 <= pnt.y && pnt.y <= OrgY+width/2))
return true;
else
return false;
}
8.OnDraw()
由于Shape.cpp调用了Ondraw()函数,而OnDraw()函数的定义是在LwhView.cpp中(参见附表1.函数定义与功能一览表),故应该在LwhView.cpp 中对Ondraw()进行调用声明,代码如下:
void CLwhView::OnDraw(CDC* pDC)
{
CLwhDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CShape* p=NULL;
if (pDoc->m_Elements.GetSize() > 0)
{
for (int i=0; i < pDoc->m_Elements.GetSize(); i++)
{
p = (CShape*)pDoc->m_Elements[i];
p->Draw(pDC);
}
}
// TODO: add draw code for native data here
}
9. 鼠标左键消息响应函数
按下Ctrl+W组合键,在弹出的MFC ClassWizard 对话框中选择Message Map,在Class name选择CLwhView类,在Object ID中选择CLwhView,在右边的Messages中为其添加鼠标左键的消息响应函数OnLButtonDown,双击OnLButtonDown函数(参见附表1.函数定义与功能一览表),出现OnLButtonDown ()的定义模块,写入以下代码:
CType dlg;
if ((nFlags&MK_CONTROL) == MK_CONTROL)//Ctrl键按下
dlg.DoModal();
即可实现在单文档运行界面按下Ctrl+鼠标左键弹出对话框的操作,但是,要实现当弹出对话框按下OK键就可以画出图形的操作,就得利用枚举型传过来的参数进行选择判断(switch语句),然后执行画图操作(以CSquare为例)if (dlg.DoModal() == IDOK)
{
switch(dlg.m_TuYuanTyp)
{
case EnumTuYuanTyp_Square:
{
p = new CSquare(dlg.X,dlg.Y,dlg.Width,dlg.LineWidth,
dlg.LineColorR,dlg.LineColorG,dlg.LineColorB,
dlg.FillColorR,dlg.FillColorG,dlg.FillColorB);
break;
}
……
}
}
当不按下Ctrl键,直接按左键,要进行修改图元属性的功能,则也是在此处添加相应代码,对应之前的按下Ctrl键的if语句,写入else语句,添加重新绘图的功能代码即可。
(具体见主要代码清单)
10.鼠标右键双击消息响应函数
与添加鼠标左键消息相应的方法一样(参见附表1.函数定义与功能一览表),先在ClassWizard中添加,双击进入定义模块,要实现右键双击删除,并弹出一个警告是否删除的对话框,首先得明白我们基于图元的数据存储在于动态数组m_Elements,所以,要删除图元,只需删除该图元对应数组中存储的数据即可,主要代码如下:
for (int i=0;i < pDoc->m_Elements.GetSize(); i++)
{
p = (CShape*)pDoc->m_Elements[i];
if (p->IsMatched(pntLogical))
{
CCut cut;
if(cut.DoModal()==IDOK)
{
pDoc->m_Elements.RemoveAt(i);
delete p;
Invalidate();
}
}
}
11.颜色按钮
CColorDialog类实现了标准的颜色对话框,因此用创建CColorDialog类的对象去调用DoModal()函数,即可显示出对话框,如果DoModal()返回IDOK,则用GetColor()来获取颜色对话框中选择的颜色值,以下是线色按钮的相关代码:
void CType::OnLineColorButton()
{
// TODO: Add your control notification handler code here
COLORREF color = RGB(47, 78, 107);// 颜色对话框的初始颜色
CColorDialog colorDlg(color); // 构造颜色对话框,传入初始颜色值 if (IDOK == colorDlg.DoModal())
{
color = colorDlg.GetColor();// 获取颜色对话框中选择的颜色值 SetDlgItemInt(IDC_LineColorR, GetRValue(color)); // 在线色编辑框中显示所选颜色的R分量值
SetDlgItemInt(IDC_LineColorG, GetGValue(color));// 在线色编辑框中显示所选颜色的G分量值
SetDlgItemInt(IDC_LineColorB, GetBValue(color));// 在线色编辑框中显示所选颜色的B分量值
}
}
12.获取鼠标点击处的逻辑坐标
函数:Point();
函数功能:该函数检取光标的位置,以屏幕坐标表示;
函数原型:BOOL GetCursorPos(LPPOINT lpPoint);
参数:IpPoint; (参见附表1.函数定义与功能一览表)
POINT结构指针:接收光标的屏幕坐标;
代码如下:
CType::CType(CWnd* pParent /*=NULL*/)
: CDialog(CType::IDD, pParent)
{
POINT point;
GetCursorPos(&point);
X = point.x;
Y = point.y;
……
}
13.对话框中控件的显示与隐藏
首先要清楚控件的显示与隐藏是基于对其他控件进行操作,在该工程中,要实现我在图元属性组合框中选择“文本”,则出现角度框,而选择其他则不出现角度框,所以,应对该组合框添加消息相应函数,在ClassWizard中,选中IDC_m_ComBox_TuYuanType(参见附表1.函数定义与功能一览表),选择Messages 为CBN_CELCHANGE,双击进入定义模块,写入如下代码:
void CType::OnSelchangeComBoxTuYuanType()
{
// TODO: Add your control notification handler code here
int iSel=m_ComBox_TuYuanType.GetCurSel();//得到当前选择的索引值
switch(iSel)
{
case 0:
case 1:
case 2:
case 3:
case 4:
GetDlgItem(IDC_STATIC1)->ShowWindow(SW_HIDE);//隐藏角度框
GetDlgItem(IDC_Angle)->ShowWindow(SW_HIDE);
break;
case 5:
GetDlgItem(IDC_STATIC1)->ShowWindow(SW_SHOW);//显示角度框
GetDlgItem(IDC_Angle)->ShowWindow(SW_SHOW);
break;
default:
ASSERT(0);
break;
}
Invalidate();
}
14.文档的存取
文档的存储主要通过文档类重载成员函数Serialize来实现。
void COovpExam1Doc::Serialize(CArchive& ar)
{
m_Elements.Serialize(ar);//其中m_Elements是文档用来保存图元对象的数组
}
四、运行效果
1.编译运行,按下Ctrl+鼠标左键
图6.按下Ctrl+鼠标键结果示意图
2.选择文本,弹出角度框
图7.角度框的显示结果示意图3.创建正方形、圆形、文本
图8.创建图形结果示意图1
4.创建三角形和椭圆
图9.创建图形结果示意图5.单击鼠标左键修改正方形和文本属性
图10.修改图形属性结果示意图
6.右键双击删除三角形
图11.弹出删除警告窗口结果示意图
图12.删除三角形结果示意图
7.保存退出
五、设计小结
1.通过这次实验,进一步加深了我对类的运用,使我大概了解了构造函数和析构函数在程序中的应用,这次查找错处也使我更小心去注意程序的细节问题。
2.即使在MFC中,MFC虽然是VC++中的一个特色,对我来说还是有很多的地方并不了解。
我对VC++缺乏整体上的认识,我只是在程式化的执行它。
比如说,在系统已给的类的搭建,类中成员函数的插入,已有类的功能等等诸多,我的了解尚为浅薄。
3.通过这次实验至少得到了认识和了解windows绘图的功能,比如: CDC类和CObject类以及其派生类的应用,还在实验中通过调用OnDraw函数绘制不同尺寸、颜色、风格的几个图形和图位。
但是要想熟练掌握还需要大量的实践。
4.通过这次实验我掌握了动态数组的应用,动态数组相对于静态数组来说可以更加有效利用存储空间。
而这也是我以前没有掌握的知识。
5.面向对象的操作要求思路清晰,过程严谨,就好似一个连环扣,缺一环而不可。
这次实验中我深刻地了解到了编写程序的思路与实验过程,我很珍惜这次经验。
6.最后,感谢那些给予我帮助的老师和同学们!大家辛苦了!
六、主要代码清单
1.Shape.h
// Shape.h: interface for the CShape class.
//
///////////////////////////////////////////////////////////////////// /
#include "afx.h"
#include "Type.h"
#include "math.h"
#if !defined(AFX_SHAPE_H__9F3D8253_0729_4802_9938_EDAA421048A0__INCLU DED_)
#define AFX_SHAPE_H__9F3D8253_0729_4802_9938_EDAA421048A0__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CShape : public CObject
{
public:
CShape();
virtual ~CShape();
virtual void Draw(CDC*pDC)=0;//绘制图元
virtual bool IsMatched(CPoint pnt)=0;//点是否落在图形内部
virtual void Serialize(CArchive& ar) = 0;
int OrgX;
int OrgY;
int width;
int high;
int linewidth;
int R1,R2,G1,G2,B1,B2;
};
class CSquare:public CShape
{
public:
CSquare();
CSquare(int x,int y,int w,int line,int r1,int g1,int b1,int r2,int b2,int g2);
void Draw(CDC*pDC);//绘制
bool IsMatched(CPoint pnt);//重载点pnt是否落在图元内
virtual void Serialize(CArchive& ar );//序列化正方形图元
private:
DECLARE_SERIAL(CSquare)//声明类CSquare支持序列化
};
class CRectangle:public CShape
{
public:
CRectangle();
CRectangle(int x,int y,int w,int h,int line,int r1,int g1,int b1,int r2,int b2,int g2);
void Draw(CDC*pDC);//绘制
bool IsMatched(CPoint pnt);//重载点pnt是否落在图元内
virtual void Serialize(CArchive& ar );//序列化正方形图元
private:
DECLARE_SERIAL(CRectangle)//声明类CRectangle支持序列化
};
class CTriangle:public CShape
{
public:
CTriangle();
CTriangle(int x,int y,int w,int h,int line,int r1,int g1,int b1,int r2,int b2,int g2);
void Draw(CDC*pDC);//绘制
bool IsMatched(CPoint pnt);//重载点pnt是否落在图元内
virtual void Serialize(CArchive& ar );//序列化正方形图
private:
DECLARE_SERIAL(CTriangle)//声明类CTriangle支持序列化
};
class CCircle:public CShape
{
public:
CCircle();
CCircle(int x,int y,int w,int line,int r1,int g1,int b1,int r2,int b2,int g2);
void Draw(CDC*pDC);//绘制
bool IsMatched(CPoint pnt);//重载点pnt是否落在图元内
virtual void Serialize(CArchive& ar );//序列化正方形图
private:
DECLARE_SERIAL(CCircle)//声明类CCircle支持序列化
};
class CEllipse:public CShape
{
public:
CEllipse();
CEllipse(int x,int y,int w,int h,int line,int r1,int g1,int b1,int
r2,int b2,int g2);
void Draw(CDC*pDC);//绘制
bool IsMatched(CPoint pnt);//重载点pnt是否落在图元内
virtual void Serialize(CArchive& ar );//序列化正方形图
private:
DECLARE_SERIAL(CEllipse)//声明类CEllipse支持序列化
};
class CText:public CShape
{
public:
CText();
CText(int x,int y,int r1,int g1,int b1,int a);
void Draw(CDC*pDC);//绘制
bool IsMatched(CPoint pnt);//重载点pnt是否落在图元内
virtual void Serialize(CArchive& ar );//序列化正方形图
private:
int angle;
DECLARE_SERIAL(CText)//声明类CText支持序列化
};
#endif
// !defined(AFX_SHAPE_H__9F3D8253_0729_4802_9938_EDAA421048A0__INCLUD ED_)
2.Shape.cpp
// Shape.cpp: implementation of the CShape class.
//
///////////////////////////////////////////////////////////////////// /
#include "afx.h"
#include "stdafx.h"
#include "Lwh.h"
#include "Shape.h"
#include "Type.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
///////////////////////////////////////////////////////////////////// /
// Construction/Destruction
///////////////////////////////////////////////////////////////////// /
IMPLEMENT_SERIAL(CSquare, CObject, 1)//实现类CSquare的序列化,指定版本为1
IMPLEMENT_SERIAL(CCircle, CObject, 1)
IMPLEMENT_SERIAL(CRectangle, CObject, 1)
IMPLEMENT_SERIAL(CEllipse, CObject, 1)
IMPLEMENT_SERIAL(CTriangle, CObject, 1)
IMPLEMENT_SERIAL(CText, CObject, 1)
CShape::CShape()
{
}
CShape::~CShape()
{
}
//正方形
void CSquare::Serialize(CArchive &ar) {
if (ar.IsStoring())
{
ar << OrgX<< OrgY;//原点坐标
ar <<width;
ar<< linewidth;//线宽
}
else
{
ar >> OrgX >>OrgY;//原点坐标
ar >>width;
ar >> linewidth;//线宽
}
}
CSquare::CSquare()//缺省构造函数,初始化{
OrgX = 400;//原点坐标
OrgY = 400;
linewidth= 1;//线宽
width = 100;
CSquare::CSquare(int x, int y, int w,int line,int r1,int g1,int b1,int r2,int b2,int g2)
{
OrgX = x;//原点坐标
OrgY = y;
linewidth=line;
width = w;
R1=r1;
R2=r2;
G1=g1;
G2=g2;
B1=b1;
B2=b2;
}
void CSquare::Draw(CDC*pDC)//绘制函数
{
CPen pen, *pOldPen;
pen.CreatePen(PS_SOLID, linewidth,RGB(R1,G1,B1));
pOldPen = (CPen*)pDC->SelectObject(&pen);
CBrush brush, *pOldBrush;
brush.CreateHatchBrush(HS_DIAGCROSS, RGB(R2,G2,B2));
pOldBrush = (CBrush*)pDC->SelectObject(&brush);
pDC->Rectangle(OrgX - width / 2, OrgY -width / 2, OrgX + width / 2, OrgY + width / 2);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
bool CSquare::IsMatched(CPoint pnt)//图元匹配函数
{
if ((OrgX-width/2 <= pnt.x && pnt.x <= OrgX + width/2) && (OrgY - width/2 <= pnt.y && pnt.y <= OrgY+width/2))
return true;
else
return false;
}
//矩形
void CRectangle::Serialize(CArchive &ar)
{
if (ar.IsStoring())
{
ar <<OrgX<< OrgY;//原点坐标
ar <<width;
ar <<high;
ar<< linewidth;//线宽
}
else
{
ar >> OrgX >>OrgY;//原点坐标
ar >>width;
ar >>high;
ar >> linewidth;//线宽
}
}
CRectangle::CRectangle()//缺省构造函数,初始化
{
OrgX = 400;//原点坐标
OrgY = 400;
linewidth= 1;//线宽
width = 100;
high=50;
}
CRectangle::CRectangle(int x,int y,int w,int h,int line,int r1,int g1,int b1,int r2,int b2,int g2)
{
OrgX = x;//原点坐标
OrgY = y;
linewidth=line;
width = w;
high=h;
R1=r1;
R2=r2;
G1=g1;
G2=g2;
B1=b1;
B2=b2;
}
void CRectangle::Draw(CDC*pDC)//绘制函数
{
CPen pen, *pOldPen;
pen.CreatePen(PS_SOLID, linewidth,RGB(R1,G1,B1));
pOldPen = (CPen*)pDC->SelectObject(&pen);
CBrush brush, *pOldBrush;
brush.CreateHatchBrush(HS_DIAGCROSS, RGB(R2,G2,B2));
pOldBrush = (CBrush*)pDC->SelectObject(&brush);
pDC->Rectangle(OrgX - width / 2, OrgY - high / 2, OrgX + width / 2, OrgY +high / 2);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
}
bool CRectangle::IsMatched(CPoint pnt)//图元匹配函数
{
if ((OrgX - width / 2 <= pnt.x && pnt.x <= OrgX + width / 2) && (OrgY - high / 2 <= pnt.y && pnt.y <= OrgY + high / 2))
return true;
else
return false;
}
//三角形
void CTriangle::Serialize(CArchive &ar)
{
if (ar.IsStoring())
{
ar << OrgX << OrgY;//原点坐标
ar << width;
ar << high;
ar << linewidth;//线宽
}
else
{
ar >> OrgX >> OrgY;//原点坐标
ar >> width;
ar >> high;
ar >> linewidth;//线宽
}
}
CTriangle::CTriangle()//缺省构造函数,初始化
{
OrgX = 400;//原点坐标
OrgY = 400;
linewidth= 1;//线宽
width = 100;
high=50;
}
CTriangle::CTriangle(int x,int y,int w,int h,int line,int r1,int g1,int b1,int r2,int b2,int g2)
{
OrgX = x;//原点坐标
OrgY = y;
linewidth=line;
width = w;
high=h;
R1=r1;
R2=r2;
G1=g1;
G2=g2;
B1=b1;
B2=b2;
}
void CTriangle::Draw(CDC*pDC)//绘制函数
{
CPen pen, *pOldPen;
pen.CreatePen(PS_SOLID, linewidth,RGB(R1,G1,B1));
pOldPen = (CPen*)pDC->SelectObject(&pen);
CBrush brush, *pOldBrush;
brush.CreateHatchBrush(HS_DIAGCROSS, RGB(R2,G2,B2));
pOldBrush = (CBrush*)pDC->SelectObject(&brush);
POINT polygon[3] = {{OrgX,OrgY-2*high/3},{OrgX-width/2,OrgY+high/3},{OrgX+width/2,OrgY+h igh/3}};
pDC->Polygon(polygon,3);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
}
bool CTriangle::IsMatched(CPoint pnt)//图元匹配函数
{
if ((OrgX - high <= pnt.x && pnt.x <= OrgX + high) && (OrgY - ((sqrt(3)/2)* high) <= pnt.y && pnt.y <= OrgY + (sqrt(3) / 2)* high)) return true;
else
return false;
}
//圆
void CCircle::Serialize(CArchive &ar)
{
if (ar.IsStoring())
{
ar << OrgX<< OrgY;//原点坐标
ar <<width;
ar<< linewidth;//线宽
}
else
{
ar >> OrgX >>OrgY;//原点坐标
ar >>width;
ar >> linewidth;//线宽
}
}
CCircle::CCircle()//缺省构造函数,初始化
{
OrgX = 400;//原点坐标
OrgY = 400;
linewidth= 1;//线宽
width = 100;
}
CCircle::CCircle(int x,int y,int w,int line,int r1,int g1,int b1,int r2,int b2,int g2)
{
OrgX = x;//原点坐标
OrgY = y;
linewidth=line;
width = w;
R1=r1;
R2=r2;
G1=g1;
G2=g2;
B1=b1;
B2=b2;
}
void CCircle::Draw(CDC*pDC)//绘制函数
{
CPen pen, *pOldPen;
pen.CreatePen(PS_SOLID, linewidth,RGB(R1,G1,B1));
pOldPen = (CPen*)pDC->SelectObject(&pen);
CBrush brush, *pOldBrush;
brush.CreateHatchBrush(HS_DIAGCROSS, RGB(R2,G2,B2));
pOldBrush = (CBrush*)pDC->SelectObject(&brush);
pDC->Ellipse(OrgX - width / 2, OrgY -width / 2, OrgX + width / 2, OrgY + width / 2);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
}
bool CCircle::IsMatched(CPoint pnt)//图元匹配函数
{
if ((OrgX - width / 2 <= pnt.x && pnt.x <= OrgX + width/ 2) && (OrgY - width / 2 <= pnt.y && pnt.y <= OrgY + width / 2))
return true;
else
return false;
}
//椭圆
void CEllipse::Serialize(CArchive &ar)
{
if (ar.IsStoring())
{
ar << OrgX<< OrgY;//原点坐标
ar << width;
ar << high;
ar<< linewidth;//线宽
}
else
{
ar >> OrgX >>OrgY;//原点坐标
ar >> width;
ar >> high;
ar >> linewidth;//线宽
}
}
CEllipse::CEllipse()//缺省构造函数,初始化
{
OrgX = 400;//原点坐标
OrgY = 400;
linewidth= 1;//线宽
width = 100;
high=50;
}
CEllipse::CEllipse(int x,int y,int w,int h,int line,int r1,int g1,int b1,int r2,int b2,int g2)
{
OrgX = x;//原点坐标
OrgY = y;
linewidth=line;
width = w;
high=h;
R1=r1;
R2=r2;
G1=g1;
G2=g2;
B1=b1;
B2=b2;
}
void CEllipse::Draw(CDC*pDC)//绘制函数
{
CPen pen, *pOldPen;
pen.CreatePen(PS_SOLID, linewidth,RGB(R1,G1,B1));
pOldPen = (CPen*)pDC->SelectObject(&pen);
CBrush brush, *pOldBrush;
brush.CreateHatchBrush(HS_DIAGCROSS, RGB(R2,G2,B2));
pOldBrush = (CBrush*)pDC->SelectObject(&brush);
pDC->Ellipse(OrgX - width / 2, OrgY - high / 2, OrgX + width / 2, OrgY +high / 2);
pDC->SelectObject(pOldPen);
pDC->SelectObject(pOldBrush);
}
bool CEllipse::IsMatched(CPoint pnt)//图元匹配函数
{
if ((OrgX-width/2 <= pnt.x && pnt.x <= OrgX + width/2) && (OrgY - high/2 <= pnt.y && pnt.y <= OrgY+high/2))
return true;
else
return false;
}
//文本
void CText::Serialize(CArchive &ar)
{
if (ar.IsStoring())
{
ar << OrgX<< OrgY;//原点坐标
ar<< linewidth;//线宽
}
else
{
ar >> OrgX >>OrgY;//原点坐标
ar >> linewidth;//线宽
}
}
CText::CText()//缺省构造函数,初始化
{
OrgX = 400;//原点坐标
OrgY = 400;
}
CText::CText(int x,int y,int r1,int g1,int b1,int a) {
OrgX = x;//原点坐标
OrgY = y;
R1=r1;
G1=g1;
B1=b1;
angle=a;
}
void CText::Draw(CDC*pDC)//绘制函数
{
CFont * pNewFont=new CFont;
CFont * pOldFont;
pNewFont->CreateFont(30,20,angle,0,
200,FALSE,1,FALSE,
ANSI_CHARSET,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
DEFAULT_PITCH&FF_SWISS,
"Aerial");
pOldFont=(CFont *)pDC->SelectObject(pNewFont);
pDC->SetTextColor(RGB(R1,G1,B1));
pDC->TextOut(OrgX,OrgY,"Yangtze University!");
}
bool CText::IsMatched(CPoint pnt)//图元匹配函数
{
if ((OrgX <= pnt.x ) && (OrgY <= pnt.y ))
return true;
else
return false;
}
3.LwhView.cpp
// LwhView.cpp : implementation of the CLwhView class
//
#include "stdafx.h"
#include "Lwh.h"
#include "math.h"
#include "LwhDoc.h"
#include "LwhView.h"
#include "Type.h"
#include "Shape.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
///////////////////////////////////////////////////////////////////// ////////
// CLwhView
IMPLEMENT_DYNCREATE(CLwhView, CView)
BEGIN_MESSAGE_MAP(CLwhView, CView)
//{{AFX_MSG_MAP(CLwhView)
ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDBLCLK()
//}}AFX_MSG_MAP
// Standard printing commands
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()
///////////////////////////////////////////////////////////////////// ////////
// CLwhView construction/destruction
CLwhView::CLwhView()
{
// TODO: add construction code here
}
CLwhView::~CLwhView()
{
}
BOOL CLwhView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
///////////////////////////////////////////////////////////////////// ////////
// CLwhView drawing
void CLwhView::OnDraw(CDC* pDC)
{
CLwhDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CShape* p;
if (pDoc->m_Elements.GetSize() > 0)
{
for (int i=0; i < pDoc->m_Elements.GetSize(); i++)
{
p = (CShape*)pDoc->m_Elements[i];
p->Draw(pDC);
}
}
// TODO: add draw code for native data here
}
///////////////////////////////////////////////////////////////////// ////////
// CLwhView printing
BOOL CLwhView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CLwhView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {
// TODO: add extra initialization before printing
}
void CLwhView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {
// TODO: add cleanup after printing
}
///////////////////////////////////////////////////////////////////// ////////
// CLwhView diagnostics
#ifdef _DEBUG
void CLwhView::AssertValid() const
{
CView::AssertValid();
}
void CLwhView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CLwhDoc* CLwhView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CLwhDoc)));
return (CLwhDoc*)m_pDocument;
}
#endif //_DEBUG
///////////////////////////////////////////////////////////////////// ////////
// CLwhView message handlers
void CLwhView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CLwhDoc* pDoc = GetDocument();
CClientDC dc(this);
CPoint pntLogical = point;
OnPrepareDC(&dc);
dc.DPtoLP(&pntLogical);//DP->LP进行转换
CType dlg;
CShape* p=NULL;
if ((nFlags&MK_CONTROL) == MK_CONTROL)//Ctrl键按下
{
if (dlg.DoModal() == IDOK)
{
switch(dlg.m_TuYuanTyp)
{
case EnumTuYuanTyp_Square:
{
p = new CSquare(dlg.X,dlg.Y,dlg.Width,dlg.LineWidth,
dlg.LineColorR,dlg.LineColorG,dlg.LineColorB,
dlg.FillColorR,dlg.FillColorG,dlg.FillColorB);
break;
}
case EnumTuYuanTyp_Rectangle:
{
p = new CRectangle(dlg.X,dlg.Y,dlg.Width,dlg.High,dlg.LineWidth,
dlg.LineColorR,dlg.LineColorG,dlg.LineColorB,
dlg.FillColorR,dlg.FillColorG,dlg.FillColorB);
break;
}
case EnumTuYuanTyp_Triangle:
{
p = new CTriangle(dlg.X,dlg.Y,dlg.Width,dlg.High,dlg.LineWidth,
dlg.LineColorR,dlg.LineColorG,dlg.LineColorB,
dlg.FillColorR,dlg.FillColorG,dlg.FillColorB);
break;
}
case EnumTuYuanTyp_Circle:
{
p = new CCircle(dlg.X,dlg.Y,dlg.Width,dlg.LineWidth,
dlg.LineColorR,dlg.LineColorG,dlg.LineColorB,
dlg.FillColorR,dlg.FillColorG,dlg.FillColorB);
break;
}
case EnumTuYuanTyp_Ellipse:
{
p = new CEllipse(dlg.X,dlg.Y,dlg.Width,dlg.High,dlg.LineWidth,
dlg.LineColorR,dlg.LineColorG,dlg.LineColorB,
dlg.FillColorR,dlg.FillColorG,dlg.FillColorB);
break;
}
case EnumTuYuanTyp_Text:。