Использование многослойных окон для создания плавных границ окон

StackOverflow https://stackoverflow.com/questions/745404

  •  09-09-2019
  •  | 
  •  

Вопрос

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

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

Вот что я делаю:У меня есть окно, назовем его A, с элементами управления, текстом и всем, что входит в это окно.У меня window B является дочерним по отношению к window A , за исключением того, что оно имеет стиль WS_POPUP вместо WS_CHILD , поэтому оно может располагаться за пределами области A и рисуется поверх элементов управления A.Окно B также имеет стиль WS_EX_LAYERED, и при инициализации я вызываю Обновляемый слой окна с флагом ULW_ALPHA и исходным DC с 32-битным растровым изображением с альфа-каналом, чтобы заставить его отрисовываться с использованием альфа-пикселя.

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

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

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

Итак, это работает, но я не могу быть уверен, что это действительно лучший способ сделать это.У меня есть два вопроса:

  • Звучит ли это приемлемо, или в этом есть что-то вопиюще ужасное?
  • Поскольку в настоящее время это работает, кажется, что он использует закадровый буфер размером с окно (который может быть размером до 1024х768), хотя очень немногие его пиксели имеют какие-либо ненулевые данные о непрозрачности - будет ли это стоить накладных расходов и дополнительной сложности разрезания его на отдельные фрагменты границы и объединения их вместе?
Это было полезно?

Решение

Мой продукт использует многоуровневые окна для рисования маленьких вкладок, которые я прикрепляю к каждому окну.Я использовал многоуровневые окна, чтобы получить плавное округление без сглаживания.Единственная неприятная проблема, с которой я столкнулся до сих пор, заключается в том, что некоторые окна OpenGL написаны поверх многоуровневых окон в Windows XP и Vista без DWM.Это проблема низкого уровня, и Microsoft не очень помогла.Вы можете воспроизвести это, открыв Google Планета Земля и перетащив свое приложение через главное окно рендеринга, ваше многоуровневое окно исчезнет.

Другие советы

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

  1. Не забудьте протестировать под RDP и виртуальной машиной (Hyper-V и VMware)
  2. Попробуйте несколько карт gfx, а также на нетбуках и ноутбуках (если применимо).
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top