Win32: Как заставить падающую тень соблюдать непрямоугольное окно Layered?

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

alt text

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

alt text


Рассмотрение ближе Windows tooltips окно подсказки класса. Используя SpyXX - я могу добраться, его окно реагируют, и стили класса:

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.

17
задан 11 revs, 2 users 92% 14 June 2019 в 01:08
поделиться

3 ответа

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

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

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

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

6
ответ дан 30 November 2019 в 14:41
поделиться

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

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

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

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

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

1
ответ дан 30 November 2019 в 14:41
поделиться

CS_DROPSHADOW only works with standard rectangular windows. WS_EX_LAYERED windows don't support everything. They are more of a low-level, self-service method to draw exactly what you want.

To get a drop shadow, you'll have to generate the drop-shadow yourself from the alpha channel in the image.

1
ответ дан 30 November 2019 в 14:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: