防止最大化的WPF窗口覆盖任务栏

4
我使用Microsoft.Windows.Shell DLL和.NET 4.0在WPF中创建了一个自定义窗口。
问题是,如果任务栏设置为自动隐藏并且窗口最大化,则窗口完全覆盖任务栏。我已经尝试过几种不同的解决方案(前几个谷歌结果),但没有一个实际上起作用。
MahApps.Metro软件包使用的方法会将窗口设为屏幕底部1像素(如果任务栏没有自动隐藏)。
我需要一个解决方案:
1.适用于.NET 4.0
2.无论任务栏停靠在哪一侧都能工作
3.当任务栏设置为始终显示和自动隐藏时都能工作。

你如何最大化窗口?我一直以为“最大化”状态会考虑工具栏(及其行为)的影响。 - ChrisF
1
在WPF中,使用自定义窗口时,当WindowState被设为WindowState.Maximized时,渲染系统会完全忽略自动隐藏的任务栏。 - Ming Slogar
我以前也遇到过这个问题。如果要让自定义窗口尊重任务栏,您需要使用Win32 API来定位任务栏。 - Gayot Fow
1
我可以识别出感兴趣的API函数和与之配合使用的框架Interop方法;但是我不想为您编写调整大小的方法,因为我目前没有办法在多个监视器上进行测试。仅命名一些API声明是否可以作为对这个问题的“答案”? - Gayot Fow
@GarryVass:当然!我已经尝试使用一些P/Invoke方法,但无法找到可行的解决方案。目前我不担心多监视器支持,虽然我将在不久的将来需要添加它。 - Ming Slogar
显示剩余2条评论
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/zh-cn/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/zh-cn/library/windows/desktop/dd145066(v=vs.85).aspx
    [StructLayout(LayoutKind.Sequential)]
    public struct Rect
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

这里特别值得注意的是,您正在以当前分辨率的 DPI 获取工作区。

最后,您需要从 PresentationCore(WPF)Interop 命名空间使用 HwndSource.FromHwnd 方法。

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

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


我该如何在最大化窗口的情况下使用它?我需要覆盖最大化调用以保持窗口处于正常状态吗? - Ming Slogar
是的,就像那样。跟踪窗口状态并在其改变时进行干预。现在你拥有所有需要的东西了。 - Gayot Fow
好的,我已经尝试过这样做,并遇到了以下问题:http://stackoverflow.com/questions/18047362/window-caption-render-issues。我想我正在寻找的是类似于Visual Studio和Office可以在窗口真正最大化时工作的东西。 - Ming Slogar
我会查看那个问题,看看我能否贡献一些有用的东西。 - Gayot Fow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接