Come ottenere le dimensioni della schermata corrente in WPF?


87

So di poter ottenere le dimensioni dello schermo principale utilizzando

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

Ma come ottengo le dimensioni dello schermo corrente? (Gli utenti multischermo non utilizzano sempre lo schermo principale e non tutti gli schermi utilizzano la stessa risoluzione, giusto?)

Sarebbe bello poter accedere alla dimensione da XAML, ma sarebbe sufficiente farlo dal codice (C #).


1
Definisci "corrente". Una finestra può essere su più di uno schermo contemporaneamente.
Jim Balter

Risposte:


13

Per quanto ne so, non esiste una funzione WPF nativa per ottenere le dimensioni del monitor corrente. Invece puoi PInvoke funzioni native di più monitor di visualizzazione , racchiuderle in classi gestite ed esporre tutte le proprietà necessarie per utilizzarle da XAML.


Questo è esattamente ciò che temevo: la necessità di P / Invoke la roba o di accedere a System.Windows.Forms.Screen in qualche modo. E quando lo faccio devo sempre calcolare i "pixel indipendenti dal dispositivo" ... Grazie, però.
Nils

Sì ... Forse anche la funzione SystemParameters.ConvertPixel () ti aiuterà. È interno, ma a Reflector non interessa
:)

74

Ho creato un piccolo wrapper attorno allo schermo da System.Windows.Forms, attualmente tutto funziona ... Non sono sicuro dei "pixel indipendenti dal dispositivo", però.

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

Grazie per questo fantastico piccolo wrapper, nota che global :: Rect doveva essere convertito in un semplice Rect quando l'ho usato con WPF 3.5.
Andy Dent

1
Mi piace questo. Certo ha bisogno di un po 'di lavoro, ma non mi aspetto di trovare soluzioni al 100%.
jeff

4
Funziona alla grande. Ho appena esteso il metodo GetRect per restituire Rect in pixel indipendenti dal dispositivo: private Rect GetRect (valore Rectangle) {var pixelWidthFactor = SystemParameters.WorkArea.Width / this.screen.WorkingArea.Width; var pixelHeightFactor = SystemParameters.WorkArea.Height / this.screen.WorkingArea.Height; restituisce nuovo Rect {X = value.X * pixelWidthFactor, Y = value.Y * pixelHeightFactor, Width = value.Width * pixelWidthFactor, Height = value.Height * pixelHeightFactor}; }
Jürgen Bayer

1
Credo che l'aggiunta del codice da @ JürgenBayer migliorerà ulteriormente la tua risposta. Ho avuto il problema con i pixel indipendenti dal dispositivo e il codice di Jürgen lo ha risolto. Grazie ad entrambi.
Bruno V

3
@ Jürgen: credo che il tuo metodo funzioni solo in circostanze molto specifiche. Se "this.screen" ha un rapporto di aspetto diverso rispetto al monitor principale (che il tuo metodo usa sempre come riferimento invece del monitor corrente), otterrai erroneamente fattori di scala diversi per larghezza e altezza che portano a dimensioni dello schermo errate. Se la schermata corrente ha un'impostazione DPI diversa da quella principale, i limiti saranno tutti sbagliati. Sul mio sistema, ogni singolo valore del Rect restituito è (selvaggiamente) errato.
Wilford,

27

Qui amico. Questo ti darà solo la larghezza e l'altezza dell'area di lavoro

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

13
"Ottiene le dimensioni dell'area di lavoro sul monitor di visualizzazione principale." - non quello che stavo cercando ...
Nils

10

Questo ti darà la schermata corrente basata sull'angolo in alto a sinistra della finestra, chiama semplicemente this.CurrentScreen () per ottenere informazioni sulla schermata corrente.

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'utente sta cercando le dimensioni dello schermo corrente, piuttosto che lo schermo principale.
Greggannicott

3
questo restituisce la schermata corrente, basata sulla posizione in alto a sinistra della finestra da cui si chiama la funzione di supporto. Ma devo mancare qualcosa a questa domanda, in base al punteggio della mia risposta.
EJ

Forse Greggannicott intendeva pubblicare il suo commento su una delle altre risposte, poiché è completamente irrilevante per questa.
Jim Balter

@ jim-balter Votato - In realtà questa è la risposta migliore qui, avevo bisogno dello schermo per ottenere l'area di lavoro e quindi assicurarmi che il mio dialogo non superi il limite, posterò la mia soluzione qui. Complimenti a EJ per la risposta rapida al punto.
Giovedì

^ bizzarro commento.
Jim Balter,

5

Prenditi il ​​tempo per esaminare i membri di SystemParameters.

  • VirtualScreenWidth
  • VirtualScreenHeight

Questi tengono anche conto delle posizioni relative degli schermi.

