0

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

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

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

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

W2::onCertainEvent()
{
        Invalidate(NULL);
        UpdateWindow();
}

OnPaintW2的处理是这样的:

   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如何解决闪烁问题。

谢谢,

4

2 回答 2

2

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

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

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

于 2010-02-05T16:06:20.497 回答
2

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

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

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

同时,您可以删除 W3 以使 W2 不会被遮挡,并查看您的所有绘制消息是否都返回。另外,请注意CWnd::Invalidate不将 NULL 作为选项,它需要BOOL(TRUEFALSE)。

于 2010-02-05T14:01:51.453 回答