为什么即使在调用UpdateWindow()之后也会丢失消息?

时间:2010-02-05 13:25:01

标签: c++ windows mfc paint cwnd

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

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.如果使用标志,如何解决闪烁问题。

谢谢,

2 个答案:

答案 0 :(得分:2)

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

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

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

与此同时,您可以移除W3,以便W2不会被遮挡,并查看是否所有的绘画消息都返回。另请注意,CWnd::Invalidate不会选择NULL作为选项,需要BOOLTRUEFALSE)。

答案 1 :(得分:2)

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

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

历史背景是,如果有很多待处理的消息,你不想花太多时间画一个窗口,因为这些可能只会使你的窗口无效。最好先让你的模型更新,然后再查看东西。