Testato solo con due monitor.


9
dana - Non l'ho testato, ma VirtualScreen * non restituisce la dimensione intera di tutti gli schermi? - Ho specificamente bisogno delle dimensioni di uno schermo (quello in cui risiede la finestra corrente).
Nils

1
VirtualScreen sembra riferirsi alla dimensione di tutti gli schermi
Thomas

1
Una miniera ha restituito le dimensioni di tutti e 4 i miei schermi combinati.
DJ van Wyk

3

Perché non usarlo?

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

Lo schermo è Windows.Forms piuttosto che WPF, ma questo è un punto di partenza. Se guardi la soluzione che ho usato allora ( stackoverflow.com/a/2118993/180156 ) questo è esattamente quello che ho fatto - tuttavia ho scelto System.Windows.Forms.Screendi far fronte al pixel indipendente dal dispositivo
Nils

3

Se hai familiarità con l'uso della classe System.Windows.Forms , puoi semplicemente aggiungere un riferimento alla classe System.Windows.Forms al tuo progetto:

Esplora soluzioni -> Riferimenti -> Aggiungi riferimenti ... -> (Assembly: Framework) -> scorri verso il basso e controlla l' assembly System.Windows.Forms -> OK .

Ora puoi aggiungere usando System.Windows.Forms; dichiarazione e usa lo schermo nel tuo progetto wpf proprio come prima.


Questa è di gran lunga la soluzione più semplice. Mi chiedo: oltre ad aggiungere un gruppo piuttosto grande, ci sono buone ragioni per non farlo in questo modo?
AeonOfTime

3

Avevo anche bisogno della dimensione dello schermo corrente, in particolare dell'area di lavoro, che restituiva il rettangolo escludendo la larghezza della barra delle applicazioni.

L'ho usato per riposizionare una finestra, che si apre a destra e in basso dove è posizionato il mouse. Poiché la finestra è abbastanza grande, in molti casi è uscita dai limiti dello schermo. Il codice seguente si basa sulla risposta @ej: Questo ti darà la schermata corrente ... . La differenza è che mostro anche il mio algoritmo di riposizionamento, che presumo sia effettivamente il punto.

Il codice:

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

Alcune spiegazioni:

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 │     
     └──────────────────────┴──────────┘             └──────────────────────┴──────────┘     
  • Non avevo altra scelta che usare il formato del codice (altrimenti gli spazi bianchi sarebbero andati persi).
  • Originariamente questo appariva nel codice sopra come un file <remark><code>...</code></remark>

1

Capisco le richieste. Il fatto è che esistono metodi WPF per ottenere quei valori, ma sì, uno dei contributori ha ragione, non direttamente. La soluzione non è ottenere tutte quelle soluzioni alternative, ma modificare l'approccio iniziale in base a un design e uno sviluppo puliti.

A) Impostare la finestra principale iniziale su Schermo

B) Ottieni i valori per ActualWindow inclusi un sacco di utili metodi WPF

C) Puoi aggiungere tutte le finestre che vuoi per il comportamento che vuoi avere, come ridimensionabile, minimizzato qualunque ... ma ora puoi sempre accedere alla schermata caricata e renderizzata

Fai attenzione con il seguente esempio, c'è del codice in giro che rende necessario usare quel tipo di approccio, tuttavia dovrebbe funzionare (ti darebbe i punti per ciascuno degli angoli dello schermo): Esempio di lavoro su singolo, Doppio monitor e diverse risoluzioni (all'interno della classe della finestra principale principale):

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

Evento indirizzato:

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

Se usi una finestra a schermo intero (che ne ha WindowState = WindowState.Maximized, WindowStyle = WindowStyle.None), puoi racchiudere il suo contenuto in System.Windows.Controls.Canvasquesto modo:

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

Quindi puoi usare MyCanvas.ActualWidtheMyCanvas.ActualHeight per ottenere la risoluzione dello schermo corrente, tenendo conto delle impostazioni DPI e in unità indipendenti dal dispositivo. Non aggiunge margini come fa la finestra ingrandita stessa.

(Canvas accetta messaggi di posta UIElementelettronica come bambini, quindi dovresti essere in grado di usarlo con qualsiasi contenuto.)


0

Centra la finestra sullo schermo in XAML, WindowStartupLocation="CenterOwner"quindi chiama in WindowLoaded ()

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


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

4
Come la risposta precedente, questo è solo per lo schermo principale . Avevo bisogno della schermata corrente .
Nils

-4

Funziona con

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

Testato su 2 monitor.


se guardi la risposta del 18 maggio '10 alle 15:52 - che era esattamente la tua vedrai che si VirtualScreenestende su tutti gli schermi - quindi questo non funzionerà mai se hai più di uno schermo!
Nils
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.