Окно ActualTop, ActualLeft - PullRequest
       5

Окно ActualTop, ActualLeft

5 голосов
/ 30 августа 2010

Как правильно получить положение окна в 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, но не имеет публичного свойства для их раскрытия.

Как вы получаете правильное значение?

Ответы [ 3 ]

13 голосов
/ 09 ноября 2011

Вы можете использовать рефлексию, если не хотите полагаться на 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;
    }
3 голосов
/ 11 августа 2014

Вот решение, которое основано на P / Invoke GetWindowRect, но использует методы расширения, чтобы ваш код выглядел лучше. Вы используете 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;
    }
}
3 голосов
/ 30 августа 2010

Да, неловко. У вас есть большие проблемы, (0, 0) не будет действительным даже на основном мониторе, если пользователь поместит панель задач слева или сверху. Как я и сделал. Вы можете получить помощь в классе Windows Forms Screen. Используйте его метод FromPoint (), затем свойство WorkingArea. Или свойство Bounds, если вы разрешаете окну переходить в полноэкранный режим.

Лично я бы просто P / Invoke GetWindowRect ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...