У меня есть окно, созданное с помощью WS_EX_LAYERED
окна WS_EX_LAYERED
. В настоящее время я рисую на растровое изображение с использованием GDI+ и используя UpdateLayeredWindow
для обновления графического содержимого моего многоуровневого окна. Я намерен использовать это окно в качестве основного окна моего приложения, которое потребует его для частого перерисовки.
Видя, как многослойные окна не получают сообщение Windows WM_PAINT
[?], Мне нужно создать соответствующий метод для повторного рисования окна. Оптимизация не является существенной, но всегда приятно иметь ваш торт и есть его тоже. Поэтому я ищу "правильный" метод для использования.
Вот мои мысли:
Я бы предположил, что это хорошая идея для рендеринга на экранном растровом изображении до BitBlt
ing или аналогичного.
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(...);
}
PeekMessage(PM_NOREMOVE)
иGetMessage()
вместе? Если вместо этого вы используетеPeekMessage(PM_REMOVE)
, вам вообще не нуженGetMessage()
. Если нет ничего , чтобы подглядывать,PeeMessage()
возвращает FALSE, так что воwhile
цикла до сих пор работает.