Как рисовать за окном?

Глядя на окно подсказки класса tooltips в Windows, я вижу, что она рисует свою тень вне фактического прямоугольника окна подсказки.

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

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

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

Примечание: тень не рисуется с использованием стандартного CS_DROPSHADOW стиля класса. я подтвердил это экспериментально, а также могу увидеть стиль класса для окна в SpyXX; он не использует CS_DROPSHADOW:

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

Итак, как я могу рисовать за окном?

Примечание. Попытка рисовать на рабочем столе DC отсутствует. Из перенаправления GDI, Грега Шехтера, Приложения DirectX и WPF:

Рисование и чтение с экрана - Баааад!

Наконец, поскольку мы затронули тему перенаправления, одна особенно опасная практика - это запись на экран либо с использованием GetDC (NULL) и запись в него, либо попытка выполнения строк с резинкой XOR и т. Д. важные причины того, что писать на экран плохо:

Это дорого ... запись на экран сама по себе не дорогая, но она почти всегда сопровождается чтением с экрана, потому что при записи на экран обычно выполняются операции чтения-изменения-записи, такие как XOR. Чтение с поверхности видеопамяти очень дорого, требует синхронизации с DWM и останавливает весь конвейер графического процессора, а также конвейер приложения DWM.
Это непредсказуемо ... если вам каким-то образом удастся добраться до фактического основного и напишите в него, невозможно предсказать, как долго то, что вы написали на первичный компьютер, будет оставаться на экране. Поскольку UCE не знает об этом, он может быть очищен при следующем обновлении кадра или может сохраняться в течение очень долгого времени, в зависимости от того, что еще нужно обновить на экране. (Мы действительно не разрешаем прямую запись на первичный сервер, именно по этой причине ... например, если вы попытаетесь получить доступ к первичному серверу DirectDraw, DWM отключится до тех пор, пока приложение, обращающееся к нему, не закроется)


person Ian Boyd    schedule 09.02.2010    source источник
comment
Простой ответ - вы не можете рисовать за окном. По указанным причинам это плохая идея. это означает, что то, что вы видите, когда падающие тени за пределами оконных рамок, - это не необработанный рабочий стол, а какое-то составное изображение. В Windows 6 составным рабочим столом управляет dwm.exe - в Windows XP я не знаю - вы рисуете фон элемента управления с помощью DrawThemeBackground?   -  person Chris Becke    schedule 10.02.2010


Ответы (3)


Вы не можете рисовать за окном так, как вы описываете.

Если вы щелкните правой кнопкой мыши на рабочем столе, затем перейдите в свойства / внешний вид / эффекты и снимите флажок «Показывать тени в меню» ... у вас больше не будет тени.

Суть в том, что это продукт оконного менеджера, а не вашей программы.

person Community    schedule 09.02.2010
comment
Как выглядит tooltips общий контрольный рисунок за пределами своего окна? Или какую функцию Windows он просит использовать? - person Ian Boyd; 10.02.2010
comment
@ Ян Бойд - я думаю, вы неправильно поняли. Сам элемент управления не рисует за пределами своего окна. Когда диспетчер окон просят нарисовать окна определенными классами, такими как «меню» или «всплывающие подсказки», он (диспетчер окон) отображает отбрасывающуюся тень, а затем окно. Он встроен в оконный менеджер по умолчанию в Windows. Доступны сменные оконные менеджеры. Некоторые могут иметь открытый исходный код и раскрывать свои секреты. Однако ни одно из окон не красится снаружи. - person ; 10.02.2010
comment
Как общий элемент управления всплывающих подсказок просит диспетчер окон Windows визуализировать тень вокруг своего окна? - person Ian Boyd; 10.02.2010
comment
Суть в том, что это не может быть уловкой оконного менеджера, потому что оконному менеджеру не даются необходимые подсказки, чтобы приказать ему нарисовать падающую тень. Это означает, что элемент управления всплывающей подсказкой явно вызывает какой-то API оконного менеджера для ручного рендеринга тени. что это за api? я заинтригован. - person Chris Becke; 10.02.2010
comment
Диспетчер окон просто добавляет к окну стиль CS_DROPSHADOW. В вашем сообщении выше вы не перечислили стили классов, только стили окон. Если бы вы фактически перечислили стили классов в окне всплывающей подсказки с установленной опцией «Показать тени под меню», вы бы увидели стиль класса CS_DROPSHADOW. Если флажок снят, вы его не увидите. Стиль класса отличается от стилей окна. Почему бы не написать образец программы для проверки? У меня нет на это времени. - person ; 10.02.2010
comment
Всплывающая подсказка (вероятно) использует стиль класса CS_DROPSHADOW (я не знаю, как получить стили класса hWnd) для добавления тени. Причина, по которой тень соответствует непрямоугольной форме окна, потому что к окну применена область (GetWindowRgn подтверждает это). Итак, ответ: «Вы не можете рисовать за окном» - правильный ответ. +1 и принято. - person Ian Boyd; 10.02.2010

