⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 draw.cpp

📁 Viaual C++实战演练一书的源代码,对于C++程序员有实际的借鉴意义.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"
#include "resource.h"       // main symbols

#include "Draw.h"
#include "math.h"

#define MAXOFFSET 2 // 定义输入点与真实点最大误差值
					// 在AtPoint和AtLine函数中使用

//-----------------------------
// 以下为CDrawObject类方法实现
//-----------------------------

IMPLEMENT_SERIAL(CDrawObject, CObject, 1);

COLORREF CDrawObject::GetPenColor()
{
	if(this)
	{//当前类为有效类指针
		return m_PenColor;
	}
	else
	{
		return 0;
	}
}

void CDrawObject::SetPenColor(COLORREF color)
{
	if(this)
	{//当前类为有效类指针
		m_PenColor = color;
	}
}

void CDrawObject::HotPoint(CDC *pDC, long x, long y)
{
	COLORREF XorColor = pDC->GetBkColor();
	CBrush brush(XorColor), *oldbrush;
	CPen pen(PS_SOLID, 1, XorColor), *oldpen;
	int oldmode = pDC->GetROP2();
	oldpen = pDC->SelectObject(&pen);
	oldbrush = pDC->SelectObject(&brush);
	pDC->SetROP2(R2_XORPEN);

	pDC->Rectangle(x-2, y-2, x+2, y+2);

	pDC->SelectObject(oldpen);
	pDC->SelectObject(oldbrush);
	pDC->SetROP2(oldmode);
	pen.DeleteObject();//释放笔资源
	brush.DeleteObject();//释放画刷资源
}

bool CDrawObject::AtPoint(long x1, long y1, long x, long y)
{
	double d;//两点距离

	d = sqrt((double)(x1-x)*(x1-x)+(y1-y)*(y1-y));

	return(d < MAXOFFSET);
}

bool CDrawObject::AtLine(long x1, long y1, long x2, long y2, long x, long y)
{
	float A, B, C, d;

	A = (float)(y1-y2);
	B = (float)(x2-x1);
	C = (float)(x1*y2 - x2*y1);
	d = (A*x+B*y+C) * (A*x+B*y+C) / (A*A+B*B);//在直线上

	return(d < MAXOFFSET && ((x1-x)*(x2-x)<0 || (y1-y)*(y2-y)<0));
}


//--------------------------------
//以下为CDrawLine(绘线)类方法实现
//--------------------------------

IMPLEMENT_SERIAL(CDrawLine, CDrawObject, 1);

void CDrawLine::Serialize(CArchive& ar)
{
	COLORREF color;

	if(ar.IsLoading())
	{
		ar >> m_nStyle >> color >> m_x1 >> m_y1 >> m_x2 >> m_y2;
		SetPenColor(color);
	}
	else
	{
		color = GetPenColor();
		ar << m_nStyle << color << m_x1 << m_y1 << m_x2 << m_y2;
	}
}

CDrawLine::CDrawLine(COLORREF color)
{
	m_x1=m_y1=m_x2=m_y2=0;
	SetPenColor(color);
	m_nStyle = IDT_LINE;
}

void CDrawLine::Draw(CDC* pDC)
{
	if(!this)
	{//当前类为空,既无效类指针
		return;
	}

	COLORREF CopyColor = GetPenColor();
	CPen pen(PS_SOLID, 1, CopyColor), *oldpen;
	int oldmode = pDC->GetROP2();
	oldpen = pDC->SelectObject(&pen);
	pDC->SetROP2(R2_COPYPEN);

	pDC->MoveTo(m_x1, m_y1);//移动当前绘图点为线段第一点
	pDC->LineTo(m_x2, m_y2);//绘制直线

	pDC->SelectObject(oldpen);
	pDC->SetROP2(oldmode);
	pen.DeleteObject();//释放笔资源
}

int CDrawLine::NewPoint(long x, long y)
{
	m_x1 = m_x2 = x;
	m_y1 = m_y2 = y;

	return 2;
}

int CDrawLine::SelectAt(long x, long y)
{

	if(AtPoint(m_x1, m_y1, x, y))
	{//指针靠近第一点
		return 1;
	}
	else if(AtPoint(m_x2, m_y2, x, y))
	{//指针靠近第二点
		return 2;
	}
	else if(AtLine(m_x1, m_y1, m_x2, m_y2, x, y))
	{//指针在直线上
		m_oldx = x;//保存当前点位置,用于以后判断移动的距离
		m_oldy = y;
		return 3;
	}
	else 
		return 0;
}

