设为首页 加入收藏

TOP

vc++笔记之绘图程序 (四)
2014-11-23 19:22:48 来源: 作者: 【 】 浏览:192
Tags:笔记 绘图 程序
epareDC(&dc);

CRect rectInvalid = pStroke->GetBoundingRect();

dc.LPtoDP(&rectInvalid);

InvalidateRect(&rectInvalid);

return;

}

}

// We can't interpret the hint, so assume that anything might

// have been updated.

Invalidate(TRUE);

return;

}

这里,传给pHint指针的内容是指向需要绘制的笔画对象的指针。采用强制类型转换将它转换为笔划指针,然后取得包围该笔划的最小矩形。OnPrepareDC用于调整视图坐标原点。由于InvalidateRect需要设备坐标,因此调用LPToDP(&rectInvalid)将逻辑坐标转换为设备坐标。最后,调用InvalidateRect是窗口部分区域“无效”,也就是视图在收到WM_PAINT消息后需要重绘这一区域。

InvalidateRect函数原型为:

void InvalidateRect( LPCRECT lpRect, BOOL bErase = TRUE );

第一个参数是指向要重绘的矩形的指针,第二个参数告诉视图是否要删除区域内的背景。

这样,当需要重画某一笔划时,只需要重画包围笔划的最小矩形部分就可以了,其他部分就不再重绘。这也是为什么在笔划对象中提供最小矩形信息的原因。

如果pHint为空,则表明是一般的重绘,此时需要重绘整个客户区。

现在,在OnDraw中,根据无效矩形绘制图形,而不是重绘全部笔划,见清单8.6。

清单8.6 根据无效矩形绘制图形的OnDraw成员函数

void CDrawView::OnDraw(CDC* pDC)

{

CDrawDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

 

// Get the invalidated rectangle of the view, or in the case

// of printing, the clipping region of the printer dc.

CRect rectClip;

CRect rectStroke;

pDC->GetClipBox(&rectClip);

pDC->LPtoDP(&rectClip);

rectClip.InflateRect(1, 1); // avoid rounding to nothing

// Note: CScrollView::OnPaint() will have already adjusted the

// viewport origin before calling OnDraw(), to reflect the

// currently scrolled position.

// The view delegates the drawing of individual strokes to

// CStroke::DrawStroke().

CTypedPtrList& strokeList = pDoc->m_strokeList;

POSITION pos = strokeList.GetHeadPosition();

while (pos != NULL)

{

CStroke* pStroke = strokeList.GetNext(pos);

rectStroke = pStroke->GetBoundingRect();

pDC->LPtoDP(&rectStroke);

rectStroke.InflateRect(1, 1); // avoid rounding to nothing

if (!rectStroke.IntersectRect(&rectStroke, &rectClip))

continue;

pStroke->DrawStroke(pDC);

}

// TODO: add draw code for native data here

}

OnDraw首先调用GetClipBox取得当前被剪裁区域(无效矩形区域),它把矩形复制导GetClipBox的参数rectClip中。然后将rectClip的坐标由逻辑坐标转换为设备坐标。为了防止该矩形太小而无法包围其他内容,上下各放大一个单位。然后OnDraw遍历笔划链表中的所有笔划,获取它们的最小矩形,用IntersectRect看它是否与无效矩形相交。如果相交,说明笔划的部分或全部落在无效矩形中,此时调用笔划的DrawStroke方法画出该笔划。

图8-6 根据包围笔划 的矩形是否与无效

矩形相交 ,判断笔划是否落入无效矩形中

为了获得笔划的最小包围矩形,需要在结束笔划时计算出包围笔划的最小矩形。因此为笔划提供两个方法:一个是FinishStroke(),用于在笔划结束时计算最小矩形,见清单8.7。

清单8.7 CStroke::FinishStroke()成员函数

void CStroke::FinishStroke()

{

// Calculate the bounding rectangle. It's needed for smart

// repainting.

if (m_pointArray.GetSize()==0)

{

m_rectBounding.SetRectEmpty();

return;

}

CPoint pt = m_pointArray[0];

m_rectBounding = CRect(pt.x, pt.y, pt.x, pt.y);

for (int i=1; i < m_pointArray.GetSize(); i++)

{

// If the point lies outside of the accumulated bounding

// rectangle, then inflate the bounding rect to include it.

pt = m_pointArray[i];

m_rectBounding.left = min(m_rectBounding.left, pt.x);

m_rectBounding.right = max(m_rectBounding.right, pt.x);

m_rectBounding.top = max(m_rectBounding.top, pt.y);

m_rectBounding.bottom = min(m_rectBounding.bottom, pt.y);

}

// Add the pen width to the bounding rectangle. This is necessary

// to account for the width of the stroke when invalidating

// the screen.

m_rectBounding.InflateRect(CSize(m_nPenWidth, -(int)m_nPenWidth));

return;

}

另一个是DrawStroke(),用于绘制笔划:

BOOL CStroke::DrawStroke(CDC* pDC)

{

CPen penStroke;

if (!penStroke.CreatePen(PS_SOLID, m_nPenWidth, RGB(0,0,0)))

return FALSE;

CPen* pOldPen = pDC->SelectObject(&penStroke);

pDC->MoveTo(m

首页 上一页 1 2 3 4 5 6 下一页 尾页 4/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇VC密码框显示字符的终极设置方法 下一篇图形设备接口(学习笔记)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: