У меня есть окно, созданное с WS_EX_LAYERED
стиль окна В настоящее время я рисую на растровое изображение памяти, используя GDI +, и использую UpdateLayeredWindow
обновить графическое содержимое моего многослойного окна. Я намерен использовать это окно в качестве основного окна моего приложения, что потребовало бы его частой перерисовки.
Видя, как многослойные окна не получают WM_PAINT
сообщение Windows[?], Мне нужно придумать подходящий метод для перерисовки окна. Оптимизация не существенный, но всегда приятно иметь свой торт и есть его тоже. Поэтому я нахожусь в поиске «правильного» метода для использования.
Вот мои мысли до сих пор:
Я предполагаю, что это хорошая идея, чтобы сделать рендеринг на закадровое изображение перед BitBlt
или аналогичный.
60 кадров в секунду должно быть (больше чем?) Достаточно (но как это сравнить с частотой кадров других приложений?).
Возможные решения:
использование SetTimer
отправить WM_TIMER
сообщение на регулярной основе.
Полезно, потому что, указав значение тайм-аута, я могу достичь желаемых кадров в секунду, не требуя измерения длительности, в течение которой будет отображаться «кадр».
Скорее всего, будет причиной ввода или других задержек из-за частоты и скорости сообщений.
Рендеринг кадров только тогда, когда происходят определенные события, такие как изменение размера окна.
Требуется, чтобы я выяснил все события, которые потребуют перерисовки.
Значительно уменьшит количество ненужных кадров.
Рендеринг кадров, когда в очереди сообщений нет сообщений, проверяя PeekMessage
.
это может быть замедлить обработку оконных сообщений.
Это приведет к высокой загрузке ЦП, поскольку обрабатывается больше кадров, чем необходимо.
Создайте новый поток для выполнения цикла рендеринга.
Многослойные окна не получают WM_PAINT
сообщения, которые иначе были бы сгенерированы после изменения видимости окна, но это не помешает им вообще получить это сообщение.
Вы можете продолжать использовать InvalidateRect
чтобы изменить область обновления окна, дождитесь WM_PAINT
в вашей оконной процедуре нарисуйте содержимое в растровом изображении и вызовите 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(...);
}