Правильный метод перерисовки многослойного окна

0

У меня есть окно, созданное с помощью WS_EX_LAYERED окна WS_EX_LAYERED. В настоящее время я рисую на растровое изображение с использованием GDI+ и используя UpdateLayeredWindow для обновления графического содержимого моего многоуровневого окна. Я намерен использовать это окно в качестве основного окна моего приложения, которое потребует его для частого перерисовки.

Видя, как многослойные окна не получают сообщение Windows WM_PAINT [?], Мне нужно создать соответствующий метод для повторного рисования окна. Оптимизация не является существенной, но всегда приятно иметь ваш торт и есть его тоже. Поэтому я ищу "правильный" метод для использования.

Вот мои мысли:

  • Я бы предположил, что это хорошая идея для рендеринга на экранном растровом изображении до BitBlt ing или аналогичного.

  • 60 кадров в секунду должны быть (более?) Достаточно (но как это соотносится с частотой кадров других приложений?).

Возможные решения:

  • Используйте SetTimer для отправки сообщения WM_TIMER на регулярной основе.

    • Полезно, потому что, указав значение тайм-аута, я могу достичь желаемых кадров в секунду без необходимости измерять длительность, которую требуется выполнить "кадр".

    • Вероятно, приведет к возникновению входных или других задержек из-за частоты и скорости сообщений.

  • Отправлять кадры только тогда, когда происходят определенные события, такие как изменение размера окна.

    • Мне потребовалось бы выяснить все события, которые потребуют перерисовки.

    • Было бы значительно уменьшить количество ненужных кадров.

  • Отправлять кадры, когда в очереди сообщений нет сообщений, проверяя PeekMessage.

    • Это может замедлить обработку оконных сообщений.

    • Это приведет к высокому использованию ЦП, поскольку обрабатывается больше кадров, чем необходимо.

  • Создайте новый поток для выполнения цикла рендеринга.

    • Расчеты времени должны быть выполнены для поддержания постоянной частоты кадров.
Теги:
graphics
winapi

2 ответа

1

Слоистые окна не получают сообщений WM_PAINT, которые иначе были бы созданы после изменения видимости окна, но это не помешает им получить это сообщение вообще.

Вы можете продолжать использовать InvalidateRect чтобы изменить область обновления окна, дождаться WM_PAINT в вашей оконной процедуре, нарисовать содержимое в растровом изображении и вызвать UpdateLayeredWindow для изменения содержимого окна. Этот метод можно использовать для запроса перерисовки при изменении содержимого окна, например, при нажатии кнопки или изменении размера окна (или активации/деактивации).

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(...);
}
  • 0
    Почему вы используете PeekMessage(PM_NOREMOVE) и GetMessage() вместе? Если вместо этого вы используете PeekMessage(PM_REMOVE) , вам вообще не нужен GetMessage() . Если нет ничего , чтобы подглядывать, PeeMessage() возвращает FALSE, так что во while цикла до сих пор работает.
  • 0
    Я согласен. Но с этим способом мне не нужно использовать дополнительную обработку для WM_QUIT. Да, вы можете просто использовать PM_REMOVE и проверить WM_QUIT после просмотра. Это просто вопрос стиля.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню