Comment obtenir la taille de l'écran actuel dans WPF?


87

Je sais que je peux obtenir la taille de l'écran principal en utilisant

System.Windows.SystemParameters.PrimaryScreenWidth;
System.Windows.SystemParameters.PrimaryScreenHeight;

Mais comment obtenir la taille de l'écran actuel? (Les utilisateurs multi-écrans n'utilisent pas toujours l'écran principal et tous les écrans n'utilisent pas la même résolution, non?)

Ce serait bien de pouvoir accéder à la taille à partir de XAML, mais le faire à partir du code (C #) suffirait.


1
Définissez "courant". Une fenêtre peut être sur plusieurs écrans à la fois.
Jim Balter

Réponses:


13

Pour autant que je sache, il n'y a pas de fonction WPF native pour obtenir les dimensions du moniteur actuel. Au lieu de cela, vous pouvez PInvoke des fonctions natives de plusieurs moniteurs d'affichage, les encapsuler dans une classe gérée et exposer toutes les propriétés dont vous avez besoin pour les consommer à partir de XAML.


C'est exactement ce que je craignais - le besoin de P / Invoke ou d'accéder à System.Windows.Forms.Screen d'une manière ou d'une autre. Et ce faisant, j'ai toujours besoin de calculer les "pixels indépendants de l'appareil" ... Merci, cependant.
Nils

Oui ... Peut-être que la fonction SystemParameters.ConvertPixel () vous aidera également. C'est interne, mais Reflector s'en fiche
:)

74

J'ai créé un petit wrapper autour de l'écran à partir de System.Windows.Forms, actuellement tout fonctionne ... Je ne suis pas sûr des "pixels indépendants du périphérique", cependant.

public class WpfScreen
{
    public static IEnumerable<WpfScreen> AllScreens()
    {
        foreach (Screen screen in System.Windows.Forms.Screen.AllScreens)
        {
            yield return new WpfScreen(screen);
        }
    }

    public static WpfScreen GetScreenFrom(Window window)
    {
        WindowInteropHelper windowInteropHelper = new WindowInteropHelper(window);
        Screen screen = System.Windows.Forms.Screen.FromHandle(windowInteropHelper.Handle);
        WpfScreen wpfScreen = new WpfScreen(screen);
        return wpfScreen;
    }

    public static WpfScreen GetScreenFrom(Point point)
    {
        int x = (int) Math.Round(point.X);
        int y = (int) Math.Round(point.Y);

        // are x,y device-independent-pixels ??
        System.Drawing.Point drawingPoint = new System.Drawing.Point(x, y);
        Screen screen = System.Windows.Forms.Screen.FromPoint(drawingPoint);
        WpfScreen wpfScreen = new WpfScreen(screen);

        return wpfScreen;
    }

    public static WpfScreen Primary
    {
        get { return new WpfScreen(System.Windows.Forms.Screen.PrimaryScreen); }
    }

    private readonly Screen screen;

    internal WpfScreen(System.Windows.Forms.Screen screen)
    {
        this.screen = screen;
    }

    public Rect DeviceBounds
    {
        get { return this.GetRect(this.screen.Bounds); }
    }

    public Rect WorkingArea
    {
        get { return this.GetRect(this.screen.WorkingArea); }
    }

    private Rect GetRect(Rectangle value)
    {
        // should x, y, width, height be device-independent-pixels ??
        return new Rect
                   {
                       X = value.X,
                       Y = value.Y,
                       Width = value.Width,
                       Height = value.Height
                   };
    }

    public bool IsPrimary
    {
        get { return this.screen.Primary; }
    }

    public string DeviceName
    {
        get { return this.screen.DeviceName; }
    }
}

Merci pour ce super petit wrapper, notez que global :: Rect avait besoin d'être converti en Rect simple lorsque je l'ai utilisé avec WPF 3.5.
Andy Dent

1
J'aime ça. Bien sûr, il faut un peu de travail, mais je ne m'attends pas à trouver des solutions à 100%.
jeff

