Win32:Как сделать drop shadow для непрямоугольного многослойного окна?
-
19-09-2019 - |
Вопрос
я создал многоуровневое окно путем добавления в WS_EX_LAYERED расширенный стиль:
wndClass.ExStyle = wndClass.ExStyle | WS_EX_LAYERED;
Windows будет использовать черный цвет в качестве значения цвета ключа цветности.я собираюсь оставить большую черную рамку, чтобы сделать проблему очевидной:
После того, как окно создано, я сообщаю ему используйте черный цвет в качестве хромакея:
SetLayeredWindowAttributes(hwnd, 0x00000000, 255, LWA_COLORKEY);
Теперь всплывающее многоуровневое окно выглядит частично прозрачным:
Проблема - это заключительный шаг.я хочу использовать CS_DROPSHADOW стиль класса, доступный начиная с Windows XP, для создания падающей тени:
wndClass.Style = wndClass.Style | CS_DROPSHADOW;
Появится отбрасываемая тень, но тень окружает исходное прямоугольное окно и не учитывает прозрачность окна, обеспечиваемую многоуровневым окном:
Кто-нибудь знает, какую волшебную опцию я где-то пропустил, которая заставит отбрасываемую тень соответствовать непрямоугольному слоистому окну?
Другой пример, когда возникает эта проблема, - это когда вы не включаете отступы / поля размером 6 пикселей.Окно подсказки, нарисованное в Windows® themes, не является прямоугольным.Это оставляет небольшой видимый зазор, где окно прозрачно, но отбрасываемая тень не появляется:
Microsoft удалось заставить это работать, как вы можете видеть из этой подсказки в Internet Explorer:
Присматриваюсь к Окнам поближе tooltips
окно подсказки класса.Используя Шпионский секс - я могу получить его прямоугольник окна и стили классов:
SpyXX говорит:
Rectangle: (440, 229)-(544, 249), 104x20
Restored Rect: (440, 229)-(544, 249), 104x20
Client Rect: (0, 0)-(104, 20), 104x20
Таким образом, все указывает на то, что само окно имеет размер 104х20 пикселей, а отбрасываемая тень находится за пределами самого окна.(Что согласуется с CS_DROPSHADOW
.)
Далее я могу взглянуть на стили tooltips
класс окна:
Windows Styles: 94000001
WS_POPUP 80000000
WS_VISIBLE 10000000
WS_CLIPSIBLINGS 4000000
TTS_ALWAYSTIP 1
Extended Styles: 00080088
WS_EX_LAYERED 80000
WS_EX_TOOLWIN 80
WS_EX_TOPMOST 8
Интересно, что он не использует CS_SAVEBITS
(0x800
);что полезно для небольших, недолговечных окон.
Также он не использует CS_DROPSHADOW
(0x20000
).Так что теперь мне интересно, как он рисует за пределами своего собственного окна?
Примечание: Прозрачные многослойные окна задокументированы как предпочтительный метод по сравнению с регионами.
Редактировать: Многоуровневые окна появились вместе с Windows 2000.CS_DropShadow был добавлен с XP.
Решение
Прозрачные многослойные окна задокументированы как предпочтительный метод по сравнению с регионами.
Однако, CS_DROPSHADOW
делает обратите внимание на регионы.Если вы обрезаете окно или иным образом придаете ему форму, используя область, отбрасываемая тень будет повторять новый контур.
К счастью, вы может используйте области со слоистыми окнами и, комбинируя их, получите желаемый эффект.
КСТАТИ:tooltips_class32 инструментальный класс делает используйте CS_DROPSHADOW - вы не увидите его в оконных стилях, потому что это стиль класса, а не стиль окна.
Другие советы
Почему бы вам не использовать LWA_ALPHA и не встроить тень в изображение?
Отредактируйте в ответ на ваш комментарий:
A) Не мешает вам использовать PNG с альфа-каналом только для тени.Соедините 2 изображения вместе и используйте как одно изображение.
Б) Создать отбрасываемую тень несложно.На изображении, которое вы опубликовали, оно черного цвета с 3 различными альфа-значениями.
В) Но это не работает, не так ли?то есть пришло время проявить творческий подход.
D) Тогда не пытайтесь заставить Windows делать что-то, чего она не сделает за вас.
E) Совершенно не имеет значения.Многоуровневые окна справятся с этим за вас.
Я настоятельно рекомендую вам узнать больше о многоуровневых окнах, потому что они МОГУТ помочь вам в достижении вашей цели.
Редактировать 2:У вас есть растровое изображение.Довольно легко отсканировать изображение и найти, какие биты будут иметь цветовую маркировку (самостоятельно определив черный цвет), и затем изменить это, чтобы оно имело альфа-значение 0, где все остальное будет иметь альфа-значение 255 (не:Возможно, вам придется преобразовать изображение в 32-разрядное изображение из более низкого цветового формата, вы можете сделать это, создав новый DC и скопировав изображение).Это даст вам тот же эффект с LWA_ALPHA, что и с LWA_COLORKEY.Оттуда довольно легко идентифицировать пиксель на краю, где цвет меняется на (R = 0, G = 0, B = 0, A = 0).Затем вы изменяете этот первый пиксель так, чтобы он имел n alpha равным 192, тот, что ниже, увеличиваете его до 128, а тот, что ниже, до 64.Теперь у вас есть альфа-градация под изображением, которая будет выглядеть как тень.Вы можете настроить альфа-частоту, чтобы получить желаемый эффект.
CS_DROPSHADOW
работает только со стандартными прямоугольными окнами. WS_EX_LAYERED
windows поддерживает не все.Это скорее низкоуровневый метод самообслуживания, позволяющий нарисовать именно то, что вы хотите.
Чтобы получить отбрасываемую тень, вам нужно будет самостоятельно сгенерировать отбрасываемую тень из альфа-канала на изображении.