在WPF中检索窗口位置的正确方法是什么?
这是我做的一些尝试.第一次尝试,显而易见
Point GetPosition(Window win)
{
return new Point(win.Top, win.Left);
}
Run Code Online (Sandbox Code Playgroud)
但是当窗口最大化时,这会返回"错误"的位置.第二次尝试:
Point GetPosition(Window win)
{
if (win.WindowState == WindowState.Maximized)
return new Point(0, 0);
else
return new Point(win.Top, win.Left);
}
Run Code Online (Sandbox Code Playgroud)
几乎在那里,但仍然存在一个问题:当你有两个(或更多)屏幕并且窗口在第二个屏幕中最大化时,你会得到一个(0,0)位置,它不会反映窗口的实际位置.
我注意到Window有_actualTop和_actualLeft私有成员,但没有公共属性来公开它们.
你如何检索正确的值?
小智 14
如果您不想依赖Winforms或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;
}
Run Code Online (Sandbox Code Playgroud)
小智 5
这是一个基于 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;
}
}
Run Code Online (Sandbox Code Playgroud)
是的,尴尬。您遇到了更大的问题,如果用户将任务栏放在左侧或顶部,即使在主显示器上,(0, 0) 也无效。就像我一样。您可以从 Windows 窗体屏幕类获得帮助。使用其FromPoint() 方法,然后使用WorkingArea 属性。或者 Bounds 属性(如果您允许窗口全屏显示)。
就我个人而言,我只是 P/Invoke GetWindowRect()。