Lem*_*eed 6 .net c# winapi winforms
我正在 C# Winforms 应用程序中开发一个功能,它需要确定任务栏的 Windows“通知区域”的宽度(特别是当停靠在屏幕底部的默认位置时)。
为了提供更好的上下文,程序显示小的、瞬态的、无边界的窗口(类似于工具提示),我们希望确保通知区域“系统托盘”图标和时钟永远不会被这些窗口之一覆盖。
下面是我想要获得的宽度的屏幕截图(来自 Windows 10),以及它的用途:
到目前为止,我已经探索了 .Net 框架,并研究了 Win32 API 调用,但是我无法确定任何潜在的解决方案(也无法确定这是否确实可行)。
任何建议将不胜感激。理想情况下,解决方案最早可与 Windows 7 兼容,但这并不是绝对要求。
外壳托盘窗口(或任务栏)及其子窗口的位置和大小可以使用GetWindowRect()检索,传递Handle相关窗口的 。
窗口Handle由FindWindowEx() ( FindWindowExW)返回,使用窗口类名来标识它。(注意,此函数执行不区分大小写的搜索)。
正如 Hans Passant 在评论中指出的那样,在执行此类措施时需要考虑一些重要的细节。
此操作不是框架或系统需要支持的。类名将来可能会更改。这不是一项托管任务。
最重要的是,应用程序必须是 DPI Aware。如果不是,则应用程序受虚拟化的约束。
这意味着当使用非 DPI-Aware API 功能时,其测量/结果也可以虚拟化。
GetWindowRect()例如,不是 DPI-Aware 功能。
来自 MSDN:
混合模式 DPI 缩放和 DPI 感知 API
SO 问题中的一些注释:
从 GetWindowRect 获取 DPI 感知正确的 RECT
关于 DPI Awareness,我在这里写了一些笔记。
另外,来自 Hans Passant 的这个(经典)回答:
如何配置应用程序以在具有高 DPI 设置(例如 150%)的机器上正确运行?
来自 Raymond Chen 的博客:
如何更新我的 WinForms 应用程序,使其在高 DPI 或非常大屏幕上的正常 DPI 下表现更好?
来自 MSDN:
Windows 上的高 DPI 桌面应用程序开发
Shell Tray Window 具有类名Shell_TrayWnd。它的位置和相对大小可由用户定义。这是处于默认位置的类 Windows 范围。
托盘通知区域是 的子窗口Shell_TrayWnd。它的类名是TrayNotifyWnd
( Shell_TrayWnd ? TrayNotifyWnd)
其他几个子类:
任务栏,类名MSTaskSwWClass:
( Shell_TrayWnd ? ReBarWindow32 ? MSTaskSwWClass ? MSTaskSwWClass)
托盘时钟,类名TrayClockWClass:
( Shell_TrayWnd ? TrayNotifyWnd ? TrayClockWClass)
这些类名适用于 Windows 7 和 Windows 10 中的这些系统组件
关于命名约定的一些说明:
Raymond Chen on为什么有些人称任务栏为“托盘”?
Shell_TrayWndparent is Desktop,因此我们IntPtr.Zero作为父句柄传递。可以改用
GetDesktopWindow()。
TrayNotifyWnd是 的子窗口Shell_TrayWnd。我们正在使用它的句柄来加速搜索。
using System.Drawing;
using System.Runtime.InteropServices;
//Shell Tray rectangle
IntPtr hWnd = FindWindowByClassName(IntPtr.Zero, "Shell_TrayWnd");
Rectangle shellTrayArea = GetWindowRectangle(hWnd);
//Notification area rectangle
hWnd = FindWindowByClassName(hWnd, "TrayNotifyWnd");
Rectangle trayNotifyArea = GetWindowRectangle(hWnd);
Run Code Online (Sandbox Code Playgroud)
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 className)
{
return SafeNativeMethods.FindWindowEx(hwndParent, IntPtr.Zero, className, null);
}
[SecuritySafeCritical]
public static Rectangle GetWindowRectangle(IntPtr windowHandle)
{
RECT rect;
new UIPermission(UIPermissionWindow.AllWindows).Demand();
SafeNativeMethods.GetWindowRect(windowHandle, out rect);
return rect.ToRectangle();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1268 次 |
| 最近记录: |