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

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

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

Вот мои мысли до сих пор:

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

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

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

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

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

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

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

    • Требуется, чтобы я выяснил все события, которые потребуют перерисовки.

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

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

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

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

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

    • Расчет времени должен быть выполнен, чтобы поддерживать постоянную частоту кадров.

0

Решение

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

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

1

Другие решения

Это не должно быть так сложно, это псевдокод для вашего цикла сообщений:

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

По вопросам рекламы [email protected]