Wie kann ich die aktiven Bildschirmabmessungen ermitteln?


142

Was ich suche, entspricht System.Windows.SystemParameters.WorkAreadem Monitor, auf dem sich das Fenster gerade befindet.

Klarstellung: Das fragliche Fenster ist WPFnicht WinForm.


2
Die akzeptierte Antwort wurde geändert, um die beste Vorgehensweise von WPF widerzuspiegeln. System.Windows.SystemParameters. *
chilltemp

1
Die Besessenheit, keinen WinForms-Namespace zu verwenden, scheint mir seltsam, es bringt Ihnen nichts; Stattdessen haben Sie nicht die Werkzeuge, die Sie zur ordnungsgemäßen Lösung des Problems benötigen.
Jeff Yates

4
Für mich geht es nicht um WinForms vs. WPF. Es geht darum, etwas Neues zu lernen. Ich kann mich nicht entscheiden, welcher Weg besser ist, wenn ich nicht beide Wege lerne.
Chilltemp

3
Nun, in diesem Szenario gibt es keine "beide Möglichkeiten", da es nur eine Möglichkeit gibt, dies zu tun, nämlich das WinForms-Zeug zu verwenden.
Jeff Yates

@ Jeff Yates: Du bist richtig. Ich habe das ursprüngliche Projekt ausgegraben, für das ich diese Frage gestellt habe, und festgestellt, dass ich die PrimaryScreen * -Eigenschaften verwendet habe. Sie haben meine Bedürfnisse des Tages gelöst, aber nicht die eigentliche Frage, die ich gestellt habe. Entschuldigung für das Durcheinander; Ich habe die akzeptierte Antwort entsprechend geändert.
Chilltemp

Antworten:


143

Screen.FromControl, Screen.FromPointUnd Screen.FromRectangleSie sollten dabei helfen. Zum Beispiel in WinForms wäre es:

class MyForm : Form
{
  public Rectangle GetScreen()
  {
    return Screen.FromControl(this).Bounds;
  }
}

Ich kenne keinen entsprechenden Anruf für WPF. Daher müssen Sie so etwas wie diese Erweiterungsmethode ausführen.

static class ExtensionsForWPF
{
  public static System.Windows.Forms.Screen GetScreen(this Window window)
  {
    return System.Windows.Forms.Screen.FromHandle(new WindowInteropHelper(window).Handle);
  }
}

1
Vielleicht hat mein Tagging nicht deutlich gemacht, dass ich WPF-Fenster verwende, nicht WinForms. Ich habe nicht auf die System.Windows.Forms.dll verwiesen, und es würde sowieso nicht funktionieren, da WPF einen eigenen Vererbungsbaum hat.
Chilltemp

1
Bitte. Ich entschuldige mich dafür, dass ich nicht direkt zur Antwort gekommen bin. Ich musste untersuchen, was in WPF verfügbar war, bevor ich meinen Beitrag aktualisierte.
Jeff Yates

Dies funktioniert, um ein Fenster am rechten Rand zu platzieren: var bounds = this.GetScreen (). WorkingArea; this.Left = bounds.Right - this.Width; Es sind jedoch Verweise auf System.Windows.Forms und System.Drawing erforderlich, was nicht ideal ist.
Anthony

1
@devios Beachten Sie, dass dieser Anruf nicht DPI-fähig ist. Sie müssen Berechnungen durchführen.
Lynn Crumbling

6
In meinem VS 2015 WPF - Anwendung .NET 4.5 auf meinem 4-Monitor - System auf Windows 10 Pro (v10.0.14393) mit der Ausrichtung windowauf dem Monitor über meiner Primary ist ( zum Beispiel seines Top < 0), FromHandlekehrte das Screenallerdings für meinen primärer Monitor (selbst windowwar vollständig innerhalb der sekundäre Monitor)!?! Seufzer. Es sieht so aus, als Screen.AllScreensmüsste ich das Array selbst durchsuchen . Warum können Dinge nicht "einfach funktionieren"?!? Arrrrgh.
Tom

62

Sie können dies verwenden, um Desktop-Arbeitsbereichsgrenzen des primären Bildschirms abzurufen:

System.Windows.SystemParameters.WorkArea

Dies ist auch nützlich, um nur die Größe des primären Bildschirms zu ermitteln:

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


19
Ich bin verwirrt ... Dies scheint nur die primären Bildschirmabmessungen zurückzugeben. Ich möchte wissen, wie
groß

