4

我使用Microsoft.Windows.ShellDLL 和 .NET 4.0 在 WPF 中创建了一个自定义窗口。

问题是如果任务栏设置为自动隐藏并且窗口最大化,窗口会完全覆盖任务栏。我尝试了几种不同的解决方案(前几个谷歌结果),但没有一个真正起作用。

如果任务栏没有自动隐藏,包使用的方法MahApps.Metro会将窗口设置为距离屏幕底部 1px 。

我需要一个解决方案

  1. 适用于 .NET 4.0
  2. 无论任务栏停靠在哪一侧都有效
  3. 当任务栏设置为始终显示和自动隐藏时工作。
4

1 回答 1

3

自定义 WPF 窗口不考虑任务栏占用的区域。为此,您需要 Win32 API 的支持。

您需要的第一种方法是...

    [DllImport("user32.dll")]
    public static extern IntPtr MonitorFromWindow(IntPtr hwnd, int dwFlags);

MonitorFromWindow 函数检索与指定窗口的边界矩形相交的区域最大的显示监视器的句柄。 http://msdn.microsoft.com/en-us/library/windows/desktop/dd145064(v=vs.85).aspx

设置 dwFlags = 2

下一个是...

    [DllImport("user32.dll")]
    public static extern bool GetMonitorInfo(HandleRef hmonitor, 
                       [In, Out] MonitorInfoEx monitorInfo);

GetMonitorInfo 函数检索有关显示监视器的信息。 http://msdn.microsoft.com/en-us/library/windows/desktop/dd144901(v=vs.85).aspx

MonitorInfoEx 结构看起来像......

    [StructLayout(LayoutKind.Sequential)]
    public class MonitorInfoEx
    {
        public int cbSize;
        public Rect rcMonitor;     
        public Rect rcWork;        
        public int dwFlags;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
        public char[] szDevice;
    }

MONITORINFOEX 结构包含有关显示监视器的信息。 http://msdn.microsoft.com/en-us/library/windows/desktop/dd145066(v=vs.85).aspx

正在传递的 Rect 是...

    [StructLayout(LayoutKind.Sequential)]
    public struct Rect
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

这里特别有趣的是,您正在以当前分辨率获得 DPI 中的工作区域。

最后,您需要 PresentationCore (WPF) 的互操作命名空间中的 HwndSource.FromHwnd 方法

将所有信息放在一起后,您可以使用 CompositionTarget.TransformFromDevice 来... 获取一个矩阵,该矩阵可用于将坐标从渲染目标设备转换到此目标。 http://msdn.microsoft.com/en-us/library/system.windows.media.compositiontarget.transformfromdevice.aspx

...这将为您提供定位自定义窗口所需的尺寸,使其尊重状态栏。

于 2013-08-10T20:44:03.297 回答