Как центрировать главное окно в WPF?

У меня есть приложение WPF, и мне нужно знать, как программно центрировать окно wain (не в XAML).

Мне нужно иметь возможность делать это как при запуске, так и в ответ на определенные события пользователя. Он должен быть динамически рассчитан, так как сам размер окна является динамическим.

какой самый простой способ сделать это? В старом коде Win32 я бы вызвал функции системных метрик и все это разработал. Это все еще так, как это делается, или есть простой CenterWindowOnScreen() функция, которую я теперь могу вызвать.

10 ответов


private void CenterWindowOnScreen()
{
    double screenWidth = System.Windows.SystemParameters.PrimaryScreenWidth;
    double screenHeight = System.Windows.SystemParameters.PrimaryScreenHeight;
    double windowWidth = this.Width;
    double windowHeight = this.Height;
    this.Left = (screenWidth / 2) - (windowWidth / 2);
    this.Top = (screenHeight / 2) - (windowHeight / 2);
}

этот метод можно использовать для установки положения окна в центре экрана.


Ну, для времени запуска вы можете установить автозагрузки:

window.WindowStartupLocation = WindowStartupLocation.CenterScreen;

позже вам нужно будет запросить его. Информация (по крайней мере для основного экрана) доступна через SystemParameters.PrimaryScreenWidth/Высота.


разве не так же просто установить

WindowStartupLocation="CenterScreen"

в определении XAML для окна.


Rect workArea = System.Windows.SystemParameters.WorkArea;
this.Left = (workArea.Width - this.Width) / 2 + workArea.Left;
this.Top = (workArea.Height - this.Height) / 2 + workArea.Top;

это учитывает размер панели задач (с помощью System.Windows.SystemParameters.WorkArea) и положение (путем добавления workArea.Left и workArea.Top)


мне пришлось объединить несколько из этих ответов, чтобы покрыть все основания в моем случае:

  • Петровская чтобы найти текущий монитор-а не только основной монитор (серьезно, кто имеет только 1 монитор на работе больше?)
  • @Wild_A это!--11--> использовать workarea, а не screen bounds чтобы учесть пространство для панели задач.
  • мне пришлось добавить масштабирование DPI, специально для планшета, отображающего 1280x800 как 1024x640, но который полезен для покрытия краевых случаев, для которых я нашел ответ для здесь. Примечание dpiScaling переменная имеет значение null, если вызывается при первой загрузке перед отображением пользовательского интерфейса (пояснил, что)
//get the current monitor
Screen currentMonitor = Screen.FromHandle(new System.Windows.Interop.WindowInteropHelper(Application.Current.MainWindow).Handle);

//find out if our app is being scaled by the monitor
PresentationSource source = PresentationSource.FromVisual(Application.Current.MainWindow);
double dpiScaling = (source != null && source.CompositionTarget != null ? source.CompositionTarget.TransformFromDevice.M11 : 1);

//get the available area of the monitor
Rectangle workArea = currentMonitor.WorkingArea;
var workAreaWidth = (int)Math.Floor(workArea.Width*dpiScaling);
var workAreaHeight = (int)Math.Floor(workArea.Height*dpiScaling);

//move to the centre
Application.Current.MainWindow.Left = (((workAreaWidth - (myWindowWidth * dpiScaling)) / 2) + (workArea.Left * dpiScaling));
Application.Current.MainWindow.Top = (((workAreaHeight - (myWindowHeight * dpiScaling)) / 2) + (workArea.Top * dpiScaling));

здесь myWindowWidth и myWindowHeight являются переменными, которые я использовал для ручной установки размера окна ранее.


в элементе window просто добавьте эту пару атрибут-значение: WindowStartupLocation="CenterScreen"


в случае, если вам нужно нарисовать окно в среде с несколькими экранами. Я создал статический класс, в котором можно повторно использовать следующий метод:

public static void PostitionWindowOnScreen(Window window, double horizontalShift = 0, double verticalShift = 0)
{
    Screen screen = Screen.FromHandle(new System.Windows.Interop.WindowInteropHelper(window).Handle);
    window.Left = screen.Bounds.X + ((screen.Bounds.Width - window.ActualWidth) / 2) + horizontalShift;
    window.Top = screen.Bounds.Y + ((screen.Bounds.Height - window.ActualHeight) / 2) + verticalShift;        
}

в конструкторе окна теперь просто вызываем метод:

this.Loaded += (s, a) => Globals.PostitionWindowOnScreen(this, 0, 0)

в качестве базового решения можно использовать свойство StartupLocation окна, присвоив ему одно из значений перечисления, определенных в System.Окна.Перечисление WindowStartupLocation, есть один для центра экрана:

_wpfWindow.StartupLocation = System.Windows.WindowStartupLocation.CenterScreen;

к сожалению, это не всегда так просто; вам нужно учитывать несколько мониторов,панелей задач и т. д. Опция "CenterScreen" открывает окно в центре экрана с курсором мыши. См.это так вопрос для многих информация или ссылка на api.


Если вы его развернуть сразу
этот.Windowstate Значение = Система.Окна.Windowstate значение.Максимизировано;


на основе ответа @Wild_A я только что подписался на SizeChanged событие и добавлен этот обработчик событий:

private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
    try
    {
        Rect workArea = SystemParameters.WorkArea;
        this.Left = (workArea.Width - e.NewSize.Width) / 2 + workArea.Left;
        this.Top = (workArea.Height - e.NewSize.Height) / 2 + workArea.Top;
    }
    catch (Exception ex) { ... Handel exception; }
}