1
Dies beantwortet die Frage nicht und selbst wenn Sie nur die Größe der primären Anzeige erhalten möchten, sind die Systemparameter (in WPF) falsch. Sie geben geräteunabhängige Einheiten und keine Pixel zurück. Für eine bessere Implementierung siehe diese Antwort: stackoverflow.com/questions/254197/…
Patrick Klug

1
PrimaryScreenHeight / Width funktionierte genau wie erwartet, und MSDN enthält Folgendes: "Ruft einen Wert ab, der die Bildschirmhöhe des primären Anzeigemonitors in Pixel angibt." WorkArea sagt nicht speziell Pixel, aber die Dokumentation und Verwendungsbeispiele lassen mich glauben, dass es auch in Pixel ist. Haben Sie einen Link zu etwas, das auf die Verwendung geräteunabhängiger Einheiten hinweist?
Chilltemp


17

Hinzufügen einer Lösung, die stattdessen nicht WinForms, sondern NativeMethods verwendet. Zuerst müssen Sie die erforderlichen nativen Methoden definieren.

public static class NativeMethods
{
    public const Int32 MONITOR_DEFAULTTOPRIMERTY = 0x00000001;
    public const Int32 MONITOR_DEFAULTTONEAREST = 0x00000002;


    [DllImport( "user32.dll" )]
    public static extern IntPtr MonitorFromWindow( IntPtr handle, Int32 flags );


    [DllImport( "user32.dll" )]
    public static extern Boolean GetMonitorInfo( IntPtr hMonitor, NativeMonitorInfo lpmi );


    [Serializable, StructLayout( LayoutKind.Sequential )]
    public struct NativeRectangle
    {
        public Int32 Left;
        public Int32 Top;
        public Int32 Right;
        public Int32 Bottom;


        public NativeRectangle( Int32 left, Int32 top, Int32 right, Int32 bottom )
        {
            this.Left = left;
            this.Top = top;
            this.Right = right;
            this.Bottom = bottom;
        }
    }


    [StructLayout( LayoutKind.Sequential, CharSet = CharSet.Auto )]
    public sealed class NativeMonitorInfo
    {
        public Int32 Size = Marshal.SizeOf( typeof( NativeMonitorInfo ) );
        public NativeRectangle Monitor;
        public NativeRectangle Work;
        public Int32 Flags;
    }
}

Und dann holen Sie sich den Monitorgriff und die Monitorinformationen wie folgt.

        var hwnd = new WindowInteropHelper( this ).EnsureHandle();
        var monitor = NativeMethods.MonitorFromWindow( hwnd, NativeMethods.MONITOR_DEFAULTTONEAREST );

        if ( monitor != IntPtr.Zero )
        {
            var monitorInfo = new NativeMonitorInfo();
            NativeMethods.GetMonitorInfo( monitor, monitorInfo );

            var left = monitorInfo.Monitor.Left;
            var top = monitorInfo.Monitor.Top;
            var width = ( monitorInfo.Monitor.Right - monitorInfo.Monitor.Left );
            var height = ( monitorInfo.Monitor.Bottom - monitorInfo.Monitor.Top );
        }

1
Können Sie die tatsächliche Bildschirmgröße ermitteln, wenn der Skalierungsfaktor Ihrer Fenster vorhanden ist (100% / 125% / 150% / 200%)?
Kiquenet


12

Achten Sie auf den Skalierungsfaktor Ihrer Fenster (100% / 125% / 150% / 200%). Sie können die tatsächliche Bildschirmgröße mithilfe des folgenden Codes ermitteln:

SystemParameters.FullPrimaryScreenHeight
SystemParameters.FullPrimaryScreenWidth

1
Das ist für den primären Bildschirm - was ist, wenn sich Ihr App-Fenster auf einem virtuellen (erweiterten) Bildschirm befindet (dh Sie haben einen oder zwei externe Monitore an Ihren PC angeschlossen)?
Matt

4

Ich wollte die Bildschirmauflösung vor dem Öffnen des ersten meiner Fenster haben, daher hier eine schnelle Lösung, um ein unsichtbares Fenster zu öffnen, bevor die Bildschirmabmessungen tatsächlich gemessen werden (Sie müssen die Fensterparameter an Ihr Fenster anpassen, um sicherzustellen, dass beide geöffnet sind der gleiche Bildschirm - hauptsächlich WindowStartupLocationist das wichtig)

