Мерцающие дочерние окна с альфа-каналами

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

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

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

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

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

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

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


person Doug Kavendek    schedule 14.05.2009    source источник
comment
Как узнать, что фоновое окно перерисовывается, а дочернее - нет? Вы делаете недействительным прямоугольник больше дочернего окна?   -  person Mark Ransom    schedule 15.05.2009
comment
Когда я вызываю InvalidateRect () с родительским дескриптором, фоновое изображение, которое я рисую в родительском окне, перерисовывается поверх дочернего окна, но дочернее окно не рисуется поверх него, как если бы родительский элемент был нарисован после дочернего. Хотя, поскольку msdn сообщает, что все потомки окна получают порядок рисования снизу вверх с использованием двойной буферизации, я думаю, этого следовало ожидать.   -  person Doug Kavendek    schedule 18.05.2009


Ответы (2)


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

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

person Valentin Galea    schedule 14.05.2009
comment
Я использую многоуровневые окна для очень конкретных целей прямо сейчас, хотя думаю, что смогу применить их в нескольких конкретных случаях, где это возможно. Кроме того, другой вариант - не использовать MFC, а вручную выполнить двойную буферизацию. - person Doug Kavendek; 18.05.2009

Это могло быть совершенно не по плану - мои дни с графическим интерфейсом были давным-давно ...

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

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

person Mike G.    schedule 14.05.2009
comment
Что-то подобное могло бы сработать, если бы я автоматизировал его для каждого экземпляра, поскольку одно и то же исходное растровое изображение может быть поверх любого количества разных фонов. Это не поможет с окнами, которые будут перемещаться (для этого может потребоваться использование многоуровневых окон), но это решит случайное мерцание на кнопках. - person Doug Kavendek; 18.05.2009