Win32:Как сделать drop shadow для непрямоугольного многослойного окна?

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

Вопрос

я создал многоуровневое окно путем добавления в WS_EX_LAYERED расширенный стиль:

wndClass.ExStyle = wndClass.ExStyle | WS_EX_LAYERED;

Windows будет использовать черный цвет в качестве значения цвета ключа цветности.я собираюсь оставить большую черную рамку, чтобы сделать проблему очевидной:

alt text


После того, как окно создано, я сообщаю ему используйте черный цвет в качестве хромакея:

SetLayeredWindowAttributes(hwnd, 0x00000000, 255, LWA_COLORKEY);

Теперь всплывающее многоуровневое окно выглядит частично прозрачным:

alt text


Проблема - это заключительный шаг.я хочу использовать CS_DROPSHADOW стиль класса, доступный начиная с Windows XP, для создания падающей тени:

wndClass.Style = wndClass.Style | CS_DROPSHADOW;

Появится отбрасываемая тень, но тень окружает исходное прямоугольное окно и не учитывает прозрачность окна, обеспечиваемую многоуровневым окном:

Кто-нибудь знает, какую волшебную опцию я где-то пропустил, которая заставит отбрасываемую тень соответствовать непрямоугольному слоистому окну?


Другой пример, когда возникает эта проблема, - это когда вы не включаете отступы / поля размером 6 пикселей.Окно подсказки, нарисованное в Windows® themes, не является прямоугольным.Это оставляет небольшой видимый зазор, где окно прозрачно, но отбрасываемая тень не появляется:

alt text

Microsoft удалось заставить это работать, как вы можете видеть из этой подсказки в Internet Explorer:

alt text


Присматриваюсь к Окнам поближе 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 поддерживает не все.Это скорее низкоуровневый метод самообслуживания, позволяющий нарисовать именно то, что вы хотите.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top