Entity类成员变量
public: COLORREF m_brushcolor;//填充颜色
实现方法:
public:
void Fill(COLORREF color){ m_brushcolor = color; };
派生类实现:
void MRectangle::Draw(CDC * pDC, int drawMode )
{…
CBrush* pOldBrush = pDC->SelectObject(&brush);
pDC->Rectangle(rect);
…}
1.填充消息响应
VCadView.h
protected:
//{{AFX_MSG(CVCadView)
afx_msg void OnModifyEntity(UINT m_nID);
afx_msg void OnUpdateModifyCommand(CCmdUI* pCmdUI);
VCadView.cpp
BEGIN_MESSAGE_MAP(CVCadView, CView) ON_COMMAND_RANGE(ID_MODIFY_MOVE, ID_MODIFY_FILL, OnModifyEntity) ON_UPDATE_COMMAND_UI_RANGE(ID_MODIFY_MOVE, ID_MODIFY_FILL, OnUpdateModifyCommand) END_MESSAGE_MAP()
消息响应
void CVCadView::OnModifyEntity(UINT m_nID)
{
switch(m_nID)
{
case ID_MODIFY_MIRROR:
{// 镜像
m_pCmd = new CMirror();
break;
}
case ID_MODIFY_FILL:
{// 填充
m_pCmd = new CFill();
break;
}
default:
//删除
Erase() ;
break;
}
}
填充操作类实现
CFill::CFill()
{
CColorDialog ccd(SeedClr, CC_SOLIDCOLOR);
if (IDOK == ccd.DoModal())//调用颜色对话框选取填充色
SeedClr = ccd.GetColor();
//::prompt("请输入移动的目标点:单击鼠标右键取消");
CDC* pDC = g_pView->GetDC(); // 获得视类的设备环境指针
// 将选择集中的图元移动到目标位置并进行绘制
int i, n;
for (n = g_pDoc->m_selectArray.GetSize(), i = 0; i < n; i++)
{
MEntity* pEntity = (MEntity*)g_pDoc->m_selectArray[i];
pEntity->Draw(pDC, dmInvalid); // 清除原来位置上的图元
MEntity * pNewEnt = pEntity->Copy();
pNewEnt->Fill(SeedClr);
pNewEnt->Draw(pDC, dmNormal); // 在目标位置上绘制图元
g_pDoc->SetModifiedFlag(TRUE); // 标志文档数据已被修改
pNewEnt->m_nOperationNum = g_pView->m_nCurrentOperation;
pEntity->Append(pNewEnt);
}
g_pDoc->m_selectArray.RemoveAll(); // 清空选择集
// g_pDoc->SetModifiedFlag(TRUE); // 标志文档数据已被修改
g_pView->ReleaseDC(pDC); // 释放视类的设备环境指针
}
2.选中后拖拽
拖拽后松开左键响应
void CVCadView::OnLButtonUp(UINT nFlags, CPoint point)
{
if(m_bDragging)
{
for(n = g_pDoc->m_selectArray.GetSize(), i = 0; i < n; i++)
{
//都是对基类MEntity在操作!!
MEntity* pNewEnt = pEntity->Copy();
pNewEnt->Move(basePos, desPos); // 将图元移动到目标位置
pNewEnt->m_brushcolor = pEntity->m_brushcolor;
pEntity->m_brushcolor = RGB(255, 255, 255);
pEntity->Draw(pDC, dmInvalid); // 清除原来位置上的图元
pNewEnt->Draw(pDC, dmNormal); // 在目标位置上绘制图元
g_pDoc->SetModifiedFlag(TRUE); // 标志文档数据已被修改
pNewEnt->m_nOperationNum = g_pView->m_nCurrentOperation;
pEntity->Append(pNewEnt);
}
g_pDoc->m_selectArray.RemoveAll(); // 清空选择集
// g_pDoc->SetModifiedFlag(TRUE); // 标志文档数据已被修改
g_pView->ReleaseDC(pDC); // 释放视类的设备环境指针
}
}
3.平移、旋转、镜像
int CMove::OnLButtonDown(UINT nFlags, const Position& pos)
{
m_nStep ++ ;
switch(m_nStep)
{
case 1:
// 第一次单击鼠标左键时得到基点位置,并初步设定目标位置
m_basePos = m_desPos = pos;
::prompt("请输入移动的目标点:单击鼠标右键取消") ;
break;
case 2:
{
m_desPos = pos;
CDC* pDC = g_pView->GetDC(); // 获得视类的设备环境指针
// 清除鼠标移动时最后遗留下的橡皮线
MLines* pTempLine = new MLines(m_basePos, m_desPos);
pTempLine->Draw(pDC, dmDrag);
delete pTempLine;
// 将选择集中的图元移动到目标位置并进行绘制
int i, n;
for(n = g_pDoc->m_selectArray.GetSize(), i = 0; i < n; i++)
{
MEntity* pEntity = (MEntity*)g_pDoc->m_selectArray[i];
pEntity->Draw(pDC,dmInvalid); // 清除原来位置上的图元
//Move
//Draw
MEntity * pNewEnt = pEntity->Copy();
pNewEnt->Move(m_basePos, m_desPos); // 将图元移动到目标位置
pNewEnt->m_brushcolor = pEntity->m_brushcolor;
pEntity->m_brushcolor = RGB(255, 255, 255);
pEntity->Draw(pDC, dmInvalid); // 清除原来位置上的图元
pNewEnt->Draw(pDC,dmNormal); // 在目标位置上绘制图元
g_pDoc->SetModifiedFlag(TRUE); // 标志文档数据已被修改
pNewEnt->m_nOperationNum = g_pView->m_nCurrentOperation;
pEntity->Append(pNewEnt);
}
g_pDoc->m_selectArray.RemoveAll(); // 清空选择集
g_pView->ReleaseDC(pDC); // 释放视类的设备环境指针
m_nStep = 0;
g_pView->SendMessage(WM_COMMAND, ID_PICK);
break;
}
default:
break;
}
return 0;
}
种子填充
VCadView类设计
protected: // create from serialization only CRect rect; //定义客户区 CP2 Seed;//种子及其四个相邻点 COLORREF SeedClr;//种子色 BOOL bFill;//填充标志 public: void SeedFill(CDC *pDC);//字符填充函数
填充相应
void CVCadView::OnSeedFill()
{
// TODO: Add your command handler code here
CColorDialog ccd(SeedClr, CC_SOLIDCOLOR);
if (IDOK == ccd.DoModal())//调用颜色对话框选取填充色
SeedClr = ccd.GetColor();
else
return;
if (IDOK == MessageBox(CString("请在区域内部选取种子点"), CString("提示"), MB_OKCANCEL))
{
bFill = TRUE;
}
else
return;
}
选择种子
void CVCadView::OnLButtonDown(UINT nFlags, CPoint point)
{
if(!m_bEditable)
return;
CDC * pDC = GetDC();
m_basePos = m_desPos = point;
if (bFill == TRUE)
{
GetClientRect(&rect);
pDC->SetMapMode(MM_ANISOTROPIC);//显示DC自定义坐标系
pDC->SetWindowExt(rect.Width(), rect.Height());
pDC->SetViewportExt(rect.Width(), -rect.Height());
pDC->SetViewportOrg(rect.Width() / 2, rect.Height() / 2);
Seed = CP2(point.x - rect.Width() / 2, rect.Height() / 2 - point.y);//选择种子位置
SeedFill(pDC);//填充空心汉字
bFill = FALSE;
ReleaseDC(pDC);//释放pDC
return;
}
种子算法
void CVCadView::SeedFill(CDC *pDC)//文字填充函数
{
COLORREF BoundaryClr = g_CurColor;//边界色
BOOL bSpanFill;
Stack PStakeU, PStakeD;
PStakeU.Push(Seed); PStakeD.Push(Seed);
int x, y, x0 = Round(Seed.x), y0 = Round(Seed.y);//x,y用于判断种子与图形的位置关系
x = x0 - 1;
while (pDC->GetPixel(x, y0) != BoundaryClr && pDC->GetPixel(x, y0) != SeedClr)//左方判断
{
x--;
if (x <= -rect.Width() / 2)
{
MessageBox(CString("种子不在图形之内"), CString("警告"));//到达客户区最左端
return;
}
}
y = y0 + 1;
while (pDC->GetPixel(x0, y) != BoundaryClr && pDC->GetPixel(x0, y) != SeedClr)//上方判断
{
y++;
if (y >= rect.Height() / 2)//到达客户区最上端
{
MessageBox(CString("种子不在图形之内"), CString("警告"));//到达客户区最左端
return;
}
}
x = x0 + 1;
while (pDC->GetPixel(x, y0) != BoundaryClr && pDC->GetPixel(x, y0) != SeedClr)//右方判断
{
x++;
if (x >= rect.Width() / 2)//到达客户区最右端
{
MessageBox(CString("种子不在图形之内"), CString("警告"));//到达客户区最左端
return;
}
}
y = y0 - 1;
while (pDC->GetPixel(x0, y) != BoundaryClr && pDC->GetPixel(x0, y) != SeedClr)//下方判断
{
y--;
if (y <= -rect.Height() / 2)//到达客户区最下端
{
MessageBox(CString("种子不在图形之内"), CString("警告"));//到达客户区最左端
return;
}
}
double xleft, xright;//区间最左端与最右端像素
CP2 PopPoint, PointTemp;
while (!PStakeU.Empty())//如果栈不为空
{
PopPoint = PStakeU.GetTop()->data; PStakeU.Pop();
if (pDC->GetPixel(Round(PopPoint.x), Round(PopPoint.y)) == SeedClr)
continue;
PointTemp = PopPoint;
//像素不为边界色,不为种子色,此时在画一条横线
//向右
while (pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != BoundaryClr && pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != SeedClr)
{
pDC->SetPixelV(Round(PointTemp.x), Round(PointTemp.y), SeedClr);
PointTemp.x++;
}
xright = PointTemp.x - 1;//右边界
PointTemp.x = PopPoint.x - 1;
//向左
while (pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != BoundaryClr && pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != SeedClr)
{
pDC->SetPixelV(Round(PointTemp.x), Round(PointTemp.y), SeedClr);
PointTemp.x--;
}
xleft = PointTemp.x + 1;
//处理上一条扫描线
PointTemp.x = xleft;
PointTemp.y = PointTemp.y + 1;
while (PointTemp.x < xright)
{
bSpanFill = FALSE;
while (pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != BoundaryClr && pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != SeedClr)
{
bSpanFill = TRUE;
PointTemp.x++;
}
if (bSpanFill)
{
if (PointTemp.x == xright && pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != BoundaryClr && pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != SeedClr)
{
PopPoint = PointTemp;
}
else
{
PopPoint.x = PointTemp.x - 1;
PopPoint.y = PointTemp.y;
}
PStakeU.Push(PopPoint);
bSpanFill = FALSE;
}
while ((pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) == BoundaryClr && PointTemp.x < xright) || (pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) == SeedClr && PointTemp.x < xright))
PointTemp.x++;
}
//处理下一条扫描线
PointTemp.x = xleft;
PointTemp.y = PointTemp.y - 2;
while (PointTemp.x < xright)
{
bSpanFill = FALSE;
while (pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != BoundaryClr && pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != SeedClr)
{
bSpanFill = TRUE;
PointTemp.x++;
}
if (bSpanFill)
{
if (PointTemp.x == xright && pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != BoundaryClr && pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) != SeedClr)
{
PopPoint = PointTemp;
}
else
{
PopPoint.x = PointTemp.x - 1;
PopPoint.y = PointTemp.y;
}
PStakeU.Push(PopPoint);
bSpanFill = FALSE;
}
while ((pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) == BoundaryClr && PointTemp.x < xright) || (pDC->GetPixel(Round(PointTemp.x), Round(PointTemp.y)) == SeedClr && PointTemp.x < xright))
PointTemp.x++;
}
}
PStakeU.Clear();
}



