📄 draw.cpp
字号:
#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 + -