J'ai une application WPF et j'ai besoin de savoir comment centrer la fenêtre Wain par programmation (pas en XAML).
Je dois pouvoir le faire à la fois au démarrage et en réponse à certains événements utilisateur. Il doit être calculé dynamiquement car la taille de la fenêtre elle-même est dynamique.
Quelle est la manière la plus simple de procéder? Sous l'ancien code Win32, j'appellerais les fonctions de métriques du système et je réglerais tout cela. Est-ce toujours la façon dont cela se fait ou existe-t-il une simple fonction CenterWindowOnScreen()
que je peux maintenant appeler.
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);
}
Vous pouvez utiliser cette méthode pour définir la position de la fenêtre au centre de votre écran.
Eh bien, pour le temps de démarrage, vous pouvez définir emplacement de démarrage :
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
Plus tard, vous devrez l'interroger. Les informations (au moins pour l'écran principal) sont disponibles via SystemParameters.PrimaryScreenWidth /Height.
N'est-ce pas aussi simple à régler
WindowStartupLocation="CenterScreen"
Dans la définition XAML de la fenêtre.
Rect workArea = System.Windows.SystemParameters.WorkArea;
this.Left = (workArea.Width - this.Width) / 2 + workArea.Left;
this.Top = (workArea.Height - this.Height) / 2 + workArea.Top;
Cela prend en compte la taille de la barre des tâches (en utilisant System.Windows.SystemParameters.WorkArea
) et position (en ajoutant workArea.Left
et workArea.Top
)
J'ai dû combiner quelques-unes de ces réponses pour couvrir toutes les bases de mon cas:
workarea
plutôt que le screen bounds
pour prendre en compte l'espace pour la barre des tâches.dpiScaling
est nulle si elle est appelée lors du premier chargement avant l'affichage de l'interface utilisateur ( expliqué ici )//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));
où myWindowWidth
et myWindowHeight
sont des variables que j'ai utilisées pour définir manuellement la taille de la fenêtre plus tôt.
Dans le cas où vous devez dessiner une fenêtre dans un environnement à plusieurs écrans. J'ai créé une classe statique où la méthode suivante peut être réutilisée:
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;
}
Dans le constructeur de la fenêtre, appelez maintenant la méthode:
this.Loaded += (s, a) => Globals.PostitionWindowOnScreen(this, 0, 0)
Dans l'élément window, ajoutez simplement cette paire attribut-valeur: WindowStartupLocation = "CenterScreen"
En tant que solution de base, vous pouvez utiliser la propriété StartupLocation de la fenêtre, la définir sur l'une des valeurs d'énumération définies dans l'énumération System.Windows.WindowStartupLocation, il y en a une pour le centre de l'écran:
_wpfWindow.StartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
Malheureusement, ce n'est pas toujours aussi simple; vous devez tenir compte de plusieurs moniteurs, barres de tâches, etc. L'option "CenterScreen" ouvre la fenêtre au centre de l'écran qui a le curseur de la souris. Voir this SO question pour beaucoup d'informations, ou référencez le api .
Ce que j'utilise dans mon application, cela fonctionne pour plusieurs écrans et pour différents paramètres DPI
//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;
}
}
Si vous voulez être maximisé à la fois
this.WindowState = System.Windows.WindowState.Maximized;
Sur la base de la réponse @Wild_A, je viens de m'abonner à l'événement SizeChanged
et j'ai ajouté ce gestionnaire d'événements:
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; }
}