关于"VC 技术内幕"-控件上绘图代码的解释 vc 技术内幕,有一节关于在对话框上控件画图(6.8 节)的代码: void CMyDlg::OnPaint() { CWnd *pWnd = GetDlgItem(IDC_STATIC1); RECT rect; pWnd->GetClientRect(&;rect); CDC *pControlDC = pWnd->GetDC(); pWnd->Invalidate(); pWnd->UpdateWindow(); pControlDC->SelectStockObject(BLACK_BRUSH); pControlDC->Rectangle(rect.left, rect.top, rect.right,rect.bottom); pWnd->ReleaseDC(pControlDC); } 这里连用了 pWnd->Invalidate(); pWnd->UpdateWindow(); 原文解释: "这里面的一个技巧就在于我们既要在控件窗口内绘图,又要防止 Windows 对 它进行重复绘制. " 就是这两句代码 (pWnd->Invalidate(); pWnd->UpdateWindow(); ) 让许多人摸不着头脑. 归纳起来有两种问题: 1,认为这是死循环 这是初学者提的
问题,这里需指出:pWnd 是 IDC_STATIC 控件的指针,并不是对当前 窗体 2,对 Invalidate,UpdateWindow 均会引起 WM_PAINT 事件的不解 "系统会在多个不同的时机发送 WM_PAINT 消息:当第一次创建一个窗口时,当改变 窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时,等等,这些 动作都是由系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操作;大 多数的时候应用也需要能够主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时 候 , 这 一 般 是 通 过 InvalidateRect 和 InvalidateRgn 函 数 来 完 成 的 . InvalidateRect 和 InvalidateRgn 把指定的区域加到窗口的 Update Region 中,当应用的消息队列没有其他消息 时,如果窗口的 Update Region 不为空时,系统就会自动产生 WM_PAINT 消息. "最后一句 话指出了问题所在,Invalidate 使客户区无效,但并没有及时触发 WM_PAINT,WM_PAINT 是由
系统控制的,只有当在消息队列没有其他消息时才触发 WM_PAINT 系统为什么不在调用 Invalidate 时发送 WM_PAINT 消息呢?又为什么非要等应用消息 队列为空时才发送 WM_PAINT 消息呢? "这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地推后 做,这样有利于提高绘制的效率:在两个 WM_PAINT 消息之间多个 Invalidate 调用使之失 效的区域就会被累加起来,然后在一个 WM_PAINT 消息中一次得到更新,不仅能避免多次 重复地更新同一区域, 也优化了应用的更新操作. 像这种通过 InvalidateRect 和 InvalidateRgn 来使窗口区域无效,依赖于系统在合适的时机发送 WM_PAINT 消息的机 制实际上是一种 异步
工作方式,也就是说,在无效化窗口区域和发送 WM_PAINT 消息之间是有延迟的;有
时候这种延迟并不是我们希望的, 这时我们当然可以在无效化窗口区域后利用 SendMessage 发送一条 WM_PAINT 消息来强制立即重画, 但不如使用 Windows GDI 为我们提供的更方便 和强大的函数:UpdateWindow 和 RedrawWindow.UpdateWindo
w 会检查窗口的 Update Region,当其不为空时才发送 WM_PAINT 消息;RedrawWindow 则给我们更多的控制:是 否重画非客户区和背景, 是否总是发送 WM_PAINT 消息而不管 Update Region 是否为空等"
这也就解释了代码中去掉 pWnd->UpdateWindow() 后不能出现所绘图的现象,其实 图像已经绘制,只不过被 Invalidate 滞后触发的WM_PAINT 刷了 MSDN的解释 pWnd->Invalidate(); Specifies whether the background within the update region is to be erased pWnd->UpdateWindow(); Updates the client area by sending aWM_PAINT message if the update region is not empty. The UpdateWindow member function sends a WM_PAINT message directly, bypassing the application queue. If the update region is empty, WM_PAINT is not sent.
本 文 来 自 CSDN 博 客 , 转 载 请 blog.csdn.net/sinhua_ren/archive/2007/06/21/1660473.aspx
标
明
出
处
: