如何找到最大化窗口的位置?

时间:2011-01-26 15:08:17

标签: wpf window

我需要知道最大化窗口的位置。

WPF窗口具有Top和Left属性,用于指定窗口的位置。但是,如果最大化窗口,这些属性会使窗口的值保持正常状态。

如果您在单屏设置上运行,则最大化位置自然是(0,0)。但是,如果您有多个屏幕不一定是真的。如果在主屏幕上将窗口最大化,窗口将只有位置(0,0)。

那么......有没有办法找出最大化窗口的位置(最好是与Top和Left属性相同的逻辑单位)?

7 个答案:

答案 0 :(得分:9)

这是我在此基础上提出的解决方案(谢谢!)。

此解决方案......

  • 返回当前状态窗口的位置
  • 处理所有窗口状态(最大化,最小化,恢复)
  • 不依赖于Windows Forms(但受其启发)
  • 使用窗口句柄可靠地确定正确的监视器

主要方法GetAbsolutePosition在此处作为扩展方法实现。如果您有一个名为Window的{​​{1}},请按以下方式调用:

myWindow

这是完整的代码:

Point p = myWindow.GetAbsolutePosition();

答案 1 :(得分:7)

我终于找到了一个适合我的解决方案:

private System.Drawing.Rectangle getWindowRectangle()
{
    System.Drawing.Rectangle windowRectangle;

    if (this.WindowState == System.Windows.WindowState.Maximized)
    {
        /* Here is the magic:
         * Use Winforms code to find the Available space on the
         * screen that contained the window 
         * just before it was maximized
         * (Left, Top have their values from Normal WindowState)
         */
        windowRectangle = System.Windows.Forms.Screen.GetWorkingArea(
            new System.Drawing.Point((int)this.Left, (int)this.Top));
    }
    else
    {
        windowRectangle = new System.Drawing.Rectangle(
            (int)this.Left, (int)this.Top,
            (int)this.ActualWidth, (int)this.ActualHeight);
    }

    return windowRectangle;
}

答案 2 :(得分:5)

public static System.Drawing.Rectangle GetWindowRectangle(this Window w)
{
    if (w.WindowState == WindowState.Maximized) {
        var handle = new System.Windows.Interop.WindowInteropHelper(w).Handle;
        var screen = System.Windows.Forms.Screen.FromHandle(handle);
        return screen.WorkingArea;
    }
    else {
        return new System.Drawing.Rectangle(
            (int)w.Left, (int)w.Top, 
            (int)w.ActualWidth, (int)w.ActualHeight);
    }
}

答案 3 :(得分:5)

适用于所有显示器和所有高DPI变体的通用一行答案:

Point leftTop = this.PointToScreen(new Point(0, 0));

例如,返回(-8,-8)窗口,该窗口在1920 {{}}返回1936的宽屏幕上最大化。

对其他答案的咆哮:永远不要将逻辑96 dpi WPF像素(使用ActualWidth)与本机真实像素混合(使用double) - 特别是只需将double转换为int!

答案 4 :(得分:0)

我意识到您正在使用WPF,这个答案使用了Forms技术,但它应该没有太大困难。

您可以通过My.Settings.Screens.AllScreens获取一系列屏幕。从那里,您可以访问屏幕当前正在处理的分辨率。

由于WPF窗口保留了它们最大化时的顶部/左侧值,因此您可以通过确定顶部/左侧坐标所指的屏幕,然后获取顶部/左侧坐标来确定它们所在的屏幕对于那个屏幕。

不幸的是,我在路上,此刻无法测试。如果你确实实施了,我很乐意看到你提出的建议。

答案 5 :(得分:0)

这似乎是System.Windows.Window的问题!!!

最大化的窗口给出的Left,Width,ActualWidth,Top,Height和ActualHeight值不可靠。

最大化窗口后,通常可以保留预先最大化窗口的Left和Width值。

对于其他阅读者-窗口未最大化时没有问题。

此外,我觉得奇怪的是,您读取的值在WPF DPI坐标中,即1936x1096,从(-8,-8)到(1928,1088)],但是设置这些值时,您必须使用屏幕像素坐标[即1920x1080,使用(0,0)等...]

@tgr在上面提供了可靠的部分解决方案,下面我对其进行了改进:

  • 通过将帮助程序类移到子类来解决扩展方法的智能感知
  • 创建GetAbsoluteRect()方法以提供Width / Height并一次调用即可全部指向
  • 重构通用代码

这是C#解决方案:

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;

public static partial class Extensions
{
    static class OSInterop
    {
        [DllImport("user32.dll")]
        public static extern int GetSystemMetrics(int smIndex);
        public const int SM_CMONITORS = 80;

        [DllImport("user32.dll")]
        public static extern bool SystemParametersInfo(int nAction, int nParam, ref RECT rc, int nUpdate);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool GetMonitorInfo(HandleRef hmonitor, [In, Out] MONITORINFOEX info);

        [DllImport("user32.dll")]
        public static extern IntPtr MonitorFromWindow(HandleRef handle, int flags);

        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
            public int width { get { return right - left; } }
            public int height { get { return bottom - top; } }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Auto)]
        public class MONITORINFOEX
        {
            public int cbSize = Marshal.SizeOf(typeof(MONITORINFOEX));
            public RECT rcMonitor = new RECT();
            public RECT rcWork = new RECT();
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
            public char[] szDevice = new char[32];
            public int dwFlags;
        }
    }

    static Int32Rect _getOsInteropRect(Window w)
    {
        bool multimonSupported = OSInterop.GetSystemMetrics(OSInterop.SM_CMONITORS) != 0;
        if (!multimonSupported)
        {
            OSInterop.RECT rc = new OSInterop.RECT();
            OSInterop.SystemParametersInfo(48, 0, ref rc, 0);
            return new Int32Rect(rc.left, rc.top, rc.width, rc.height);
        }

        WindowInteropHelper helper = new WindowInteropHelper(w);
        IntPtr hmonitor = OSInterop.MonitorFromWindow(new HandleRef((object)null, helper.EnsureHandle()), 2);
        OSInterop.MONITORINFOEX info = new OSInterop.MONITORINFOEX();
        OSInterop.GetMonitorInfo(new HandleRef((object)null, hmonitor), info);
        return new Int32Rect(info.rcWork.left, info.rcWork.top, info.rcWork.width, info.rcWork.height);
    }

    public static Rect GetAbsoluteRect(this Window w)
    {
        if (w.WindowState != WindowState.Maximized)
            return new Rect(w.Left, w.Top, w.ActualWidth, w.ActualHeight);

        var r = _getOsInteropRect(w);
        return new Rect(r.X, r.Y, r.Width, r.Height);
    }

    public static Point GetAbsolutePosition(this Window w)
    {
        if (w.WindowState != WindowState.Maximized)
            return new Point(w.Left, w.Top);

        var r = _getOsInteropRect(w);
        return new Point(r.X, r.Y);
    }
}

答案 6 :(得分:0)

我还没有找到解决您问题的方法,但是如果您只需要放置一个窗口来创建一个新窗口,则可以执行以下操作:

...
Window windowNew = new Window();
ConfigureWindow(this, windowNew);
Window.Show();
...

static public void ConfigureWindow(Window windowOld, Window windowNew)
    {
        windowNew.Height = windowOld.ActualHeight;
        windowNew.Width = windowOld.ActualWidth;

        if (windowOld.WindowState == WindowState.Maximized)
        {
            windowNew.WindowState = WindowState.Maximized;
        }
        else
        {
            windowNew.Top = windowOld.Top;
            windowNew.Left = windowOld.Left;
        }
    }