web-dev-qa-db-de.com

Wie zentriere ich mein Hauptfenster in WPF?

Ich habe eine WPF-Anwendung und muss wissen, wie man das wain-Fenster programmgesteuert zentriert (nicht in XAML).

Ich muss in der Lage sein, dies sowohl beim Start als auch als Reaktion auf bestimmte Benutzerereignisse zu tun. Es muss dynamisch berechnet werden, da die Fenstergröße selbst dynamisch ist.

Was ist der einfachste Weg, dies zu tun? Unter altem Win32-Code würde ich die Systemmetrikfunktionen aufrufen und alles ausarbeiten. Ist das noch so oder gibt es eine einfache CenterWindowOnScreen() Funktion, die ich jetzt aufrufen kann?.

51
paxdiablo
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);
}

Mit dieser Methode können Sie die Fensterposition auf die Bildschirmmitte einstellen.

74

Nun, für die Startzeit können Sie den Startort einstellen:

window.WindowStartupLocation = WindowStartupLocation.CenterScreen;

Später müssen Sie es abfragen. Die Informationen (zumindest für den Primärbildschirm) sind über SystemParameters.PrimaryScreenWidth /Height verfügbar.

95
Reed Copsey

Ist es nicht genauso einfach einzustellen?

WindowStartupLocation="CenterScreen"

In der XAML-Definition für das Fenster.

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

Dies berücksichtigt die Größe der Taskleiste (mit System.Windows.SystemParameters.WorkArea) und Position (durch Hinzufügen von workArea.Left und workArea.Top)

22
Wild_A

Ich musste einige dieser Antworten kombinieren, um alle Grundlagen in meinem Fall abzudecken:

  • Peters Methode um den aktuellen Monitor zu finden - und nicht nur den primären Monitor (im Ernst, wer hat nur noch 1 Monitor am Werk?)
  • @ Wild_A's Methode um den workarea anstelle des screen bounds, um den Platz für die Taskleiste zu berücksichtigen.
  • Ich musste die DPI-Skalierung speziell für ein Tablet hinzufügen, das 1280x800 als 1024x640 anzeigt, aber dies ist nützlich, um Edge-Fälle abzudecken, für die ich eine Antwort für hier gefunden habe. Beachten Sie, dass die Variable dpiScaling null ist, wenn sie beim ersten Laden aufgerufen wird, bevor die Benutzeroberfläche angezeigt wird ( hier erklärt )
//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));

dabei sind myWindowWidth und myWindowHeight Variablen, mit denen ich die Größe des Fensters zuvor manuell festgelegt habe.

15
JumpingJezza

Falls Sie ein Fenster in einer Umgebung mit mehreren Bildschirmen zeichnen müssen. Ich habe eine statische Klasse erstellt, in der die folgende Methode wiederverwendet werden kann:

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;        
}

Rufen Sie im Konstruktor des Fensters einfach die Methode auf:

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

Fügen Sie im Fensterelement einfach dieses Attribut-Wert-Paar hinzu: WindowStartupLocation = "CenterScreen"

5
Husam Hilal

Als grundlegende Lösung können Sie die StartupLocation-Eigenschaft des Fensters verwenden und sie auf einen der in System.Windows.WindowStartupLocation definierten Aufzählungswerte festlegen. Für die Mitte des Bildschirms gibt es einen:

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

Leider ist es nicht immer so einfach; Sie müssen mehrere Monitore, Taskleisten usw. berücksichtigen. Die Option "CenterScreen" öffnet das Fenster in der Mitte des Bildschirms, in dem sich der Mauszeiger befindet. Weitere Informationen finden Sie unter this SO question oder unter api .

4
Guy Starbuck

Was ich in meiner App verwende, funktioniert für mehrere Displays und für unterschiedliche DPI-Einstellungen

    //center a window on chosen screen
    public static void CenterWindow(Window w, System.Windows.Forms.Screen screen = null)
    {
        if(screen == null)
            screen = System.Windows.Forms.Screen.PrimaryScreen;

        int screenW = screen.Bounds.Width;
        int screenH = screen.Bounds.Height;
        int screenTop = screen.Bounds.Top;
        int screenLeft = screen.Bounds.Left;

        w.Left = PixelsToPoints((int)(screenLeft + (screenW - PointsToPixels(w.Width, "X")) / 2), "X");
        w.Top = PixelsToPoints((int)(screenTop + (screenH - PointsToPixels(w.Height, "Y")) / 2), "Y");
    }

    public static double PixelsToPoints(int pixels, string direction)
    {
        if (direction == "X")
        {
            return pixels * SystemParameters.WorkArea.Width / System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width;
        }
        else
        {
            return pixels * SystemParameters.WorkArea.Height / System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
        }
    }

    public static double PointsToPixels(double wpfPoints, string direction)
    {
        if (direction == "X")
        {
            return wpfPoints * System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width / SystemParameters.WorkArea.Width;
        }
        else
        {
            return wpfPoints * System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height / SystemParameters.WorkArea.Height;
        }
    }
1
vinsa

Wenn Sie es auf einmal maximiert werden
this.WindowState = System.Windows.WindowState.Maximized;

0
EpiGen

Basierend auf der Antwort von @Wild_A habe ich gerade das Ereignis SizeChanged abonniert und diesen Ereignishandler hinzugefügt:

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; }
}
0
Viking