What is the correct way to retrieve a window's position in WPF?
Here's some attempts I made. First attempt, the obvious
Point GetPosition(Window win)
{
return new Point(win.Top, win.Left);
}
but this returns the "wrong" position when the window is maximized. Second attempt:
Point GetPosition(Window win)
{
if (win.WindowState == WindowState.Maximized)
return new Point(0, 0);
else
return new Point(win.Top, win.Left);
}
Almost there, but there is still an issue: when you have two (or more) screens and the window is maximized in the second screen you get a (0, 0) position that does not reflect the window's actual position.
I noticed that Window has _actualTop and _actualLeft private members, but no public property to expose them.
How do you retrieve the correct value?
You can use reflection if you don't want to rely on Winforms or PI
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;
}
Here's a solution that builds on P/Invoke of GetWindowRect, but uses extension methods to make your code look nicer. You use myWindow.ActualTop() and myWindow.ActualLeft() in your code.
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With