为啥即使在调用 UpdateWindow() 之后绘制消息也会丢失?

Posted

技术标签:

【中文标题】为啥即使在调用 UpdateWindow() 之后绘制消息也会丢失?【英文标题】:Why paint messages get lost even after calling UpdateWindow()?为什么即使在调用 UpdateWindow() 之后绘制消息也会丢失? 【发布时间】:2010-02-05 13:25:00 【问题描述】:

我有一个具有以下 Windows 层次结构的应用程序:

W1
  -W2  (Child of W1)
    - W3 ( Child of W2)

--------------------|
| W1|------------|  |
|   |W2 |------| |  |
|   |   |W3    | |  |
|   |   |------| |  |
|   |------------|  | 
|-------------------|

当 W2 发生某些事件时,我会调用 UpdateWindow:

W2::onCertainEvent()

        Invalidate(NULL);
        UpdateWindow();

W2 的OnPaint 处理如下所示:

   W2::onPaint()
  
    //W2 logic goes here
    W3.Invalidate(NULL); //So that paint messages are given to W3
  

但有时绘图消息会在 W2 中丢失。虽然UpdateWindow 被调用,但没有对应的OnPaint() 被调用。

如果我将属性 WS_EX_TRANSPARENT 添加到 W1(W2 的父级),则始终会收到 @ W2 的绘制消息。

但是添加 WS_EX_TRANSPARENT 标志的问题是,当我调整窗口 W1 的大小时,它会产生很多闪烁。

我的问题是: 1. W2 有什么问题导致Paint 消息丢失? 2.为什么添加WS_EX_TRANSPARENT可以解决Paint问题。 3. 使用flag如何解决闪烁问题。

谢谢,

【问题讨论】:

【参考方案1】:

闪烁 闪烁可以通过提交WM_ERASEBKGND 并确保它什么都不做来解决。闪烁可能是因为每个窗口在每次绘制之前都会处理此消息,以使用其背景颜色擦除无效区域。如果您处理它并且什么都不做,则不会发生擦除 - 只需确保您的 WM_PAINT 处理程序绘制整个无效区域,否则您将留下先前绘制的伪影。

但是,在这种情况下,我认为闪烁的发生是因为 W1 先绘制自身,然后是 W2,然后是 W3 每次绘制。这表明WS_EX_TRANSPARENT 不是解决您遇到的问题的方法。

缺少 WM_PAINT 很难知道如何追踪它。在 .NET 中,发生这种情况是因为子窗口遮盖了控件的整个客户区,因此不会传播绘制消息,但我相信这是特定的 .NET 行为。如果你能提供一个展示问题的示例项目或示例代码,那将是一个很大的帮助。

与此同时,您可以移除 W3 以使 W2 不会被遮挡,然后查看您的所有绘制消息是否都返回。另外,请注意CWnd::Invalidate 不采用 NULL 作为选项,它采用 BOOLTRUEFALSE)。

【讨论】:

【参考方案2】:

WM_PAINT “消息”并不是正常意义上的消息。它们的行为很像每个窗口消息队列末尾的标志。它们不通过线程消息队列,它们在 Windows 消息队列中没有位置。它们是在您尝试从 Windows 消息队列中检索消息时生成的,并且没有其他消息。那时,会考虑所有不同的失效,并生成一个或多个 (!) WM_PAINT。

结果是,在您的W2::onCertainEvent() 之后,“窗口无效”标志将被设置。因此,最终会调用WM_PAINT,但随后生成的 WM_PAINT 不会专门用于该“特定事件”。

历史背景是,如果有很多消息未决,您不希望花费太多时间来绘制窗口,因为这些消息可能只会使您的窗口无效。最好先让你的模型更新,然后再做视图。

【讨论】:

以上是关于为啥即使在调用 UpdateWindow() 之后绘制消息也会丢失?的主要内容,如果未能解决你的问题,请参考以下文章

为啥即使在配置之后 Git 也不允许我提交?

为啥即使在 System.exit(0) 之后也需要返回;

为啥即使在添加程序集“Microsoft.SqlServer.ConnectionInfo”之后 C# 也无法识别 Server()

为啥在组件加载时不调用 useEffect(()=...,[]) ?

为啥我得到“UnhandledPromiseRejectionWarning:错误:未定义类型错误。确保提供显式类型”即使在我指定了类型之后?

为啥即使在增加执行时间之后,我在本地的 Word press 中也会出现 max_execution_time 错误?