void CDrawLine::MoveAt(CDC *pDC, int flags, long x, long y)
{
	//以下设置DC
	COLORREF XorColor = pDC->GetBkColor() ^ GetPenColor();
	CPen pen(PS_SOLID, 1, XorColor), *oldpen;
	int oldmode = pDC->GetROP2();
	oldpen = pDC->SelectObject(&pen);
	pDC->SetROP2(R2_XORPEN);
	//以下移动直线
	if(m_bSelected)
	{//以前已经选择了,取消热点
		HotPoints(pDC);
	}
	pDC->MoveTo(m_x1, m_y1);
	pDC->LineTo(m_x2, m_y2);//删除原图形

	//修改新图形坐标
	if(flags == 1)
	{
		m_x1 = x, m_y1 = y;
	}else if(flags == 2)
	{
		m_x2 = x, m_y2 = y;
	}else if(flags == 3)
	{
		m_x1 += x-m_oldx;
		m_x2 += x-m_oldx;
		m_y1 += y-m_oldy;
		m_y2 += y-m_oldy;
		m_oldx = x;
		m_oldy = y;
	}

	pDC->MoveTo(m_x1, m_y1);
	pDC->LineTo(m_x2, m_y2);//绘新图形

	if(m_bSelected)
	{//以前已经选择了,设置热点
		HotPoints(pDC);
	}
	//以下恢复DC
	pDC->SetROP2(oldmode);
	pDC->SelectObject(oldpen);
	pen.DeleteObject();//释放笔资源
}

void CDrawLine::HotPoints(CDC* pDC)
{
	HotPoint(pDC, m_x1, m_y1);
	HotPoint(pDC, m_x2, m_y2);
}

void CDrawLine::Selected(CDC *pDC, bool select)
{
	if(!this)
	{//如果类指针无效,直接返回
		return;
	}

	if(select)
	{
		if(!m_bSelected)
		{//以前未选择,绘热点并设置选择标志
			HotPoints(pDC);
			m_bSelected = true;
		}
	}
	else
	{
		if(m_bSelected)
		{//以前已经选择了,取消热点设置并清选择标志
			HotPoints(pDC);
			m_bSelected = false;
		}
	}
}


//-----------------------------------
// 以下为CDrawRect(绘矩形)类方法实现
//-----------------------------------

IMPLEMENT_SERIAL(CDrawRect, CDrawObject, 1);

void CDrawRect::Serialize(CArchive& ar)
{
	COLORREF color;

	if(ar.IsLoading())
	{
		ar >> m_nStyle >> color >> m_x1 >> m_y1 >> m_x2 >> m_y2;
		SetPenColor(color);
	}
	else
	{
		color = GetPenColor();
		ar << m_nStyle << color << m_x1 << m_y1 << m_x2 << m_y2;
	}
}

CDrawRect::CDrawRect(COLORREF color)
{
	m_x1=m_y1=m_x2=m_y2=0;
	SetPenColor(color);
	m_nStyle = IDT_RECTANGLE;
}

void CDrawRect::Draw(CDC* pDC)
{
	if(!this)
	{//当前类为空,既无效类指针
		return;
	}

	COLORREF CopyColor = GetPenColor();
	CPen pen(PS_SOLID, 1, CopyColor), *oldpen;
	int oldmode = pDC->GetROP2();
	oldpen = pDC->SelectObject(&pen);//指定绘制笔
	pDC->SetROP2(R2_COPYPEN);//指定绘制模式

	pDC->MoveTo(m_x1, m_y1);
	pDC->LineTo(m_x1, m_y2);
	pDC->LineTo(m_x2, m_y2);
	pDC->LineTo(m_x2, m_y1);
	pDC->LineTo(m_x1, m_y1);

	pDC->SelectObject(oldpen);//恢复DC
	pDC->SetROP2(oldmode);
	pen.DeleteObject();//释放笔资源
}

int CDrawRect::NewPoint(long x, long y)
{
	m_x1 = m_x2 = x;
	m_y1 = m_y2 = y;

	return 4;
}

