Мерцающие дочерние окна с альфа-каналами - PullRequest
2 голосов
/ 15 мая 2009

При рисовании дочерних элементов управления, содержащих растровые изображения с альфа-каналами на пиксель, мы получаем довольно много мерцаний, когда их нужно перерисовать. Фактическое смешивание работает правильно. Я нашел много информации об уменьшении мерцания (например, этот вопрос или этот сайт ), но я не могу найти ничего, что относится именно к этой ситуации.

Например, у меня есть кнопка с несколькими различными растровыми изображениями, которые альфа-смешиваются и перетаскиваются в окно, в зависимости от состояния кнопки. Когда их состояние изменяется, и мне нужно нарисовать другое растровое изображение, мне нужно сначала перерисовать фон, иначе он смешивается с пикселями, оставшимися от растрового изображения предыдущего состояния. Это то место, где я начинаю мерцать, где иногда всплывает немного фона.

Проблема усложняется тем, что родительские окна верхнего уровня рисуют фоновый рисунок, а не сплошной цвет, вместе с возможностью перекрытия дочерних элементов управления; просто умножение базового цвета на растровое изображение дочернего элемента исключено, как и использование WS_CLIPCHILDREN.

Поскольку окна имеют растровый фон, я возвращаю true на WM_ERASEBKGND, чтобы избежать рисования цвета, который будет просто перезаписан.

Конечно, двойная буферизация, похоже, решит все это, но я не смог заставить ее работать правильно. Я установил WS_COMPOSITED для окон верхнего уровня и WS_TRANSPARENT для дочерних окон. Когда приходит время перерисовать дочернее окно с новым растровым изображением, у меня возникает несколько проблем (скорее всего, я не понимаю, как работает порядок рисования в этой ситуации):

  • Если я вызову InvalidateRect() и передам дочерний дескриптор, дочернее окно действительно перерисовывается, но фон не перерисовывается, и поэтому пиксели накапливаются друг на друге, смешиваясь вместе.
  • Если я вызову InvalidateRect() и передам дескриптор parent с прямоугольником, состоящим из размеров дочернего окна, фон будет перерисован, а дочернее окно - нет.
  • Если я сделаю оба из вышеперечисленного, то фон перерисовывается так же, как и дочернее окно, и выглядит именно так, как я хотел бы - за исключением того, что мне удалось сделать это снова мелькнуть (что не удивительно, поскольку кажется, что звонить InvalidateRect() дважды ужасно хакерски, так как я предполагаю, что каждый вызов, вероятно, вызывает переворот в буферах, что наносит ущерб цели).

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

Ответы [ 2 ]

2 голосов
/ 15 мая 2009

Используете ли вы многослойные окна ? Если нет, возможно, попробуйте.

Также для двойной буферизации рассмотрите эту технику .

1 голос
/ 15 мая 2009

Это может быть совершенно не по назначению - мои дни были давным-давно ...

Но не могли бы вы просто рассчитать смеси для разных состояний? Я предполагаю, что ваша кнопка может быть включена / отключена и вверх / вниз, так что это только 4 комбинации. Почему бы не рассчитать комбинированные растровые изображения?

Или это проблема взаимодействия уже комбинированных растровых изображений с существующим состоянием?

...