В: Как рисовать за пределами одного окна? О: Нарисуйте внутри другого окна!

Прежде всего следует отметить, что класс всплывающей подсказки на самом деле действительно использует стиль CS_DROPSHADOW, но обратите внимание, что это стиль class, а не стиль окна. , поэтому вам нужно взглянуть на вкладку Класс в диалоговом окне свойств Spy ++, чтобы найти его. Вы увидите, что в tooltips_class32 окнах действительно есть это - и несколько других.

Но это приводит к следующему вопросу - как это работает? Что ж, похоже, что Windows реализует это, создав помощник HWND для рисования тени - по-видимому, он создает другое всплывающее окно того же размера и формы, что и затененное, заполняет его серым цветом, помещает его прямо под главное окно и устанавливает это как окно WS_EX_LAYERED, чтобы тень могла быть прозрачной и исчезать по краям с использованием альфа-смешивания. И ничто не мешает вам самостоятельно использовать те же или похожие методы, если вы хотите добавить другой тип теневого эффекта к одному из ваших собственных окон.

Итак, короче: если вы хотите рисовать за пределами своего собственного окна, создайте вспомогательное прозрачное окно в общей области, в которой вы хотите рисовать, и вместо этого нарисуйте это вспомогательное окно.

--

Теперь, если вы попытаетесь найти одно из этих вспомогательных теневых окон в Spy ++, вы мало что найдете. В отличие от tooltip_class32 окон, которые долговечны и просто скрываются / отображаются по мере необходимости, эти теневые окна - более неуловимое существо: они создаются только на столько времени, сколько необходимо, поэтому вам придется обновлять Spy ++, пока есть всплывающая подсказка. или всплывающее меню или другое окно, использующее тень - и это сложно, поскольку большинство всплывающих подсказок и меню исчезнут, как только вы переместите мышь, чтобы переключиться на Spy ++. Но оказывается, что всплывающие подсказки на собственной панели инструментов Spy ++ остаются: так что запустите Spy ++, наведите указатель мыши на элемент на панели инструментов и нажмите F5, чтобы обновить дерево HWND, пока присутствуют всплывающая подсказка и тень. Теперь прокрутите вниз, и вы должны увидеть, что третий и четвертый видимые HWND в дереве - это сама всплывающая подсказка, а сразу после нее - окно SysShadow. К сожалению, поскольку всплывающая подсказка и тень к настоящему времени исчезли, если вы попытаетесь открыть диалоговое окно свойств для этого HWND, вы получите пустое диалоговое окно свойств с сообщением «Недействительное окно». Если вы действительно хотите осмотреться и посмотреть, как работает этот SysShadow, какие стили он сам использует и т. Д., Вы можете создать целевое приложение с долгоживущим всплывающим окном, которое использует CS_DROPSHADOW, которое вы затем можете изучить в Spy ++ на досуге.

(Наконец, обратите внимание, что эти тени - это совершенно другая вещь, чем тени, которые вы видите, когда одно окно приложения находится поверх другого над другим, начиная с Vista: этот тип тени является частью режима Aero Glass и обрабатывается одним и тем же Desktop Composition Manager, который добавляет стеклянный эффект заголовка, и он не использует и не нуждается в вспомогательных окнах для реализации теней.)

person BrendanMcK    schedule 07.01.2013

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

person Johann Gerell    schedule 09.02.2010
comment
Я также не верю, что tooltips общий элемент управления рисует сам тень. Но тогда какую функцию Windows он использует? - person Ian Boyd; 10.02.2010