int CDrawRect::SelectAt(long x, long y)
{
	if(AtPoint(m_x1, m_y1, x, y))
	{//指针靠近左上角点
		return 1;
	}
	else if(AtPoint(m_x2, m_y1, x, y))
	{//指针靠近右上角点
		return 2;
	}
	else if(AtPoint(m_x1, m_y2, x, y))
	{//指针靠近左下角点
		return 3;
	}
	else if(AtPoint(m_x2, m_y2, x, y))
	{//指针靠近右下角点
		return 4;
	}
	else if(AtLine(m_x1, m_y1, m_x1, m_y2, x, y)
		 || AtLine(m_x1, m_y1, m_x2, m_y1, x, y)
		 || AtLine(m_x1, m_y2, m_x2, m_y2, x, y)
		 || AtLine(m_x2, m_y1, m_x2, m_y2, x, y))
	{//指针在矩形上
		m_oldx = x;
		m_oldy = y;
		return 5;
	}
	else 
		return 0;
}

void CDrawRect::MoveAt(CDC *pDC, int flags, long x, long y)
{
	//以下设置DC
	COLORREF XorColor = pDC->GetBkColor() ^ GetPenColor();
	CPen pen(PS_SOLID, 1, XorColor), *oldpen;
	int oldmode = pDC->GetROP2();
	oldpen = pDC->SelectObject(&pen);
	pDC->SetROP2(R2_XORPEN);
	if(m_bSelected)
	{//以前已经选择了,取消热点
		HotPoints(pDC);
	}
	//首先删除原矩形
	pDC->MoveTo(m_x1, m_y1);
	pDC->LineTo(m_x1, m_y2);
	pDC->LineTo(m_x2, m_y2);
	pDC->LineTo(m_x2, m_y1);
	pDC->LineTo(m_x1, m_y1);

	//修改新图形坐标
	if(flags == 1)
	{//移动左上角
		m_x1 = x, m_y1 = y;
	}else if(flags == 2)
	{//移动右上角
		m_x2 = x, m_y1 = y;
	}else if(flags == 3)
	{//移动左下角
		m_x1 = x, m_y2 = y;
	}else if(flags == 4)
	{//移动右下角
		m_x2 = x, m_y2 = y;
	}else if(flags == 5)
	{//移动矩形
		m_x1 += x-m_oldx;
		m_x2 += x-m_oldx;
		m_y1 += y-m_oldy;
		m_y2 += y-m_oldy;
		m_oldx = x;
		m_oldy = y;
	}

	//绘新图形
	pDC->MoveTo(m_x1, m_y1);
	pDC->LineTo(m_x1, m_y2);
	pDC->LineTo(m_x2, m_y2);
	pDC->LineTo(m_x2, m_y1);
	pDC->LineTo(m_x1, m_y1);

	if(m_bSelected)
	{//以前已经选择了,设置热点
		HotPoints(pDC);
	}
	//以下恢复DC
	pDC->SetROP2(oldmode);
	pDC->SelectObject(oldpen);
	pen.DeleteObject();//释放笔资源
}

void CDrawRect::HotPoints(CDC* pDC)
{
	HotPoint(pDC, m_x1, m_y1);// 1
	HotPoint(pDC, m_x2, m_y1);// 2
	HotPoint(pDC, m_x1, m_y2);// 3
	HotPoint(pDC, m_x2, m_y2);// 4
}

void CDrawRect::Selected(CDC *pDC, bool select)
{
	if(!this)
	{//如果类指针无效,直接返回
		return;
	}

	if(select)
	{
		if(!m_bSelected)
		{//以前未选择,绘热点并设置选择标志
			HotPoints(pDC);
			m_bSelected = true;
		}
	}
	else
	{
		if(m_bSelected)
		{//以前已经选择了,取消热点设置并清选择标志
			HotPoints(pDC);
			m_bSelected = false;
		}
	}
}

/*void CDrawRect::Selected(CDC *pDC, bool select)
{
	if(!this)
	{//如果类指针无效,直接返回
		return;
	}

	if(select ^ m_bSelected)
		HotPoints(pDC);

	m_bSelected = select;
}*/


//-------------------------------------
// 以下为CDrawEllipse(绘椭圆)类方法实现
//-------------------------------------

IMPLEMENT_SERIAL(CDrawEllipse, CDrawObject, 1);

void CDrawEllipse::Serialize(CArchive& ar)
{
	COLORREF color;

	if(ar.IsLoading())
	{
		ar >> m_nStyle >> color >> m_x1 >> m_y1 >> m_x2 >> m_y2;
		SetPenColor(color);
	}
	else
	{
		color = GetPenColor();
		ar << m_nStyle << color << m_x1 << m_y1 << m_x2 << m_y2;
	}
}

CDrawEllipse::CDrawEllipse(COLORREF color)
{
	m_x1=m_y1=m_x2=m_y2=0;
	SetPenColor(color);
	m_nStyle = IDT_ELLIPSE;
}

