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

я создал многоуровневое окно, добавив расширенный стиль 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;

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

CrLH6.png

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


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

alt text

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

alt text


Присмотревшись ближе к окну tooltips класса tooltips Windows. Используя SpyXX - я могу получить прямоугольник окна и стили классов:

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 была с Windows 2000. CS_DropShadow был добавлен с XP.

Ответы

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

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

Ответ 3

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

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