web-dev-qa-db-fra.com

Comment centrez-vous votre fenêtre principale dans WPF?

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.

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

Vous pouvez utiliser cette méthode pour définir la position de la fenêtre au centre de votre écran.

74

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.

95
Reed Copsey

N'est-ce pas aussi simple à régler

WindowStartupLocation="CenterScreen"

Dans la définition XAML de la fenêtre.

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;

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)

22
Wild_A

J'ai dû combiner quelques-unes de ces réponses pour couvrir toutes les bases de mon cas:

  • méthode de Peter pour trouver le moniteur actuel - plutôt que juste le moniteur principal (sérieusement qui n'a plus qu'un seul moniteur au travail?)
  • @ méthode Wild_A pour utiliser le workarea plutôt que le screen bounds pour prendre en compte l'espace pour la barre des tâches.
  • J'ai dû ajouter une mise à l'échelle DPI, spécifiquement pour une tablette affichant 1280x800 en 1024x640, mais qui est utile pour couvrir les cas Edge, pour lesquels j'ai trouvé une réponse pour ici . Notez que la variable 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));

myWindowWidth et myWindowHeight sont des variables que j'ai utilisées pour définir manuellement la taille de la fenêtre plus tôt.

15
JumpingJezza

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)
7
Peter

Dans l'élément window, ajoutez simplement cette paire attribut-valeur: WindowStartupLocation = "CenterScreen"

5
Husam Hilal

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 .

4
Guy Starbuck

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

Si vous voulez être maximisé à la fois
this.WindowState = System.Windows.WindowState.Maximized;

0
EpiGen

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