Wie erhalte ich die Größe des aktuellen Bildschirms in WPF?


85

Ich weiß, dass ich die Größe des primären Bildschirms mithilfe von ermitteln kann

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

Aber wie erhalte ich die Größe des aktuellen Bildschirms? (Benutzer mit mehreren Bildschirmen verwenden nicht immer den primären Bildschirm und nicht alle Bildschirme verwenden dieselbe Auflösung, oder?)

Es wäre schön, auf die Größe von XAML zugreifen zu können, aber dies über Code (C #) zu tun, würde ausreichen.


1
Definieren Sie "aktuell". Ein Fenster kann sich auf mehreren Bildschirmen gleichzeitig befinden.
Jim Balter

Antworten:


13

Soweit ich weiß, gibt es keine native WPF-Funktion, um die Abmessungen des aktuellen Monitors abzurufen. Stattdessen können Sie native Funktionen für mehrere Anzeigemonitore PInvoke verwenden , sie in eine verwaltete Klasse einschließen und alle Eigenschaften verfügbar machen, die Sie benötigen, um sie aus XAML zu verwenden.


Genau das habe ich befürchtet - die Notwendigkeit, das Zeug aufzurufen oder auf System.Windows.Forms.Screen zuzugreifen. Und wenn ich das tue, muss ich immer die "geräteunabhängigen Pixel" berechnen ... Danke.
Nils

Ja ... Vielleicht hilft Ihnen auch die Funktion SystemParameters.ConvertPixel (). Es ist intern, aber Reflector ist das egal
:)

72

Ich habe aus System.Windows.Forms einen kleinen Wrapper um den Bildschirm erstellt, derzeit funktioniert alles ... Ich bin mir jedoch nicht sicher über die "geräteunabhängigen Pixel".

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

Vielen Dank für diesen tollen kleinen Wrapper. Beachten Sie, dass das globale :: Rect bei der Verwendung mit WPF 3.5 in einfaches Rect konvertiert werden musste.
Andy Dent

SystemParameters.PrimaryScreenHeighterhält die "geräteunabhängigen Pixel". Dies führt leider nicht zu "geräteunabhängigen Pixeln", sondern zu den physischen Pixeln. Naja.
Mark Lopez

4
Funktioniert super. Ich habe gerade die GetRect-Methode erweitert, um das Rect in geräteunabhängigen Pixeln zurückzugeben: private Rect GetRect (Rechteckwert) {var pixelWidthFactor = SystemParameters.WorkArea.Width / this.screen.WorkingArea.Width; var pixelHeightFactor = SystemParameters.WorkArea.Height / this.screen.WorkingArea.Height; return new Rect {X = Wert.X * pixelWidthFactor, Y = Wert.Y * pixelHeightFactor, Width = value.Width * pixelWidthFactor, Height = value.Height * pixelHeightFactor}; }
Jürgen Bayer

1
Ich glaube, dass das Hinzufügen des Codes von @ JürgenBayer Ihre Antwort noch weiter verbessern wird. Ich hatte das Problem mit den geräteunabhängigen Pixeln und der Code von Jürgen löste es. Danke euch beiden.
Bruno V

3
@ Jürgen: Ich glaube, deine Methode funktioniert nur unter ganz bestimmten Umständen. Wenn "this.screen" ein anderes Seitenverhältnis als der primäre Monitor hat (den Ihre Methode immer als Referenz anstelle des aktuellen Monitors verwendet), erhalten Sie fälschlicherweise unterschiedliche Skalierungsfaktoren für Breite und Höhe, was zu falschen Bildschirmabmessungen führt. Wenn der aktuelle Bildschirm eine andere DPI-Einstellung als der primäre Bildschirm hat, sind alle Grenzen falsch. Auf meinem System ist jeder einzelne Wert des zurückgegebenen Rect (wild) falsch.
Wilford

27

Hier Kumpel. Dadurch erhalten Sie nur die Breite und Höhe des Arbeitsbereichs

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

10
"Ruft die Größe des Arbeitsbereichs auf dem primären Anzeigemonitor ab." - nicht das, wonach ich gesucht habe ...
Nils

10

Dadurch erhalten Sie den aktuellen Bildschirm oben links im Fenster. Rufen Sie einfach this.CurrentScreen () auf, um Informationen zum aktuellen Bildschirm zu erhalten.

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

Der Benutzer sucht nach den Abmessungen des aktuellen Bildschirms und nicht nach dem primären Bildschirm.
Greggannicott

3
Dies gibt den aktuellen Bildschirm zurück, basierend auf der oberen linken Position des Fensters, von dem aus Sie die Hilfsfunktion aufrufen. Aber ich muss etwas zu dieser Frage vermissen, basierend auf der Punktzahl meiner Antwort.
EJ

Vielleicht wollte Greggannicott seinen Kommentar zu einer der anderen Antworten posten, da er für diese völlig irrelevant ist.
Jim Balter

@ jim-balter Voted Up - Eigentlich ist dies die beste Antwort hier. Ich brauchte den Bildschirm, um den Arbeitsbereich zu erhalten und dann sicherzustellen, dass mein Dialog die Grenze nicht überschreitet. Ich werde meine Lösung hier veröffentlichen. Ein großes Lob an EJ für die schnelle Antwort auf den Punkt.
Juv

^ bizarrer Kommentar.
Jim Balter

5

Nehmen Sie sich Zeit, um die SystemParameters-Mitglieder zu durchsuchen.

  • VirtualScreenWidth
  • VirtualScreenHeight

Diese berücksichtigen sogar die relativen Positionen der Bildschirme.