4
Fonctionne très bien. Je viens d'étendre la méthode GetRect pour renvoyer le Rect en pixels indépendants de l'appareil: private Rect GetRect (valeur du rectangle) {var pixelWidthFactor = SystemParameters.WorkArea.Width / this.screen.WorkingArea.Width; var pixelHeightFactor = SystemParameters.WorkArea.Height / this.screen.WorkingArea.Height; return new Rect {X = value.X * pixelWidthFactor, Y = value.Y * pixelHeightFactor, Width = value.Width * pixelWidthFactor, Height = value.Height * pixelHeightFactor}; }
Jürgen Bayer

1
Je pense que l'ajout du code de @ JürgenBayer améliorera encore plus votre réponse. J'ai eu le problème avec les pixels indépendants de l'appareil et le code de Jürgen l'a résolu. Merci à vous deux.
Bruno V

3
@ Jürgen: Je pense que votre méthode ne fonctionne que dans des circonstances très spécifiques. Si "this.screen" a un rapport hauteur / largeur différent de celui du moniteur principal (que votre méthode utilise toujours comme référence au lieu du moniteur actuel), vous obtiendrez à tort des facteurs d'échelle différents pour la largeur et la hauteur, ce qui entraînera des dimensions d'écran incorrectes. Si l'écran actuel a un paramètre DPI différent de l'écran principal, les limites seront toutes fausses. Sur mon système, chaque valeur du Rect renvoyé est (complètement) incorrecte.
wilford

27

Ici mon pote. Cela ne vous donnera que la largeur et la hauteur de la zone de travail

System.Windows.SystemParameters.WorkArea.Width
System.Windows.SystemParameters.WorkArea.Height

13
"Obtient la taille de la zone de travail sur le moniteur d'affichage principal." - pas ce que je cherchais ....
Nils

10

Cela vous donnera l'écran actuel basé sur le coin supérieur gauche de la fenêtre, appelez simplement this.CurrentScreen () pour obtenir des informations sur l'écran actuel.

using System.Windows;
using System.Windows.Forms;

namespace Common.Helpers
{
    public static class WindowHelpers
     {
        public static Screen CurrentScreen(this Window window)
         {
             return Screen.FromPoint(new System.Drawing.Point((int)window.Left,(int)window.Top));
         }
     }
}

L'utilisateur recherche les dimensions de l'écran actuel, plutôt que l'écran principal.
greggannicott

3
cela renvoie l'écran actuel, basé sur la position en haut à gauche de la fenêtre à partir de laquelle vous appelez la fonction d'assistance. Mais je dois manquer quelque chose à cette question, en fonction du score de ma réponse.
EJ

Peut-être que greggannicott avait l'intention de poster son commentaire sur l'une des autres réponses, car il n'a aucun rapport avec celle-ci.
Jim Balter

@ jim-balter a voté - En fait, c'est la meilleure réponse ici, j'avais besoin de l'écran pour obtenir la zone de travail, puis m'assurer que mon dialogue ne dépasse pas la limite, je publierai ma solution ici. Félicitations à EJ pour sa réponse rapide et précise.
Juv

^ commentaire bizarre.
Jim Balter

5

Prenez le temps de parcourir les membres SystemParameters.

  • VirtualScreenWidth
  • VirtualScreenHeight

Celles-ci prennent même en compte les positions relatives des écrans.

Testé uniquement avec deux moniteurs.


9
dana - Je n'ai pas testé cela, mais VirtualScreen * ne renvoie-t-il pas la taille complète de tous les écrans? - J'ai spécifiquement besoin de la taille d'un écran (celui dans lequel réside la fenêtre actuelle).
Nils

1
VirtualScreen semble faire référence à la taille de tous les écrans
Thomas

1
Une mine a rendu la taille de tous les 4 écrans combinés.
DJ van Wyk

3

Pourquoi ne pas simplement l'utiliser?

var interopHelper = new WindowInteropHelper(System.Windows.Application.Current.MainWindow);
var activeScreen = Screen.FromHandle(interopHelper.Handle);

Screen est Windows.Forms plutôt que WPF - mais c'est un point de départ. Si vous regardez la solution que j'ai utilisée à l'époque ( stackoverflow.com/a/2118993/180156 ), c'est exactement ce que j'ai fait - mais j'ai enveloppé System.Windows.Forms.Screenpour faire face au pixel indépendant de l'appareil
Nils

3

Si vous êtes familiarisé avec l'utilisation de la classe System.Windows.Forms , vous pouvez simplement ajouter une référence de la classe System.Windows.Forms à votre projet:

Explorateur de solutions -> Références -> Ajouter des références ... -> (Assemblies: Framework) -> faites défiler vers le bas et vérifiez l' assembly System.Windows.Forms -> OK .

Vous pouvez maintenant ajouter en utilisant System.Windows.Forms; et utilisez screen dans votre projet wpf comme avant.


C'est de loin la solution la plus simple. Je me demande - à part l'ajout d'un assemblage assez volumineux, y a-t-il de bonnes raisons de ne pas le faire de cette façon?
AeonOfTime

3

J'avais également besoin de la dimension actuelle de l'écran, en particulier de la zone de travail, qui renvoyait le rectangle à l'exclusion de la largeur de la barre des tâches.

Je l'ai utilisé pour repositionner une fenêtre, qui est ouverte vers la droite et vers le bas là où la souris est positionnée. Comme la fenêtre est assez grande, dans de nombreux cas, elle est sortie des limites de l'écran. Le code suivant est basé sur @ej Réponse: Cela vous donnera l'écran en cours ... . La différence est que je montre également mon algorithme de repositionnement, qui, je suppose, est en fait le point.

Le code:

using System.Windows;
using System.Windows.Forms;

namespace MySample
{

    public class WindowPostion
    {
        /// <summary>
        /// This method adjust the window position to avoid from it going 
        /// out of screen bounds.
        /// </summary>
        /// <param name="topLeft">The requiered possition without its offset</param>
        /// <param name="maxSize">The max possible size of the window</param>
        /// <param name="offset">The offset of the topLeft postion</param>
        /// <param name="margin">The margin from the screen</param>
        /// <returns>The adjusted position of the window</returns>
        System.Drawing.Point Adjust(System.Drawing.Point topLeft, System.Drawing.Point maxSize, int offset, int margin)
        {
            Screen currentScreen = Screen.FromPoint(topLeft);
            System.Drawing.Rectangle rect = currentScreen.WorkingArea;

            // Set an offset from mouse position.
            topLeft.Offset(offset, offset);

            // Check if the window needs to go above the task bar, 
            // when the task bar shadows the HUD window.
            int totalHight = topLeft.Y + maxSize.Y + margin;

            if (totalHight > rect.Bottom)
            {
                topLeft.Y -= (totalHight - rect.Bottom);

                // If the screen dimensions exceed the hight of the window
                // set it just bellow the top bound.
                if (topLeft.Y < rect.Top)
                {
                    topLeft.Y = rect.Top + margin;
                }
            }

            int totalWidth = topLeft.X + maxSize.X + margin;
            // Check if the window needs to move to the left of the mouse, 
            // when the HUD exceeds the right window bounds.
            if (totalWidth > rect.Right)
            {
                // Since we already set an offset remove it and add the offset 
                // to the other side of the mouse (2x) in addition include the 
                // margin.
                topLeft.X -= (maxSize.X + (2 * offset + margin));

                // If the screen dimensions exceed the width of the window
                // don't exceed the left bound.
                if (topLeft.X < rect.Left)
                {
                    topLeft.X = rect.Left + margin;
                }
            }

            return topLeft;
        }
    }
}

Quelques explications:

1) topLeft - position of the top left at the desktop (works                     
   for multi screens - with different aspect ratio).                            
            Screen1              Screen2                                        
        ─  ┌───────────────────┐┌───────────────────┐ Screen3                   
        ▲  │                   ││                   │┌─────────────────┐  ─     
        │  │                   ││                   ││   ▼-            │  ▲     
   1080 │  │                   ││                   ││                 │  │     
        │  │                   ││                   ││                 │  │ 900 
        ▼  │                   ││                   ││                 │  ▼     
        ─  └──────┬─────┬──────┘└──────┬─────┬──────┘└──────┬────┬─────┘  ─     
                 ─┴─────┴─            ─┴─────┴─            ─┴────┴─             
           │◄─────────────────►││◄─────────────────►││◄───────────────►│        
                   1920                 1920                1440                
   If the mouse is in Screen3 a possible value might be:                        
   topLeft.X=4140 topLeft.Y=195                                                 
