Рисование настраиваемых кнопок в строке заголовка Windows Vista / 7 Aero

Я нашел этот вопрос на StackOverflow. По сути, пользователь хотел нарисовать настраиваемые кнопки на строке заголовка.

Я попробовал код и понял, что в Vista / 7 он работает только при отключенном Aero. У меня вопрос: есть ли способ нарисовать пользовательские кнопки на панели заголовка при включенном aero?

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


Обновить

Вот скриншот с моего компьютера, демонстрирующий вышеуказанную концепцию. После установки DisplayFusion у меня появились дополнительные кнопки заголовка.
Notepad2 показывает дополнительные кнопки.

И я знаю, что DisplayFusion - это программа .NET, потому что она открывается в .NET Reflector. Обратной стороной является то, что программа запутана. Не то чтобы я хотел декомпилировать программу или что-то в этом роде; Я просто хочу добавить кнопку в заголовок, чтобы сделать что-то еще (например, свернуть в системный трей).
Ниже приведен снимок экрана, подтверждающий, что программа является приложением .NET.
. NET Reflector, показывающий DisplayFusion


person Alex Essilfie    schedule 07.11.2010    source источник
comment
Забудьте об этом, это просто больше не работает.   -  person Hans Passant    schedule 07.11.2010
comment
Я знаю, что это возможно, потому что это приложение для нескольких мониторов под названием Display Fusion, которое делает именно это. Я знаю, что это .NET-приложение, потому что я смотрел на него с помощью .NET Reflector Лутца Рёдера.   -  person Alex Essilfie    schedule 07.11.2010


Ответы (3)


Если вы готовы перерисовать все содержимое строки заголовка, вы можете использовать метод DWM API DwmExtendFrameIntoClientArea, который включает в себя настройку окна без заголовка, что позволяет DWM втягивать свой стакан в используемую область для создания новое пространство, которое выглядит как заголовок, но фактически находится в вашей клиентской области, так что вы можете рисовать на нем кнопки.

Обратной стороной этого метода является то, что вам придется делать стандартные кнопки, если они вам нужны. Свернуть, развернуть и закрыть - не проблема для воссоздания (хотя вы обнаружите, что кнопка максимизации представляет собой переключатель, внешний вид которого зависит от состояния), но вы можете обнаружить, что у вас возникли проблемы с воссозданием кнопки в верхнем левом углу. Вам также, конечно, придется перерисовать свой заголовок, но я не могу представить, что у вас возникнут какие-либо проблемы с этим.

Что касается чтения данных текущей темы, чтобы изменить стиль ваших кнопок как их, извините, но я ничего об этом не знаю. Я предлагаю использовать прозрачность при построении кнопок на заголовке, а также использовать эффекты полупрозрачного свечения и т. Д. Таким образом вы сможете сохранить стеклянный фон и просто изменить его внешний вид, наложив полупрозрачный цвет. Кроме того, если вы сделаете это таким образом, то смещающиеся зеркальные блики на стекле будут двигаться естественным образом, тогда как если вы просто получите цвета их темы, вы обнаружите, что либо у вас нет доступа к их отражениям, либо они воссоздаются заново внутри пространство ваших кнопок. Конечно, всего два цента - если вы сможете найти способ сделать цвета своей темы и так далее, во что бы то ни стало.

Однако есть одно предостережение - есть еще один поток StackOverflow (http://stackoverflow.com/questions/2666979/net-framework-4-0-and-drawing-on-aero-glass-issue/4656182#4656182), который описание проблемы с методом DWM API DwmExtendFrameIntoClientArea, поэтому на вашем месте я бы прочитал его, прежде чем пробовать это решение.

person David Hagan    schedule 13.01.2011

Я провел некоторое исследование по этому поводу, так как реализовал это тоже в своем собственном решении с несколькими мониторами. Это реализовано в DisplayFusion и TeamViewer путем наложения настраиваемой формы на желаемое окно, содержащее кнопки. Вы можете использовать Spy ++, чтобы подтвердить это.

Это общая идея:

  1. Напишите обработчик DLL для получения уведомлений при создании, удалении, активации, перемещении или изменении размера окна.
  2. Сделайте прозрачную форму, используя ключ прозрачности или решение для альфа-PNG и GDI + и смоделируйте кнопки, раскрасив их самостоятельно.
  3. При создании / удалении окна вы показываете / скрываете форму кнопки заголовка для желаемых окон.
  4. В сообщениях об изменении размера / перемещении окна вы перестраиваете форму кнопки заголовка.
  5. При активации окна вы устанавливаете положение окна по оси Z так, чтобы оно находилось наверху желаемого окна.

Получение и установка положения Z через API GetWindow и SetWindowPos.
Имейте в виду, что DLL должна быть написана на родном языке. Однако вы можете использовать что-то вроде этого, чтобы обойти эту проблему: Использование оконных сообщений для реализации глобальных системных хуков в C #

И вот мой результат:

введите описание изображения здесь

person Jelle Vergeer    schedule 11.06.2012
comment
Ваше решение выглядит многообещающим. Я придумал, как создать прозрачную форму и обнаруживать открытие, перемещение и закрытие окон. Я хотел бы знать, как вы создаете пустые тематические кнопки, чтобы я мог нарисовать свои собственные. Если возможно, вы можете загрузить свое решение? - person Alex Essilfie; 12.06.2012
comment
Не могли бы вы опубликовать код, чтобы показать, как вы создали кнопки строки заголовка на скриншоте? - person Alex Essilfie; 21.06.2012
comment
@Jelle Vergeer Пожалуйста, рассмотрите возможность добавления ссылки на исходный код результата, мне нужно это решение ... +1 - person ElektroStudios; 20.03.2013
comment
Я напишу статью о CodeProject, как это сочетается друг с другом, но это может занять некоторое время, так как у меня сейчас мало свободного времени .. - person Jelle Vergeer; 07.04.2013

Хорошо, системные хуки - это прямой подход для получения информации об измененных положениях окон, и предложение Jelle с прозрачной формой очень хорошо . Но вы можете использовать менее инвазивный метод для получения информации об окнах рабочего стола с помощью user32.dll.

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);

Дескрипторы окон, которые вы можете получить с помощью EnumDesktopWindows

[DllImport("user32.dll", EntryPoint = "EnumDesktopWindows", 
ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDelegate lpEnumCallbackFunction, IntPtr lParam);

Пример этого вы можете получить из потока get-a- list-of-all-applications-in-c-sharp

person Tobias Kasper    schedule 13.11.2015