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.

chilltemp
quelle
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);
  }
}
Jeff Yates
quelle
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

Pyttroll
quelle
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 );
        }
R. Rusev
quelle
1
Können Sie die tatsächliche Bildschirmgröße ermitteln, wenn der Skalierungsfaktor Ihrer Fenster vorhanden ist (100% / 125% / 150% / 200%)?
Kiquenet
12

Add zu ffpf

Screen.FromControl(this).Bounds
fehlerhaft
quelle
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
aDoubleSo
quelle
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();
Andre
quelle
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

Nasenbaer
quelle
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;
        }
    }
}
Ricardo Magalhães
quelle
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
                      );
    }
Oleg Bash
quelle
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);
user3424480
quelle
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

Daniel Santos
quelle