2) offset - the offset from the top left, one value for both                    
   X and Y directions.                                                          
3) maxSize - the maximal size of the window - including its                     
   size when it is expanded - from the following example                        
   we need maxSize.X = 200, maxSize.Y = 150 - To avoid the expansion            
   being out of bound.                                                          

   Non expanded window:                                                         
   ┌──────────────────────────────┐ ─                                           
   │ Window Name               [X]│ ▲                                           
   ├──────────────────────────────┤ │                                           
   │         ┌─────────────────┐  │ │ 100                                       
   │  Text1: │                 │  │ │                                           
   │         └─────────────────┘  │ │                                           
   │                         [▼]  │ ▼                                           
   └──────────────────────────────┘ ─                                           
   │◄────────────────────────────►│                                             
                 200                                                            

   Expanded window:                                                             
   ┌──────────────────────────────┐ ─                                           
   │ Window Name               [X]│ ▲                                           
   ├──────────────────────────────┤ │                                           
   │         ┌─────────────────┐  │ │                                           
   │  Text1: │                 │  │ │                                           
   │         └─────────────────┘  │ │ 150                                       
   │                         [▲]  │ │                                           
   │         ┌─────────────────┐  │ │                                           
   │  Text2: │                 │  │ │                                           
   │         └─────────────────┘  │ ▼                                           
   └──────────────────────────────┘ ─                                           
   │◄────────────────────────────►│                                             
                 200                                                            
4) margin - The distance the window should be from the screen                   
   work-area - Example:                                                          
   ┌─────────────────────────────────────────────────────────────┐ ─            
   │                                                             │ ↕ Margin     
   │                                                             │ ─            
   │                                                             │              
   │                                                             │              
   │                                                             │              
   │                          ┌──────────────────────────────┐   │              
   │                          │ Window Name               [X]│   │              
   │                          ├──────────────────────────────┤   │              
   │                          │         ┌─────────────────┐  │   │              
   │                          │  Text1: │                 │  │   │              
   │                          │         └─────────────────┘  │   │              
   │                          │                         [▲]  │   │              
   │                          │         ┌─────────────────┐  │   │              
   │                          │  Text2: │                 │  │   │              
   │                          │         └─────────────────┘  │   │              
   │                          └──────────────────────────────┘   │ ─            
   │                                                             │ ↕ Margin     
   ├──────────────────────────────────────────────────┬──────────┤ ─            
   │[start] [♠][♦][♣][♥]                              │en│ 12:00 │              
   └──────────────────────────────────────────────────┴──────────┘              
   │◄─►│                                                     │◄─►│              
    Margin                                                    Margin            

* Note that this simple algorithm will always want to leave the cursor          
  out of the window, therefor the window will jumps to its left:                
  ┌─────────────────────────────────┐        ┌─────────────────────────────────┐
  │                  ▼-┌──────────────┐      │  ┌──────────────┐▼-             │
  │                    │ Window    [X]│      │  │ Window    [X]│               │
  │                    ├──────────────┤      │  ├──────────────┤               │
  │                    │       ┌───┐  │      │  │       ┌───┐  │               │
  │                    │  Val: │   │  │ ->   │  │  Val: │   │  │               │
  │                    │       └───┘  │      │  │       └───┘  │               │
  │                    └──────────────┘      │  └──────────────┘               │
  │                                 │        │                                 │
  ├──────────────────────┬──────────┤        ├──────────────────────┬──────────┤
  │[start] [][][]     │en│ 12:00 │        │[start] [][][]     │en│ 12:00 │
  └──────────────────────┴──────────┘        └──────────────────────┴──────────┘
  If this is not a requirement, you can add a parameter to just use             
  the margin:                                                                   
  ┌─────────────────────────────────┐        ┌─────────────────────────────────┐
  │                  ▼-┌──────────────┐      │                ┌─▼-───────────┐ │
  │                    │ Window    [X]│      │                │ Window    [X]│ │
  │                    ├──────────────┤      │                ├──────────────┤ │
  │                    │       ┌───┐  │      │                │       ┌───┐  │ │
  │                    │  Val: │   │  │ ->   │                │  Val: │   │  │ │
  │                    │       └───┘  │      │                │       └───┘  │ │
  │                    └──────────────┘      │                └──────────────┘ │
  │                                 │        │                                 │
  ├──────────────────────┬──────────┤        ├──────────────────────┬──────────┤
  │[start] [][][]     │en│ 12:00 │        │[start] [][][]     │en│ 12:00 │
  └──────────────────────┴──────────┘        └──────────────────────┴──────────┘