Nur mit zwei Monitoren getestet.


8
dana - Ich habe dies nicht getestet, aber gibt VirtualScreen * nicht die volle Größe aller Bildschirme zurück? - Ich benötige speziell die Größe eines Bildschirms (der, in dem sich das aktuelle Fenster befindet).
Nils

VirtualScreen scheint sich auf die Größe aller Bildschirme zu beziehen
Thomas

Eine Mine ergab die Größe aller 4 meiner Bildschirme zusammen.
DJ van Wyk

3

Warum nicht einfach das benutzen?

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

Der Bildschirm ist Windows.Forms und nicht WPF - dies ist jedoch ein Ausgangspunkt. Wenn Sie sich die Lösung ansehen, die ich damals verwendet habe ( stackoverflow.com/a/2118993/180156 ), dann ist dies genau das, was ich getan habe - allerdings habe ich mich gewickelt System.Windows.Forms.Screen, um mit geräteunabhängigen Pixeln fertig zu werden
Nils

3

Wenn Sie mit der Verwendung der System.Windows.Forms- Klasse vertraut sind , können Sie dies einfach tun eine Referenz hinzufügen Ihrem Projekt der System.Windows.Forms-Klasse :

Projektmappen-Explorer -> Verweise -> Verweise hinzufügen ... -> (Baugruppen: Framework) -> scrollen Sie nach unten und überprüfen Sie die Baugruppe System.Windows.Forms -> OK .

Jetzt können Sie mit System.Windows.Forms hinzufügen . Anweisung und Verwendung des Bildschirms in Ihrem wpf-Projekt wie zuvor.


Dies ist bei weitem die einfachste Lösung. Ich frage mich - gibt es außer dem Hinzufügen einer ziemlich großen Baugruppe gute Gründe, dies nicht so zu tun?
AeonOfTime

1

Ich verstehe die Forderungen. Die Sache ist, es gibt WPF-Methoden, um diese Werte zu erhalten - aber ja, einer der Mitwirkenden hat Recht, nicht direkt. Die Lösung besteht nicht darin, alle diese Problemumgehungen zu erhalten, sondern den ursprünglichen Ansatz entsprechend dem sauberen Design und der sauberen Entwicklung zu ändern.

A) Stellen Sie das anfängliche Hauptfenster auf Bildschirm

B) Holen Sie sich die Werte für das ActualWindow, einschließlich einer Menge nützlicher WPF-Methoden

C) Sie können so viele Fenster hinzufügen, wie Sie möchten, um das gewünschte Verhalten zu erzielen, z. B. die Größe ändern, was auch immer minimiert werden. Jetzt können Sie jedoch immer auf den Bildschirm "Geladen" und "Gerendert" zugreifen

Bitte seien Sie vorsichtig mit dem folgenden Beispiel. Es gibt einen Code, der es erforderlich macht, diesen Ansatz zu verwenden. Er sollte jedoch funktionieren (er würde Ihnen die Punkte für jede der Ecken Ihres Bildschirms geben): Arbeitsbeispiel für Single, Dual Monitor und verschiedene Auflösungen (innerhalb der primären Hauptfensterklasse):

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

Routed Event:

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

Wenn Sie ein Vollbildfenster (mit einem WindowState = WindowState.Maximized, WindowStyle = WindowStyle.None) verwenden, können Sie den Inhalt folgendermaßen System.Windows.Controls.Canvaseinschließen:

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

Dann können Sie MyCanvas.ActualWidthund verwendenMyCanvas.ActualHeight die Auflösung des aktuellen Bildschirms zu erhalten, mit DPI - Einstellungen berücksichtigt und in geräteunabhängige Einheiten. Es werden keine Ränder hinzugefügt, wie dies das maximierte Fenster selbst tut.

(Canvas akzeptiert UIElements als Kinder, daher sollten Sie es mit allen Inhalten verwenden können.)


1

Ich brauchte auch die aktuelle Bildschirmgröße, insbesondere den Arbeitsbereich, der das Rechteck ohne die Breite der Taskleiste zurückgab.

Ich habe es verwendet, um ein Fenster neu zu positionieren, das rechts und unten bis zur Position der Maus geöffnet wird. Da das Fenster ziemlich groß ist, hat es in vielen Fällen die Bildschirmgrenzen überschritten. Der folgende Code basiert auf der Antwort von @ej: Dadurch erhalten Sie den aktuellen Bildschirm ... . Der Unterschied besteht darin, dass ich auch meinen Repositionierungsalgorithmus zeige, von dem ich annehme, dass er tatsächlich der Punkt ist.

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

Einige Erklärungen:

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      
     └──────────────────────┴──────────┘             └──────────────────────┴──────────┘     
  • Ich hatte keine andere Wahl, als das Codeformat zu verwenden (sonst wären die Leerzeichen verloren gegangen).
  • Ursprünglich erschien dies im obigen Code als <remark><code>...</code></remark>

0

Fenster in XAML auf dem Bildschirm WindowStartupLocation="CenterOwner"zentrieren und dann WindowLoaded () aufrufen

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


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

4
Wie die vorherige Antwort gilt dies nur für den primären Bildschirm. Ich brauchte den aktuellen Bildschirm.
Nils

-4

Es funktioniert mit

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

Getestet auf 2 Monitoren.


Wenn Sie sich die Antwort vom 18. Mai 10 um 15:52 Uhr ansehen - die genau die gleiche war wie Ihre, werden Sie sehen, dass sie VirtualScreenalle Bildschirme umfasst -, also wird dies niemals funktionieren, wenn Sie mehr als einen Bildschirm haben!
Nils
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.