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?.
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.
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.
Ist es nicht genauso einfach einzustellen?
WindowStartupLocation="CenterScreen"
In der XAML-Definition für das Fenster.
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
)
Ich musste einige dieser Antworten kombinieren, um alle Grundlagen in meinem Fall abzudecken:
workarea
anstelle des screen bounds
, um den Platz für die Taskleiste zu berücksichtigen.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.
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)
Fügen Sie im Fensterelement einfach dieses Attribut-Wert-Paar hinzu: WindowStartupLocation = "CenterScreen"
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 .
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;
}
}
Wenn Sie es auf einmal maximiert werden
this.WindowState = System.Windows.WindowState.Maximized;
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; }
}