2013-10-07 7 views
0

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    • Расчет сроков должен выполняться для поддержания стабильной частоты кадров.
+0

Застряли в UpdateLayeredWindow? Можно создать многоуровневое окно с WM_PAINT с помощью SetLayeredWindowAttributes. Если это возможно с помощью этого, вы избавитесь от вопроса о подготовке механизма обновления. – xMRi

+1

«Как это соотносится с частотой кадров других приложений?» Если приложение не анимирует что-то или не отображает видео, его частота кадров будет равна нулю. Чтобы повторно перерисовать экран без каких-либо оснований - это украсть процессорное время из более продуктивных применений, сгладить батареи ноутбуков, изнашивать вентиляторы и сделать себя целью для удаления. Серьезно, если ваше приложение ничего не делает, ничего не делайте. – arx

ответ

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 while все еще работает. –

+0

Согласен. Но таким образом мне не нужно использовать дополнительную обработку для WM_QUIT. Да, вы можете просто использовать PM_REMOVE и проверить WM_QUIT после заглядывания. Это вопрос стиля. – xMRi

+0

Хммм, давайте посмотрим ... peek + удалить сообщение и посмотреть его идентификатор напрямую - vs - заглянуть в сообщение, но оставить его в очереди, затем вернуться в очередь и заглянуть + удалить одно и то же сообщение и иметь API посмотрите на идентификатор и верните BOOL, который вы должны проверить. Да, тот же эффект ... но больше кода и больше работы для API. Но, как вы сказали, это «просто вопрос стиля». Лично я не думаю, что API должен делать больше работы, чем нужно, но это только мой стиль :) –

1

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

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

Смежные вопросы