Invalidate()函数
两个说明 :
1)、在Invalidate()之后 ,OnPaint()->OnPrepareDC()->OnDraw()
它是标记一个需要重绘的区域,(强制系统进行重绘),但并不意味着调用该函数后就立刻进行重绘。
类似于PostMessage(wm_paint)需要处理到WM_PAINT 消息时才真正重绘。因为在Invalidate()之后还有其他
的语句正在执行,所以,它只是通知系统,此时,窗口已经为无效。
2)、Invalidate()只是放一个WM_PAINT消息在队列里(,其无效区域为整个客户区,)不做别的,所以只有当
当前函数返回后,进入消息循环,取出wm_paint,才执行这一消息,所以不管Invalidate放在哪里,都是最后 的。
两个问题:
1)、系统为什么不在调用 Invalidate()时,发送wm_paint消息?
2)、为什么一定等应用消息队列为空时才发送wm_paint消息?
这是因为系统把窗口中的绘制操作当作一种低优先级的操作,于是尽可能地推后做,这样有利于
提高绘制的效率:在两个wm_paint消息之间多个Invalidate()调用使之失效的区域就会被累加
起来,然后在一个wm_paint消息中一次等到更新,不仅能避免多次重复地更新同一区域,也优化了
应用的更新操作。
例子就用MFC的:
// In this example a rectangle is drawn in a view.
//这个例子是在View上画一个矩形区域
// The OnChangeRect() function changes the dimensions
// of the rectangle and then calls CWnd::Invalidate() so the
// client area of the view will be redrawn next time the
// window is updated. It then calls CWnd::UpdateWindow
// to force the new rectangle to be painted.
void CTestView::OnChangeRect()
{
// Change Rectangle size.
m_rcBox = CRect(20, 20, 210, 210);
// Invalidate window so entire client area
// is redrawn when UpdateWindow is called.
Invalidate();
// Update Window to cause View to redraw.
UpdateWindow();
}
// On Draw function draws the rectangle.
void CTestView::OnDraw(CDC* pDC)
{
// .. Other draw code here.
pDC->Draw3dRect(m_rcBox, 0x00FF0000, 0x0000FF00);
}