Window w = new Window();
w.ResizeMode = ResizeMode.NoResize;
w.WindowState = WindowState.Normal;
w.WindowStyle = WindowStyle.None;
w.Background = Brushes.Transparent;
w.Width = 0;
w.Height = 0;
w.AllowsTransparency = true;
w.IsHitTestVisible = false;
w.WindowStartupLocation = WindowStartupLocation.Manual;
w.Show();
Screen scr = Screen.FromHandle(new WindowInteropHelper(w).Handle);
w.Close();

3

Dies ist eine "Center Screen DotNet 4.5-Lösung ", die SystemParameters anstelle von System.Windows.Forms oder My.Compuer.Screen verwendet : Da Windows 8 die Berechnung der Bildschirmabmessungen geändert hat, sieht es für mich nur so aus (Taskleistenberechnung) inbegriffen):

Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
    Dim BarWidth As Double = SystemParameters.VirtualScreenWidth - SystemParameters.WorkArea.Width
    Dim BarHeight As Double = SystemParameters.VirtualScreenHeight - SystemParameters.WorkArea.Height
    Me.Left = (SystemParameters.VirtualScreenWidth - Me.ActualWidth - BarWidth) / 2
    Me.Top = (SystemParameters.VirtualScreenHeight - Me.ActualHeight - BarHeight) / 2         
End Sub

Mittlerer Bildschirm WPF XAML


Installer Setup in WPF?
Kiquenet

Die Hauptfrage betrifft die Bildschirmposition. Wie das Msi-Installationsprogramm, Innosetup oder andere habe ich mein eigenes Installationsprogramm mit CPU-Prüfung, Berechtigungsprüfung, Treiberüberprüfung und vielem mehr erstellt, das sehr einfach zu bedienen ist. Das ist der Screenshot über.
Nasenbaer

3

Ich musste die maximale Größe meiner Fensteranwendung festlegen. Dieser könnte entsprechend geändert werden. Die Anwendung wird im primären Bildschirm oder im sekundären angezeigt. Um dieses Problem zu lösen, haben wir eine einfache Methode erstellt, die ich Ihnen als Nächstes zeige:

/// <summary>
/// Set the max size of the application window taking into account the current monitor
/// </summary>
public static void SetMaxSizeWindow(ioConnect _receiver)
{
    Point absoluteScreenPos = _receiver.PointToScreen(Mouse.GetPosition(_receiver));

    if (System.Windows.SystemParameters.VirtualScreenLeft == System.Windows.SystemParameters.WorkArea.Left)
    {
        //Primary Monitor is on the Left
        if (absoluteScreenPos.X <= System.Windows.SystemParameters.PrimaryScreenWidth)
        {
            //Primary monitor
            _receiver.WindowApplication.MaxWidth = System.Windows.SystemParameters.WorkArea.Width;
            _receiver.WindowApplication.MaxHeight = System.Windows.SystemParameters.WorkArea.Height;
        }
        else
        {
            //Secondary monitor
            _receiver.WindowApplication.MaxWidth = System.Windows.SystemParameters.VirtualScreenWidth - System.Windows.SystemParameters.WorkArea.Width;
            _receiver.WindowApplication.MaxHeight = System.Windows.SystemParameters.VirtualScreenHeight;
        }
    }

    if (System.Windows.SystemParameters.VirtualScreenLeft < 0)
    {
        //Primary Monitor is on the Right
        if (absoluteScreenPos.X > 0)
        {
            //Primary monitor
            _receiver.WindowApplication.MaxWidth = System.Windows.SystemParameters.WorkArea.Width;
            _receiver.WindowApplication.MaxHeight = System.Windows.SystemParameters.WorkArea.Height;
        }
        else
        {
            //Secondary monitor
            _receiver.WindowApplication.MaxWidth = System.Windows.SystemParameters.VirtualScreenWidth - System.Windows.SystemParameters.WorkArea.Width;
            _receiver.WindowApplication.MaxHeight = System.Windows.SystemParameters.VirtualScreenHeight;
        }
    }
}

1

In C # -Winforms habe ich einen Startpunkt (für den Fall, dass wir mehrere Monitore / Diplomaten haben und ein Formular einen anderen aufruft) mit Hilfe der folgenden Methode:

private Point get_start_point()
    {
        return
            new Point(Screen.GetBounds(parent_class_with_form.ActiveForm).X,
                      Screen.GetBounds(parent_class_with_form.ActiveForm).Y
                      );
    }

1

WinForms

Für Multi-Monitor-Setups benötigen Sie außerdem ein Konto für die X- und Y-Position:

Rectangle activeScreenDimensions = Screen.FromControl(this).Bounds;
this.Size = new Size(activeScreenDimensions.Width + activeScreenDimensions.X, activeScreenDimensions.Height + activeScreenDimensions.Y);

0

Dieser Debugging- Code sollte den Trick gut machen:

Sie können die Eigenschaften der Bildschirmklasse untersuchen

Fügen Sie alle Anzeigen mit Screen.AllScreens in ein Array oder eine Liste ein und erfassen Sie dann den Index der aktuellen Anzeige und ihre Eigenschaften.

Geben Sie hier die Bildbeschreibung ein

C # (von Telerik von VB konvertiert - bitte überprüfen)

        {
    List<Screen> arrAvailableDisplays = new List<Screen>();
    List<string> arrDisplayNames = new List<string>();

    foreach (Screen Display in Screen.AllScreens)
    {
        arrAvailableDisplays.Add(Display);
        arrDisplayNames.Add(Display.DeviceName);
    }

    Screen scrCurrentDisplayInfo = Screen.FromControl(this);
    string strDeviceName = Screen.FromControl(this).DeviceName;
    int idxDevice = arrDisplayNames.IndexOf(strDeviceName);

    MessageBox.Show(this, "Number of Displays Found: " + arrAvailableDisplays.Count.ToString() + Constants.vbCrLf + "ID: " + idxDevice.ToString() + Constants.vbCrLf + "Device Name: " + scrCurrentDisplayInfo.DeviceName.ToString + Constants.vbCrLf + "Primary: " + scrCurrentDisplayInfo.Primary.ToString + Constants.vbCrLf + "Bounds: " + scrCurrentDisplayInfo.Bounds.ToString + Constants.vbCrLf + "Working Area: " + scrCurrentDisplayInfo.WorkingArea.ToString + Constants.vbCrLf + "Bits per Pixel: " + scrCurrentDisplayInfo.BitsPerPixel.ToString + Constants.vbCrLf + "Width: " + scrCurrentDisplayInfo.Bounds.Width.ToString + Constants.vbCrLf + "Height: " + scrCurrentDisplayInfo.Bounds.Height.ToString + Constants.vbCrLf + "Work Area Width: " + scrCurrentDisplayInfo.WorkingArea.Width.ToString + Constants.vbCrLf + "Work Area Height: " + scrCurrentDisplayInfo.WorkingArea.Height.ToString, "Current Info for Display '" + scrCurrentDisplayInfo.DeviceName.ToString + "' - ID: " + idxDevice.ToString(), MessageBoxButtons.OK, MessageBoxIcon.Information);
}

VB (Originalcode)

 Dim arrAvailableDisplays As New List(Of Screen)()
    Dim arrDisplayNames As New List(Of String)()

    For Each Display As Screen In Screen.AllScreens
        arrAvailableDisplays.Add(Display)
        arrDisplayNames.Add(Display.DeviceName)
    Next

    Dim scrCurrentDisplayInfo As Screen = Screen.FromControl(Me)
    Dim strDeviceName As String = Screen.FromControl(Me).DeviceName
    Dim idxDevice As Integer = arrDisplayNames.IndexOf(strDeviceName)

    MessageBox.Show(Me,
                    "Number of Displays Found: " + arrAvailableDisplays.Count.ToString & vbCrLf &
                    "ID: " & idxDevice.ToString + vbCrLf &
                    "Device Name: " & scrCurrentDisplayInfo.DeviceName.ToString + vbCrLf &
                    "Primary: " & scrCurrentDisplayInfo.Primary.ToString + vbCrLf &
                    "Bounds: " & scrCurrentDisplayInfo.Bounds.ToString + vbCrLf &
                    "Working Area: " & scrCurrentDisplayInfo.WorkingArea.ToString + vbCrLf &
                    "Bits per Pixel: " & scrCurrentDisplayInfo.BitsPerPixel.ToString + vbCrLf &
                    "Width: " & scrCurrentDisplayInfo.Bounds.Width.ToString + vbCrLf &
                    "Height: " & scrCurrentDisplayInfo.Bounds.Height.ToString + vbCrLf &
                    "Work Area Width: " & scrCurrentDisplayInfo.WorkingArea.Width.ToString + vbCrLf &
                    "Work Area Height: " & scrCurrentDisplayInfo.WorkingArea.Height.ToString,
                    "Current Info for Display '" & scrCurrentDisplayInfo.DeviceName.ToString & "' - ID: " & idxDevice.ToString, MessageBoxButtons.OK, MessageBoxIcon.Information)

Bildschirmliste

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.