簡體   English   中英

重新繪制分層窗口的正確方法

[英]Correct method for redrawing a layered window

我有一個使用WS_EX_LAYERED窗口樣式創建的窗口。 目前,我正在使用GDI +繪制內存位圖,並使用UpdateLayeredWindow更新分層窗口的圖形內容。 我打算將此窗口用作應用程序的主窗口,這將要求它經常重繪。

看到分層窗口沒有收到WM_PAINT窗口消息[?] ,我需要提出一種適當的方法來重新繪制窗口。 優化不是必不可少的 ,但是吃蛋糕也總是很高興。 因此,我正在尋找要使用的“正確”方法。

到目前為止,這是我的想法:

  • 我想這是在BitBlt或類似方法之前渲染到屏幕外位圖的好主意。

  • 每秒渲染60幀應該足夠(超過?)(但這與其他應用程序的幀率相比如何?)。

可能的解決方案:

  • 使用SetTimer定期發送WM_TIMER消息。

    • 之所以有用,是因為通過指定超時值,我可以每秒實現所需的幀數,而無需測量渲染“幀”所需要的持續時間。

    • 由於消息的頻率和速度,可能會導致輸入或其他延遲。

  • 僅在發生特定事件(例如窗口調整大小)時才渲染幀。

    • 需要我找出所有需要重畫的事件。

    • 將大大減少呈現的不必要幀的數量。

  • 通過檢查PeekMessage ,在消息隊列中沒有消息時渲染幀。

    • 可能會減慢窗口消息的處理。

    • 這將導致較高的CPU使用率,因為正在處理的幀超出了必要。

  • 創建一個新線程以執行渲染循環。

    • 為了保持穩定的幀速率,必須執行時序計算。

分層的窗口不會接收WM_PAINT消息,否則該消息會在窗口可見性更改后生成,但完全不會阻止它們接收此消息。

您可以繼續使用InvalidateRect更改窗口更新區域,在窗口過程中等待WM_PAINTUpdateLayeredWindow圖中繪制內容,然后調用UpdateLayeredWindow更改窗口內容。 您可以使用此方法在窗口內容更改時(例如,當按下按鈕或調整窗口大小(或激活/停用)時)請求重繪。

它不應該那么復雜,這是消息循環的偽代碼:

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(...);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM