Win32: Как сделать так, чтобы тень падала в непрямоугольном многослойном окне?

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

wndClass.ExStyle = wndClass.ExStyle | WS_EX_LAYERED;

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

http://i45.tinypic.com/2qs002q.jpg


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

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

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

http://i48.tinypic.com/2cfta3o.jpg


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

wndClass.Style = wndClass.Style | CS_DROPSHADOW;

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

http://i49.tinypic.com/23lnnu9.jpg

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


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

http://i47.tinypic.com/30arsxk.png

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

http://i46.tinypic.com/f104cj.jpg


Глядя ближе на Windowstooltips окно подсказки класса. ИспользуяSpyXX- я могу получить прямоугольник окна и стили классов:

http://i49.tinypic.com/f4pued.jpg

SpyXX говорит:

Rectangle:     (440, 229)-(544, 249), 104x20
Restored Rect: (440, 229)-(544, 249), 104x20
Client Rect:   (0, 0)-(104, 20), 104x20

Таким образом, все указывает на то, что само окно имеет размер 104x20 пикселей, а тень находится за пределами самого окна. (Что согласуется с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 была с Windows 2000. CS_DropShadow был добавлен с XP.

3 ответа

Решение

Прозрачные многослойные окна задокументированы как предпочтительный метод по регионам.

Тем не мение, CS_DROPSHADOW обращает внимание на регионы. Если вы обрезаете или иным образом формируете окно, используя область, тень будет следовать за новым контуром.

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

Кстати: tooltips_class32 использует CS_DROPSHADOW - вы не увидите его в стилях окна, потому что это стиль класса, а не стиль окна.

Почему бы вам не использовать LWA_ALPHA и встроить тень в изображение?

Отредактируйте в ответ на ваш комментарий:

А) Не мешает вам использовать альфа-канал PNG только для тени. Blt 2 изображения вместе и использовать как одно изображение.
Б) Нетрудно создать тень. На изображении вы разместили его черный с 3 различными значениями альфа.
C) Но это не работает, не так ли? т.е. время, чтобы стать творческим.
D) Тогда не пытайтесь заставить окна делать то, что вам не подойдет.
E) Совершенно не имеет значения. Многослойные окна справятся с этим за вас.

Я настоятельно рекомендую вам узнать больше о многослойных окнах, потому что они МОГУТ помочь вам достичь вашей цели.

Edit2: у вас есть растровое изображение. Его довольно легко отсканировать по изображению и найти, какие биты будут выделены цветом (самостоятельно идентифицируя черный), и затем изменить его, чтобы иметь альфа 0, где все остальное будет иметь альфа 255 (Нет: возможно, вам придется преобразовать изображение в 32-битное изображение из более низкого цветового формата, вы можете сделать это, создав новый DC и скопировав изображение). Это даст вам тот же эффект с LWA_ALPHA, что и с LWA_COLORKEY. Оттуда довольно легко идентифицировать пиксель на краю, где цвет меняется на (R = 0, G = 0, B = 0, A = 0). Затем вы изменяете этот первый пиксель, чтобы иметь альфа-значение 192, один - до 128, а второй - до 64. Теперь у вас есть альфа-градация под изображением, которая будет выглядеть как тень. Вы можете настроить альфа, чтобы получить желаемый эффект.

CS_DROPSHADOW работает только со стандартными прямоугольными окнами. WS_EX_LAYERED окна не поддерживают все Это скорее низкоуровневый метод самообслуживания, позволяющий рисовать именно то, что вы хотите.

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

Другие вопросы по тегам