1、利用面向对象中的多态性实现画圆和画方形的操作
设计模式课,老师要给了我们一个DELPHI程序,要求改写成自己喜欢的语言的程序,说以后所讲的模式将通过在这个例子程序上一点点的添加来体现。
而我看不懂DELPHI程序,以前对MFC接触少,也不是很熟悉。在QQ上,宿舍同学和我一起交流了DELPHI程序的分析看法,实验室的学长在VC图形处理上,及MFC的使用上给了我非常有益的指导,开启了我学习MFC的大门,非常感谢学长和室友的帮助。现在将这个小程序写出来,以作纪念。
一、实现需求和功能描述
如图所示:
点击“画圆”和“画矩形”按钮,则会在画布上画圆和画矩形。当用鼠标点击到圆内或矩形内时,则会输出如图中的对话框,显示是什么图形,及其面积。
二、实现过程及重点地方
1、实现过程
涉及到一个基类(TShape),两个派生类(TCircle,TRectangle);另外还有一个类,用来承担画图形的抽象过程,及存储所画的所有图形的指针,以便输出面积时查询当前点所处的域及刷新当前的所有图形,我们用TShapeList来表示这个类。
具体过程如下图中所示:
2、重点地方
本次实现的重点地方是:
1)如何将所画的图形保存,用什么形式进行保存,以方便以后的查询。
2)对于鼠标所点位置进行处于那一个域的判断。
对于第二个问题,只需一一将鼠标位置与当前在于TShapeList类的存储数据进行比较,选择第一个匹配的进行计算输出。
if(List.GetShapeCount()>=1)
{
aShape=List.Intersect(point);
CString str=aShape->GetName();
double area=aShape->GetArea();
CString output,strr;
strr.Format("我的面积是:%f!",area);
output=str+strr;
bool flag=aShape->Intersect(point);
if(flag)
MessageBox(output);
++++++++++++++++++++++++++++++++++++++++++
TShape* TShapeList::Intersect(CPoint aPoint)
{
for(int i=0;i<GetShapeCount();i++)
if(GetShapes(i)->Intersect(aPoint))
{
return GetShapes(i);
}
return GetShapes(0);
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
bool TRectangle::Intersect(CPoint aPoint)
{
return ((aPoint.x>FLeftTop.x) && (aPoint.x<FRightBottom.x) && (aPoint.y>FLeftTop.y) && (aPoint.y<FRightBottom.y));
}
对于第一个问题,我们选择vector来进行操作,因为vector最常用,也最好用。当然可选择的数据类型也很多,如哈希类;还可以自己定义一个指向基类的指针数组或链表。
private:
std::vector<TShape*> FShapeList;
++++++++++++++++++++++++++++++++++++++++
void TShapeList::Add(TShape *aShape)
{
FShapeList.push_back(aShape);
}
三、实现结果
用VC++实现如图所示:
四、实现程序说明
1、类的定义部分
class TShape
{
public:
virtual void Draw(CDC *pDC){}
virtual bool Intersect(CPoint aPoint){return FALSE;}
virtual double GetArea(void){return 0.0;}
void SetName(const CString Value);
CString GetName();
private:
CString FName;
};
class TShapeList
{
public:
TShapeList();
~TShapeList();
void Add(TShape *aShape);
void Draw(CDC *pDC);
TShape* Intersect(CPoint aPoint);
int GetShapeCount();
TShape* GetShapes(int iIndex);
private:
std::vector<TShape*> FShapeList;
};
class TCircle:public TShape
{
public:
TCircle();
TCircle(CPoint aCenter,int aRadius);
~TCircle();
void Draw(CDC *pDC);
double GetArea(void);
bool Intersect(CPoint aPoint);
private:
CPoint FCenter;
int FRadius;
};
class TRectangle:public TShape
{
public:
TRectangle(CPoint aLeftTop,CPoint aRightBottom);
~TRectangle() {}
void Draw(CDC *pDC);
double GetArea(void);
bool Intersect(CPoint aPoint);
private:
CPoint FLeftTop;
CPoint FRightBottom;
};
2、类的实现部分
//TShape的实现
void TShape::SetName(const CString Value)
{
FName=Value;
}
CString TShape::GetName()
{
return FName;
}
//TCircle的实现
TCircle::TCircle()
{
FCenter=CPoint(0,0);
FRadius=10;
}
TCircle::TCircle(CPoint aCenter,int aRadius)
{
FCenter=aCenter;
FRadius=aRadius;
}
double TCircle::GetArea(void)
{
return Pi*(FRadius*FRadius);
}
bool TCircle::Intersect(CPoint aPoint)
{
return ((aPoint.x>=(FCenter.x-FRadius)) &&
(aPoint.x<=(FCenter.x+FRadius)) && (aPoint.y>=(FCenter.y-FRadius)) && (aPoint.y<=(FCenter.y+FRadius)));
}
void TCircle::Draw(CDC *MyCircle)
{
//CClientDC *MyCircle;
//COLORREF BackColor=MyCircle.GetBkColor();
CBrush *nullBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
//CBrush *pCBrush=new CBrush(BackColor);
//pCBrush->CreateSolidBrush(BackColor);
MyCircle->SelectObject(nullBrush);
CPen pen(PS_SOLID,3,0x00FF0000);
MyCircle->SelectObject(&pen);
MyCircle->Ellipse(FCenter.x-FRadius,FCenter.y-FRadius,FCenter.x+FRadius,FCenter.y+FRadius);
}
//RTectangle的实现
TRectangle::TRectangle(CPoint aLeftTop,CPoint aRightBottom)
{
FLeftTop=aLeftTop;
FRightBottom=aRightBottom;
}
void TRectangle::Draw(CDC *MyCircle)
{
//COLORREF BackColor=MyCircle.GetBkColor();
CBrush *nullBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
//CBrush *pCBrush=new CBrush(BackColor);
//pCBrush->CreateSolidBrush(BackColor);
MyCircle->SelectObject(nullBrush);
CPen pen(PS_SOLID,3,0x00FF0000);
MyCircle->SelectObject(&pen);
MyCircle->Rectangle(FLeftTop.x,FLeftTop.y,FRightBottom.x,FRightBottom.y);
}
double TRectangle::GetArea()
{
return (FLeftTop.x-FRightBottom.x)*(FLeftTop.y-FRightBottom.y);
}
bool TRectangle::Intersect(CPoint aPoint)
{
return ((aPoint.x>FLeftTop.x) && (aPoint.x<FRightBottom.x) && (aPoint.y>FLeftTop.y) && (aPoint.y<FRightBottom.y));
}
//TShapeList的实现
TShapeList::TShapeList()
{
//FShapeList.begin();
}
TShapeList::~TShapeList()
{
FShapeList.clear();
}
int TShapeList::GetShapeCount()
{
return FShapeList.size();
}
TShape* TShapeList::GetShapes(int iIndex)
{
return (FShapeList[iIndex]);
}
void TShapeList::Add(TShape *aShape)
{
FShapeList.push_back(aShape);
}
void TShapeList::Draw(CDC *pDC)
{
int i;
for(i=0;i<GetShapeCount();i++)
GetShapes(i)->Draw(pDC);
}
TShape* TShapeList::Intersect(CPoint aPoint)
{
for(int i=0;i<GetShapeCount();i++)
if(GetShapes(i)->Intersect(aPoint))
{
return GetShapes(i);
}
return GetShapes(0);
}
3、画图处理
+++++++++++++画圆+++++++++++++++++
void CCircleTestDlg::OnCircle()
{
// TODO: Add your control notification handler code here
TShape *AShape=new TCircle(CPoint(rand()%480,rand()%300),10+rand()%100);
char buffer[20];
CDC *pDC= new CClientDC(this);
_itoa(rand()%200,buffer,10);
CString TName=(CString)"我的名字是Circle"+buffer+";";
AShape->SetName(TName);
AShape->Draw(pDC);
List.Add(AShape);
}
+++++++++++++++++++++画方形+++++++++++++++++++++
void CCircleTestDlg::OnTRectangle()
{
// TODO: Add your control notification handler code here
int a,b,offset,offset1;
a=rand()%450;
b=rand()%250;
offset=rand()%100+20;
offset1=offset+rand()%100+10;
TShape *AShape=new TRectangle(CPoint(a,b),CPoint(a+offset1,b+offset));
char buffer[20];
CDC *pDC= new CClientDC(this);
_itoa(rand()%200,buffer,10);
CString TName=(CString)"我的名字是TRectangle"+buffer+";";
AShape->SetName(TName);
AShape->Draw(pDC);
List.Add(AShape);
}
+++++++++++++++单击的处理+++++++++++++++++++++++
void CCircleTestDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
TShape *aShape;
//输出一下坐标
char buffer3[20],buffer4[20];
int a,b;
a=point.x;
b=point.y;
_itoa(a,buffer3,10);
_itoa(b,buffer4,10);
CString s3=(CString)"我的坐标是:"+buffer3+" and "+buffer4;
MessageBox(s3);
//判断是在那个图形内,并返回当前图形数据存放的地址
if(List.GetShapeCount()>=1)
{
aShape=List.Intersect(point);
CString str=aShape->GetName();
double area=aShape->GetArea();
CString output,strr;
strr.Format("我的面积是:%f!",area);
output=str+strr;
bool flag=aShape->Intersect(point);
if(flag)
MessageBox(output);
}//
CDialog::OnLButtonDown(nFlags, point);
}
++++++++++++++++刷新+++++++++++++++++++++++
//TShape *aShape;
CDC *pDC= new CClientDC(this);
List.Draw(pDC);
//注意:在OnPaint()函数中
++++++++++++全局变量+++++++++++++++++
TShapeList List;