【问题标题】:Does InvalidateRect() sends WM_PAINT messages to the child controls?InvalidateRect() 是否向子控件发送 WM_PAINT 消息?
【发布时间】:2015-09-03 20:01:54
【问题描述】:

如果我在父窗口上调用InvalidateRect(),例如:

InvalidateRect(hWnd, NULL, TRUE);

会发生什么,在WM_PAINT 处理程序中,BeginPaint() 将发送一个WM_ERASEBKGND 消息,这将清除背景,因此所有子控件都将消失。

但是当我调用InvalidateRect() 时,子控件仍然存在,这是否意味着InvalidateRect() 也会向子控件发送WM_PAINT 消息?

【问题讨论】:

  • @David Heffernan 但是如何重新绘制子控件?我的意思是如果没有WM_PAINT 消息发送给他们。
  • 首先,让我们明确一点,绘画是异步的。你打电话给InvalidateRect,并没有立即发生任何事情。只有当消息队列被清空时,才会重新绘制无效区域。至于子控件,它很复杂。 DWM 组合意味着控件可能不需要重新绘制。 DWM 系统可能已经拥有了它所需要的一切,并且没有任何理由去采取另一个WM_PAINT。因此,它的行为方式可能取决于组合或双缓冲是否处于活动状态。

标签: c winapi


【解决方案1】:

InvalidateRect() 是否向子控件发送 WM_PAINT 消息?

是的(大部分情况下),这里描述得很清楚:

https://msdn.microsoft.com/en-us/library/windows/desktop/dd183426(v=vs.85).aspx

只要父窗口的更新区域的一部分包含子窗口的一部分,系统就会为子窗口设置更新区域。在这种情况下,系统首先向父窗口发送一条 WM_PAINT 消息,然后向子窗口发送一条消息,允许子窗口恢复父窗口可能已绘制的任何部分。

但有例外:

应用程序无法通过使完全位于子窗口下方的父客户区的一部分无效来为子窗口生成 WM_PAINT 消息。在这种情况下,两个窗口都不会收到 WM_PAINT 消息。

这其实很有趣

您可以通过将 WS_CLIPCHILDREN 设置为父窗口,或通过使用带有 RDW_NOCHILDREN 标志的 RedrawWindow 函数使重绘无效来防止重绘子窗口。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-23
    • 2017-10-06
    • 1970-01-01
    • 2015-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多