Window ActualTop,ActualLeft

在WPF中检索窗口位置的正确方法是什么?

这是我做的一些尝试。 第一次尝试,显而易见

Point GetPosition(Window win) { return new Point(win.Top, win.Left); } 

但是当窗口最大化时,这会返回“错误”的位置。 第二次尝试:

 Point GetPosition(Window win) { if (win.WindowState == WindowState.Maximized) return new Point(0, 0); else return new Point(win.Top, win.Left); } 

几乎在那里,但仍然存在一个问题:当你有两个(或更多)屏幕并且窗口在第二个屏幕中最大化时,你得到的(0,0)位置不能反映窗口的实际位置。

我注意到Window有_actualTop和_actualLeft私有成员,但没有公开属性来公开它们。

你如何检索正确的值?

是的,尴尬。 你有更大的问题,如果用户将任务栏放在左侧或顶部,即使在主监视器上,(0,0)也无效。 像我一样。 您可以从Windows窗体屏幕类获得帮助。 使用其FromPoint()方法,然后使用WorkingArea属性。 如果允许窗口全屏显示,则为Bounds属性。

就个人而言,我只是P / Invoke GetWindowRect()。

如果您不想依赖Winforms或PI,则可以使用reflection

 private double GetWindowLeft(Window window) { if (window.WindowState == WindowState.Maximized) { var leftField = typeof(Window).GetField("_actualLeft", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); return (double)leftField.GetValue(window); } else return window.Left; } 

这是一个基于GetWindowRect的P / Invoke的解决方案,但使用扩展方法使您的代码看起来更好。 您在代码中使用myWindow.ActualTop()和myWindow.ActualLeft()。

 static class WindowExtensions { [StructLayout(LayoutKind.Sequential)] struct RECT { public int Left; public int Top; public int Right; public int Bottom; } [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); public static double ActualTop(this Window window) { switch (window.WindowState) { case WindowState.Normal: return window.Top; case WindowState.Minimized: return window.RestoreBounds.Top; case WindowState.Maximized: { RECT rect; GetWindowRect((new WindowInteropHelper(window)).Handle, out rect); return rect.Top; } } return 0; } public static double ActualLeft(this Window window) { switch (window.WindowState) { case WindowState.Normal: return window.Left; case WindowState.Minimized: return window.RestoreBounds.Left; case WindowState.Maximized: { RECT rect; GetWindowRect((new WindowInteropHelper(window)).Handle, out rect); return rect.Left; } } return 0; } }