Window ActualTop,ActualLeft

Fra*_*ori 5 .net c# wpf

在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)


Han*_*ant 3

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

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