Нарисуйте пользовательские кнопки в Windows Vista/7 Aero Titlebar

Я нашел этот вопрос на qaru.site/info/516397/.... В принципе, пользователь хотел нарисовать пользовательские кнопки в заголовке.

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

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


Обновление

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

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

Ответ 1

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

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

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

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

Ответ 2

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

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

  • Записывать DLL-крючок для получения уведомлений при создании, удалении, активации, изменении или изменении окна.
  • Сделайте прозрачную форму с помощью ключа прозрачности или используя альфа-PNG и GDI + решение и имитируйте кнопку (ы), покрасив ее самостоятельно.
  • При создании/удалении окна вы показываете/скрываете форму titlebarbutton для нужного окна (ов).
  • В окне resize/reposition messages вы перегруппируете форму titlebarbutton.
  • При активации окна вы устанавливаете положение Z окна так, чтобы оно находилось поверх желаемого окна.

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

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

enter image description here

Ответ 3

Хорошо, системные перехватчики - это прямой подход для получения информации об измененных положениях окна и Предложение Джелла с прозрачной формой - это очень хорошо. Но вы можете использовать менее инвазивный метод для получения информации о окнах рабочего стола с помощью 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);

Пример для этого можно получить из потока getting-a-list-of-all-applications-in-c-sharp