Win32: Как нарисовать за пределами моего окна?
Глядя на Windows tooltips
окно подсказки класса, я вижу, что оно рисует свою тень вне фактического прямоугольника окна подсказки.
Используя 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 Грега Шехтера:
Рисование и чтение с экрана - Baaaad!
Наконец, так как мы находимся на теме перенаправления, одной особенно опасной практикой является запись на экран, либо посредством использования GetDC(NULL) и записи в него, либо попыткой сделать линии с резиновой лентой XOR и т. Д. Есть два Основные причины, по которым запись на экран плохая:
Это дорого... запись на сам экран не дорогая, но почти всегда сопровождается чтением с экрана, потому что при записи на экран обычно выполняются операции чтения-изменения-записи, такие как XOR. Чтение с поверхности видеопамяти очень дорого, требует синхронизации с DWM и останавливает весь канал GPU, а также канал приложения DWM.
Это непредсказуемо... если вам каким-то образом удастся добраться до фактического основного объекта и написать в него, не может быть никакой предсказуемости относительно того, как долго то, что вы записали в основной объект, будет оставаться на экране. Поскольку UCE не знает об этом, он может быть очищен при следующем обновлении кадра или может сохраняться в течение очень долгого времени, в зависимости от того, что еще нужно обновить на экране. (Мы действительно не разрешаем прямую запись в первичную базу, по той же причине... если вы попытаетесь получить доступ к первичному DirectDraw, например, DWM отключится, пока не завершится доступ к приложению)
3 ответа
Вы не можете рисовать за окном так, как вы описываете.
Если вы щелкнете правой кнопкой мыши по своему рабочему столу, перейдите в свойства / внешний вид / эффекты и снимите флажок "Показать тени под меню"... у вас больше не будет тени.
Суть в том, что это продукт оконного менеджера, а не вашей программы.
Q: Как вы рисуете за пределами одного окна? A: Нарисуйте внутри другого окна!
Первое, что нужно отметить, это то, что класс всплывающей подсказки действительно использует CS_DROPSHADOW
стиль - но обратите внимание, что это стиль класса, а не стиль окна, поэтому вы должны взглянуть на вкладку Класс в диалоге свойств Spy++, чтобы найти его. Вы увидите, что tooltips_class32
Windows действительно имеет это - и несколько других.
Но это только приводит к следующему вопросу - как это работает? Что ж, похоже, что Windows реализует это, создавая вспомогательный HWND для рисования тени - предположительно, он создает другое всплывающее окно того же размера и формы, что и затененное, заполняя его серым, помещая его непосредственно под главное окно, и устанавливая это как окно WS_EX_LAYERED, так что тень может быть прозрачной и исчезать по краям, используя альфа-смешение. И ничто не мешает вам использовать те же или похожие методы самостоятельно, если вы хотите добавить другой тип эффекта тени к одному из ваших собственных окон.
Итак, короткая история: если вы хотите рисовать за пределами своего собственного окна, создайте прозрачное вспомогательное окно в общей области, на которой вы хотите рисовать, и вместо этого нарисуйте это вспомогательное окно.
-
Теперь, если вы попытаетесь найти одно из этих вспомогательных теневых окон в Spy++, вы не найдете много. в отличие от tooltip_class32
Окна, которые являются долгоживущими и просто скрывают / показывают себя по мере необходимости, эти теневые окна являются более неуловимым существом: они создаются только столько времени, сколько необходимо, поэтому вам придется обновлять Spy++, пока есть всплывающая подсказка или всплывающее меню или другое окно, использующее тень - и это сложно, поскольку большинство подсказок и меню исчезают, как только вы перемещаете мышь, чтобы переключиться на Spy++. Но оказывается, что всплывающие подсказки на собственной панели инструментов Spy++: запустите Spy++, наведите курсор мыши на элемент на панели инструментов и нажмите F5
обновить дерево HWND при наличии всплывающей подсказки и тени. Теперь прокрутите вниз, и вы увидите, что третий и четвертый видимые HWND в дереве - это сама всплывающая подсказка, а сразу после этого SysShadow
окно. К сожалению, поскольку всплывающая подсказка и тень к настоящему времени исчезли, если вы попытаетесь открыть диалоговое окно свойств для этого HWND, вы получите пустое диалоговое окно свойств с сообщением "Неверное окно". Если вы действительно хотите поэкспериментировать и посмотреть, как работает этот SysShadow, какие стили он сам использует и так далее, вы можете создать целевое приложение с долгоживущим всплывающим окном, которое использует CS_DROPSHADOW
что вы можете исследовать в Spy++ на досуге.
(Наконец, обратите внимание, что эти тени - это нечто совершенно иное, чем тени, которые вы видите, когда одно окно приложения находится поверх другого над другим с Vista: этот тип тени является частью режима Aero Glass и обрабатывается той же композицией рабочего стола. Менеджер, который добавляет эффект стеклянного заголовка, и ему не нужны вспомогательные окна для реализации теней.
Я не удивлюсь, если эта тень тесно связана с самим оконным менеджером; в конце концов, оконный менеджер решает, какое окно будет рисовать, какие части себя и когда он сможет это сделать. Я не считаю ракетостроением рисовать эту тень, если контролирует все, что получено, что есть у оконного менеджера.