Как получить ширину области уведомлений панели задач в программе на C #? - PullRequest
0 голосов
/ 28 сентября 2018

Я разрабатываю функцию в приложении C # Winforms, которая требует определения ширины «области уведомлений» Windows панели задач (в частности, когда она закреплена в расположении по умолчанию в нижней части экрана).

Для лучшего контекста программа отображает небольшие переходные окна без полей (как всплывающая подсказка), и мы бы хотели, чтобы значки и часы в области уведомлений «на панели задач» никогда не закрывались одним из этих окон..

Ниже приведен снимок экрана (из Windows 10) ширины, которую я хотел бы получить, и способ ее использования:

Width dimension needed from Notification Area of Task Bar, and explanation of use

До сих пор я изучал платформу .Net, а также исследовал вызовы Win32 API, однако я не смог определить какие-либо потенциальные решения (и не установить, действительно ли это возможно).

Любые предложения будут ценны.В идеале решение было бы совместимо еще с Windows 7, однако это не является абсолютным требованием.

1 Ответ

0 голосов
/ 30 сентября 2018

Положение и размер окна панели задач (или панели задач) и его дочерних окон можно получить с помощью GetWindowRect () , передав Handle соответствующего окна.
Окна Handle возвращается FindWindowEx () (FindWindowExW), используя имя класса окна для его идентификации.(Как примечание, эта функция выполняет регистронезависимый поиск .)

Есть некоторые важные детали, которые следует учитывать при выполнении такого рода мер, как отметил Ханс Пассант в своемкомментарий.

Эта операция не является чем-то, что Framework или система должны поддерживать.Имена классов могут измениться в будущем.Это не управляемая задача.

Самое главное, приложение должно поддерживать DPI.В противном случае приложение подлежит виртуализации.
Это означает, что при использовании функции API, не поддерживающей DPI, его показатели / результаты также можно виртуализировать.
GetWindowRect(), например, неФункция DPI-Aware.

От MSDN:
Масштабирование DPI в смешанном режиме и API-интерфейсы с поддержкой DPI

Некоторые заметки изТАК вопрос:
Получение правильного RECT с поддержкой DPI из GetWindowRect

Об осведомленности о DPI , я написал несколько замечаний здесь .
Кроме того, этот (классический) ответ Ханса Пассанта:
Как настроить приложение для правильной работы на компьютере с настройкой высокого разрешения (например, 150%)?

Из блога Рэймонда Чена:
Как мне обновить приложение WinForms, чтобы оно работало лучше при высоком DPI или при нормальном DPI на очень больших экранах?

Из MSDN:
Разработка приложений настольного компьютера с высоким разрешением в Windows


Окно панели задач имеет имя класса Shell_TrayWnd.Его положение и относительный размер могут быть определены пользователем.Это экстент класса Windows в его положении по умолчанию.

Shell_TrayWnd

Область уведомлений лотка является дочерним окном Shell_TrayWnd.Его имя класса TrayNotifyWnd

TrayNotifyWnd

Пара других дочерних классов:

Панель задач, название класса MSTaskSwWClass:

MSTaskSwWClass

Часы лотка, название класса TrayClockWClass:

TrayClockWClass

Эти имена классов применяются к этим системным компонентам как в Windows 7, так и в Windows 10

Некоторые примечания об именованииСоглашение здесь:
Рэймонд Чен о Почему некоторые люди называют панель задач «трей»?


Shell_TrayWnd parent это Desktop, таким образом, мыВы передаете IntPtr.Zero в качестве родительского дескриптора.
Можно использовать insted GetDesktopWindow () .

TrayNotifyWnd является дочерним окном Shell_TrayWnd.Мы используем его дескриптор для ускорения поиска.

using System.Drawing;
using System.Runtime.InteropServices;

//Shell Tray rectangle
IntPtr HANDLE = FindWindowByClassName(IntPtr.Zero, "Shell_TrayWnd");
Rectangle ShellTrayArea = GetWindowRectangle(HANDLE);

//Notification area rectangle
HANDLE = FindWindowByClassName(HANDLE, "TrayNotifyWnd");
Rectangle TrayNotifyArea = GetWindowRectangle(HANDLE);

Windows API объявлений:

public struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;

    public Rectangle ToRectangle() => Rectangle.FromLTRB(Left, Top, Right, Bottom);
}

[SuppressUnmanagedCodeSecurity, SecurityCritical]
internal static class SafeNativeMethods
{
    [DllImport("User32.dll", SetLastError = true)]
    internal static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);

    [DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
}

//Helper methods
[SecuritySafeCritical]
public static IntPtr FindWindowByClassName(IntPtr hwndParent, string lpszClass)
{
    return SafeNativeMethods.FindWindowEx(hwndParent, IntPtr.Zero, lpszClass, null);
}

[SecuritySafeCritical]
public static Rectangle GetWindowRectangle(IntPtr WindowHandle)
{
    RECT rect;
    new UIPermission(UIPermissionWindow.AllWindows).Demand();
    SafeNativeMethods.GetWindowRect(WindowHandle, out rect);
    return rect.ToRectangle();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...