* Supports also the following scenarios:
  1) Screen over screen:
       ┌─────────────────┐  
       │                 │
       │                 │
       │                 │
       │                 │
       └─────────────────┘
     ┌───────────────────┐ 
     │                   │ 
     │  ▼-               │ 
     │                   │ 
     │                   │ 
     │                   │ 
     └──────┬─────┬──────┘ 
           ─┴─────┴─       
  2) Window bigger than screen hight or width
     ┌─────────────────────────────────┐        ┌─────────────────────────────────┐ 
     │                                 │        │ ┌──────────────┐                │
     │                                 │        │ │ Window    [X]│                │
     │                  ▼-┌────────────│─┐      │ ├──────────────┤ ▼-             │
     │                    │ Window    [│]│      │ │       ┌───┐  │                │
     │                    ├────────────│─┤ ->   │ │  Val: │   │  │                │ 
     │                    │       ┌───┐│ │      │ │       └───┘  │                │
     │                    │  Val: │   ││ │      │ │       ┌───┐  │                │
     │                    │       └───┘│ │      │ │  Val: │   │  │                │
     ├──────────────────────┬──────────┤ │      ├──────────────────────┬──────────┤
     │[start] [♠][♦][♣]     │en│ 12:00 │ │      │[start] [♠][♦][♣]     │en│ 12:00 │
     └──────────────────────┴──────────┘ │      └──────────────────────┴──────────┘
                          │       ┌───┐  │        │       └───┘  │
                          │  Val: │   │  │        └──────────────┘
                          │       └───┘  │
                          └──────────────┘


     ┌─────────────────────────────────┐             ┌─────────────────────────────────┐     
     │                                 │             │                                 │ 
     │                                 │             │ ┌───────────────────────────────│───┐
     │    ▼-┌──────────────────────────│────────┐    │ │ W▼-dow                        │[X]│
     │      │ Window                   │     [X]│    │ ├───────────────────────────────│───┤
     │      ├──────────────────────────│────────┤    │ │       ┌───┐      ┌───┐      ┌─┤─┐ │
     │      │       ┌───┐      ┌───┐   │  ┌───┐ │ -> │ │  Val: │   │ Val: │   │ Val: │ │ │ │
     │      │  Val: │   │ Val: │   │ Va│: │   │ │    │ │       └───┘      └───┘      └─┤─┘ │
     │      │       └───┘      └───┘   │  └───┘ │    │ └───────────────────────────────│───┘
     ├──────────────────────┬──────────┤────────┘    ├──────────────────────┬──────────┤
     │[start] [♠][♦][♣]     │en│ 12:00 │             │[start] [♠][♦][♣]     │en│ 12:00 │     
     └──────────────────────┴──────────┘             └──────────────────────┴──────────┘     
  • Je n'avais pas d'autre choix que d'utiliser le format de code (sinon les espaces blancs auraient été perdus).
  • À l'origine, cela figurait dans le code ci-dessus en tant que <remark><code>...</code></remark>

1

Je comprends les demandes. Le fait est qu'il existe des méthodes WPF pour obtenir ces valeurs - mais oui, l'un des contributeurs a raison, pas directement. La solution n'est pas d'obtenir toutes ces solutions de contournement, mais de changer l'approche initiale selon une conception et un développement propres.