void CDrawEllipse::Draw(CDC* pDC)
{
	if(!this)
	{//当前类为空,既无效类指针
		return;
	}

	COLORREF CopyColor = GetPenColor();
	CPen pen(PS_SOLID, 1, CopyColor);
	int oldmode = pDC->GetROP2();
	CPen* oldpen = pDC->SelectObject(&pen);//指定绘制笔;
	//设置为“空”刷,既不填充。
	CBrush* oldbrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);;
	pDC->SetROP2(R2_COPYPEN);//指定绘制模式

	pDC->Ellipse(m_x1, m_y1, m_x2, m_y2);//绘椭圆

	//恢复DC
	pDC->SetROP2(oldmode);
	pDC->SelectObject(oldpen);
	pDC->SelectObject(oldbrush);
	pen.DeleteObject();//释放笔资源
}

int CDrawEllipse::NewPoint(long x, long y)
{
	m_x1 = m_x2 = x;
	m_y1 = m_y2 = y;

	return 4;
}

int CDrawEllipse::SelectAt(long x, long y)
{
	if(AtPoint(m_x1, m_y1, x, y))
	{//指针靠近左上角点
		return 1;
	}
	else if(AtPoint(m_x2, m_y1, x, y))
	{//指针靠近右上角点
		return 2;
	}
	else if(AtPoint(m_x1, m_y2, x, y))
	{//指针靠近左下角点
		return 3;
	}
	else if(AtPoint(m_x2, m_y2, x, y))
	{//指针靠近右下角点
		return 4;
	}
	else if(AtCurve(x, y))
	{//指针在椭圆上
		m_oldx = x;
		m_oldy = y;
		return 5;
	}
	else 
		return 0;
}

void CDrawEllipse::MoveAt(CDC *pDC, int flags, long x, long y)
{
	//以下设置DC
	COLORREF XorColor = pDC->GetBkColor() ^ GetPenColor();
	CPen pen(PS_SOLID, 1, XorColor);
	int oldmode = pDC->GetROP2();
	CPen* oldpen = pDC->SelectObject(&pen);
	//设置为“空”刷,既不填充。
	CBrush* oldbrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
	pDC->SetROP2(R2_XORPEN);

	if(m_bSelected)
	{//以前已经选择了,取消热点
		HotPoints(pDC);
	}
	//首先删除原椭圆
	pDC->Ellipse(m_x1, m_y1, m_x2, m_y2);

	//修改新图形坐标
	if(flags == 1)
	{//移动左上角
		m_x1 = x, m_y1 = y;
	}else if(flags == 2)
	{//移动右上角
		m_x2 = x, m_y1 = y;
	}else if(flags == 3)
	{//移动左下角
		m_x1 = x, m_y2 = y;
	}else if(flags == 4)
	{//移动右下角
		m_x2 = x, m_y2 = y;
	}else if(flags == 5)
	{//移动椭圆
		m_x1 += x-m_oldx;
		m_x2 += x-m_oldx;
		m_y1 += y-m_oldy;
		m_y2 += y-m_oldy;
		m_oldx = x;
		m_oldy = y;
	}

	//绘新图形
	pDC->Ellipse(m_x1, m_y1, m_x2, m_y2);//绘椭圆

	if(m_bSelected)
	{//以前已经选择了,设置热点
		HotPoints(pDC);
	}
	//以下恢复DC
	pDC->SetROP2(oldmode);
	pDC->SelectObject(oldpen);
	pDC->SelectObject(oldbrush);
	pen.DeleteObject();
}

void CDrawEllipse::HotPoints(CDC* pDC)
{
	HotPoint(pDC, m_x1, m_y1);// 1
	HotPoint(pDC, m_x2, m_y1);// 2
	HotPoint(pDC, m_x1, m_y2);// 3
	HotPoint(pDC, m_x2, m_y2);// 4
}

void CDrawEllipse::Selected(CDC *pDC, bool select)
{
	if(!this)
	{//如果类指针无效,直接返回
		return;
	}

	if(select)
	{
		if(!m_bSelected)
		{//以前未选择,绘热点并设置选择标志
			HotPoints(pDC);
			m_bSelected = true;
		}
	}
	else
	{
		if(m_bSelected)
		{//以前已经选择了,取消热点设置并清选择标志
			HotPoints(pDC);
			m_bSelected = false;
		}
	}
}

bool CDrawEllipse::AtCurve(long x, long y)
{
	double fx1, fy1, fx2, fy2;
	double a, b, c;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -