0

我有一个使用WS_EX_LAYERED窗口样式创建的窗口。我目前正在使用 GDI+ 绘制内存位图,并UpdateLayeredWindow用于更新分层窗口的图形内容。我打算将此窗口用作我的应用程序的主窗口,这需要它经常重绘。

看到分层窗口没有收到WM_PAINT窗口消息[?],我需要想出一个适当的方法来重新绘制窗口。优化不是必需的,但拥有你的蛋糕并吃掉它总是很好的。因此,我正在寻找“正确”的方法来使用。

到目前为止,这是我的想法:

  • 我猜想在BitBlting 或类似之前渲染到屏幕外位图上是个好主意。

  • 每秒渲染 60 帧应该(超过?)足够了(但这与其他应用程序的帧速率相比如何?)。

可能的解决方案:

  • 用于定期SetTimer发送消息。WM_TIMER

    • 很有用,因为通过指定超时值,我可以达到我想要的每秒帧数,而无需测量渲染“帧”所需的持续时间。

    • 由于消息的频率和速度,可能会导致输入或其他滞后。

  • 仅在特定事件发生时渲染帧,例如窗口调整大小。

    • 需要我弄清楚所有需要重绘的事件。

    • 将大大减少被渲染的不必要帧的数量。

  • 当消息队列中没有消息时渲染帧,通过检查PeekMessage.

    • 可能会减慢窗口消息的处理速度。

    • 这将导致 CPU 使用率过高,因为正在处理的帧数超过了必要的帧数。

  • 创建一个新线程来执行渲染循环。

    • 必须执行时序计算以保持稳定的帧速率。
4

2 回答 2

1

分层窗口不会接收WM_PAINT在窗口可见性更改后会生成的消息,但它根本不会阻止它们接收此消息。

您可以继续使用InvalidateRect更改窗口更新区域,在您的窗口程序中等待WM_PAINT,在位图中绘制内容并调用UpdateLayeredWindow更改窗口内容。您可以使用此方法在窗口内容更改时请求重绘,例如,当按下按钮或调整窗口大小(或激活/停用)时。

于 2015-10-11T11:56:46.127 回答
0

它不应该那么复杂,这是您消息循环的伪代码:

while (true) 
{
    // GetMessages
    while (PeekMessage(&msg, hWnd, 0, 0, PM_NOREMOVE))
    {
        if (!GetMessage(&msg, hWnd, 0, 0 ))
        {
            // Need to handle WM_QUIT
            ...
            break;
        }
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }

    // Check if we need to draw
    if (TimeForANewFrameHasCome() ||
        IfWeNeedToDrawAfterInputOrInvalidate() ||
        AnyOtherCaseThatCausesAnUpdate())
    {
         // Render
         UpdateMemoryDCOrBitmap(...);

         // Display it
         UpdateLayeredWindow(...);
    }

    // May sleep a while
    // Either Sleep(20); or better MsgWaitForMultipleObjects, that makes it possible
    // to wake up upon an Event too... 
    MsgWaitForMultipleObjects(...);
}
于 2013-10-07T10:24:10.893 回答