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

发布于 2024-08-20 01:16:15 字数 944 浏览 7 评论 0原文

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

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

谢谢,

I have an application with following windows hierarchy:

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

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

When certain event happens in W2, I call UpdateWindow:

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

The OnPaint handling of W2 looks like this:

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

But some times the paint messages are getting lost in W2. Though UpdateWindow gets called, there is no corresponding OnPaint() getting called.

If I add a property WS_EX_TRANSPARENT to W1 ( the parent of W2) then always paint messages are received @ W2.

But the problem with adding the WS_EX_TRANSPARENT flag is that it creates lot of flicker when I resize the window W1.

My Questions are:
1. What is wrong in W2 so that Paint messages are lost?
2. Why adding WS_EX_TRANSPARENT solves the Paint problem.
3. How do I solve flicker issue if the flag is used.

Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ゞ花落谁相伴 2024-08-27 01:16:15

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

然而,在这种情况下,我相信会出现闪烁,因为每次绘制时 W1 首先绘制自身,然后是 W2,然后是 W3。这表明 WS_EX_TRANSPARENT 不是解决您遇到的问题的方法。

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

同时,您可以删除 W3,以便 W2 不被遮挡,并查看是否所有绘制消息都返回。另请注意 CWnd::Invalidate不接受 NULL 作为选项,它接受 BOOLTRUEFALSE)。

Flicker
Flicker can be resolved by handing WM_ERASEBKGND and making sure it does nothing. The flicker can occur because each Window handles this message before every paint to erase the invalid area using its background colour. If you handle it and do nothing, the erase doesn't occur - just make sure your WM_PAINT handler paints the entire invalidated area or you'll leave artifacts from the previous paint behind.

However, in this case, I believe the flicker occurs because W1 paints itself first, then W2, then W3 on each paint. This suggests that WS_EX_TRANSPARENT is not the way to fix the problem you're experiencing.

Missing WM_PAINT
It's difficult to know how to track this down. In .NET, this happens because the child windows obscure the entire client area of the control and so the paint message is not propagated through but I believe that's a specific .NET behaviour. If you could provide a sample project or sample code that exhibits the problem, it would be a big help.

In the meantime, you could remove W3 so that W2 is not obscured and see if all your paint messages return. Also, note that CWnd::Invalidate doesn't take NULL as an option, it takes a BOOL (TRUE or FALSE).

陪我终i 2024-08-27 01:16:15

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

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

历史背景是,如果有大量待处理的消息,您不想花费太多时间来绘制窗口,因为无论如何这些消息可能都会使您的窗口失效。最好先更新您的模型,然后再执行视图操作。

WM_PAINT "messages" are not really messages in the normal sense of the word. They behave much like flags at the end of the message queue of each window. They don't go through the thread message queue, they don't have a position in the windows message queue. They're generated when you try to retrieve a message from the windows message queue, and there are no other messages. At that time, all the different invalidations are considered and one or more (!) WM_PAINT are generated.

The result is that after your W2::onCertainEvent() the "window invalid" flag will be set. It follows that eventually WM_PAINT will be called, but the WM_PAINT that is generated then will not be exclusively for that "Certain Event".

The historical background is that you don't want to spend too much time painting a window if there were a lot of messages pending, as those are probably just going to invalidate your window anyway. Better get your Model up to date first, and then do the View stuff.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文