A) Réglez la fenêtre principale initiale sur Écran

B) Obtenez les valeurs pour ActualWindow, y compris une tonne de méthodes WPF utiles

C) Vous pouvez ajouter autant de fenêtres que vous le souhaitez pour le comportement que vous souhaitez avoir, comme redimensionnable, minimisé quoi que ce soit ... mais maintenant vous pouvez toujours accéder à l'écran chargé et rendu

Veuillez faire attention à l'exemple suivant, il y a du code autour qui rend nécessaire d'utiliser ce type d'approche, mais cela devrait fonctionner (cela vous donnerait les points pour chacun des coins de votre écran): Exemple de travail sur simple, Double moniteur et différentes résolutions (dans la classe principale de la fenêtre principale):

InitializeComponent();
[…]
ActualWindow.AddHandler(Window.LoadedEvent, new RoutedEventHandler(StartUpScreenLoaded));

Événement acheminé:

private void StartUpScreenLoaded(object sender, RoutedEventArgs e)
    {
        Window StartUpScreen = sender as Window;

        // Dispatcher Format B:
        Dispatcher.Invoke(new Action(() =>
        {
            // Get Actual Window on Loaded
            StartUpScreen.InvalidateVisual();
            System.Windows.Point CoordinatesTopRight = StartUpScreen.TranslatePoint(new System.Windows.Point((StartUpScreen.ActualWidth), (0d)), ActualWindow);
            System.Windows.Point CoordinatesBottomRight = StartUpScreen.TranslatePoint(new System.Windows.Point((StartUpScreen.ActualWidth), (StartUpScreen.ActualHeight)), ActualWindow);
            System.Windows.Point CoordinatesBottomLeft = StartUpScreen.TranslatePoint(new System.Windows.Point((0d), (StartUpScreen.ActualHeight)), ActualWindow);

            // Set the Canvas Top Right, Bottom Right, Bottom Left Coordinates
            System.Windows.Application.Current.Resources["StartUpScreenPointTopRight"] = CoordinatesTopRight;
            System.Windows.Application.Current.Resources["StartUpScreenPointBottomRight"] = CoordinatesBottomRight;
            System.Windows.Application.Current.Resources["StartUpScreenPointBottomLeft"] = CoordinatesBottomLeft;
        }), DispatcherPriority.Loaded);
    }

1

Si vous utilisez une fenêtre plein écran (ayant son WindowState = WindowState.Maximized, WindowStyle = WindowStyle.None), vous pouvez envelopper son contenu System.Windows.Controls.Canvascomme ceci:

<Canvas Name="MyCanvas" Width="auto" Height="auto">
...
</Canvas>

Ensuite, vous pouvez utiliser MyCanvas.ActualWidthetMyCanvas.ActualHeight pour obtenir la résolution de l'écran actuel, avec les paramètres DPI pris en compte et en unités indépendantes de l'appareil. Il n'ajoute aucune marge comme le fait la fenêtre agrandie elle-même.

(Canvas accepte les UIElements comme enfants, vous devriez donc pouvoir l'utiliser avec n'importe quel contenu.)


0

Centrer la fenêtre sur l'écran en XAML WindowStartupLocation="CenterOwner"puis appeler WindowLoaded ()

double ScreenHeight = 2 * (Top + 0.5 * Height);


-4
double screenWidth = System.Windows.SystemParameters.PrimaryScreenWidth;
double screenhight= System.Windows.SystemParameters.PrimaryScreenHeight;

4
Comme la réponse précédente, ce n'est que pour l' écran principal . J'avais besoin de l' écran actuel .
Nils

-4

Cela fonctionne avec

this.Width = System.Windows.SystemParameters.VirtualScreenWidth;
this.Height = System.Windows.SystemParameters.VirtualScreenHeight;

Testé sur 2 moniteurs.


Si vous regardez la réponse du 18 mai 2010 à 15h52 - qui était exactement la même que la vôtre, vous verrez qu'elle VirtualScreens'étend sur tous les écrans - donc cela ne fonctionnera jamais si vous avez plus d'un écran!
Nils
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.