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;

发布了208 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/hopegrace/article/details/104168331