Come posso ottenere le dimensioni dello schermo attive?


142

Quello che sto cercando è l'equivalente di System.Windows.SystemParameters.WorkAreaper il monitor su cui la finestra è attualmente attiva.

Chiarimento: la finestra in questione è WPFno WinForm.


2
Modificata la risposta accettata per riflettere il modo migliore per farlo da WPF. System.Windows.SystemParameters. *
chilltemp

1
L'ossessione di non usare uno spazio dei nomi WinForms mi sembra strano, non ti guadagna nulla; invece, ti lascia senza gli strumenti necessari per risolvere correttamente il problema.
Jeff Yates,

4
Per me, non si tratta di WinForms vs. WPF. Si tratta di imparare qualcosa di nuovo. Non riesco a decidere quale sia la strada migliore se non imparo in entrambi i modi.
Chilltemp,

3
Bene, in questo scenario non esistono "entrambi i modi" in quanto esiste un solo modo per farlo, che è quello di usare la roba WinForms.
Jeff Yates,

@Jeff Yates: hai ragione. Ho scavato il progetto originale per cui ho posto questa domanda e ho scoperto che ho usato le proprietà PrimaryScreen *. Hanno risolto i miei bisogni del giorno, ma non la vera domanda che ho posto. Ci scusiamo per il run-around; Ho modificato la risposta accettata di conseguenza.
Chilltemp,

Risposte:


143

Screen.FromControl, Screen.FromPointE Screen.FromRectangledovrebbe aiutare con questo. Ad esempio in WinForms sarebbe:

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

Non conosco una chiamata equivalente per WPF. Pertanto, devi fare qualcosa di simile a questo metodo di estensione.

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

1
Forse il mio tagging non ha chiarito che sto usando Windows WPF, non WinForms. Non ho il riferimento System.Windows.Forms.dll e non funzionerebbe comunque poiché WPF ha il suo albero di ereditarietà.
Chilltemp,

1
Prego. Mi scuso per non essere arrivato direttamente alla risposta: ho dovuto indagare su ciò che era disponibile in WPF prima di aggiornare il mio post.
Jeff Yates,

Questo funziona per mettere una finestra sul bordo destro: var bounds = this.GetScreen (). WorkingArea; this.Left = bounds.Right - this.Width; Ma richiede riferimenti a System.Windows.Forms e System.Drawing, che non è l'ideale.
Anthony,

1
@devios Attenzione che questa chiamata non è compatibile con DPI; dovrai fare calcoli.
Lynn che si sbriciola il

6
Nella mia app WPF di VS 2015 destinata a .NET 4.5 sul mio sistema a 4 monitor su Windows 10 Pro (v10.0.14393) con windowsul monitor sopra quello della mia Primaria (ad esempio, il suo Top < 0), ha FromHandlerestituito il Screenmonitor per il mio Primario (anche se windowera completamente all'interno il monitor secondario)!?! Sospiro. Sembra che dovrò cercare l' Screen.AllScreensArray da solo. Perché le cose non "funzionano"?!? Arrrrgh.
Tom,

62

Puoi usarlo per ottenere i limiti dell'area di lavoro desktop della schermata principale:

System.Windows.SystemParameters.WorkArea

Questo è utile anche per ottenere solo le dimensioni dello schermo principale:

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


19
Sono confuso ... Questo sembra solo restituire le dimensioni dello schermo principale. Voglio sapere le dimensioni dello schermo in cui la finestra si trova attualmente ...
VitalyB,

1
questo non risponde alla domanda e anche se si desidera solo ottenere le dimensioni del display principale, i parametri di sistema (in WPF) non sono corretti. restituiscono unità indipendenti dal dispositivo e non pixel. per una migliore implementazione vedere questa risposta: stackoverflow.com/questions/254197/…
Patrick Klug,

1
PrimaryScreenHeight / Width ha funzionato esattamente come previsto e MSDN ha le seguenti caratteristiche: "Ottiene un valore che indica l'altezza dello schermo, in pixel, del monitor principale." WorkArea non dice specificamente i pixel, ma la documentazione e gli esempi di utilizzo mi portano a credere che sia anche in pixel. Hai un link a qualcosa che indica l'uso di unità indipendenti dal dispositivo?
Chilltemp,


17

Aggiunta di una soluzione che non utilizza WinForms ma NativeMethods. Innanzitutto è necessario definire i metodi nativi necessari.

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

E quindi ottenere la maniglia del monitor e le informazioni del monitor in questo modo.

        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
Puoi ottenere le dimensioni reali dello schermo se ci sono fattori di scala delle tue finestre (100% / 125% / 150% / 200%)?
Kiquenet,


12

Fai attenzione al fattore di scala delle tue finestre (100% / 125% / 150% / 200%). È possibile ottenere le dimensioni reali dello schermo utilizzando il seguente codice:

SystemParameters.FullPrimaryScreenHeight
SystemParameters.FullPrimaryScreenWidth

1
Questo è per lo schermo principale: cosa succede se la finestra dell'app si trova su uno schermo virtuale (esteso) (ovvero se hai uno o due monitor esterni collegati al tuo PC)?
Matt

4

Volevo avere la risoluzione dello schermo prima di aprire la prima delle mie finestre, quindi qui una soluzione rapida per aprire una finestra invisibile prima di misurare effettivamente le dimensioni dello schermo (è necessario adattare i parametri della finestra alla finestra per assicurarsi che entrambi siano aperti lo stesso schermo - principalmente WindowStartupLocationè importante)

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

Questa è una "soluzione Center Dot Dot 4.5 4.5 ", che utilizza SystemParameters anziché System.Windows.Forms o My.Compuer.Screen : poiché Windows 8 ha modificato il calcolo delle dimensioni dello schermo, l'unico modo in cui funziona per me è simile a quello (calcolo della barra delle applicazioni incluso):

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

Schermo centrale WPF XAML


installazione del programma di installazione in WPF?
Kiquenet,

La domanda principale riguarda la posizione dello schermo. Come il programma di installazione Msi, Innosetup o altri, ho creato il mio programma di installazione con controllo CPU, controllo autorizzazioni, verifica driver e molto altro, molto semplice da usare. Questo è lo screenshot di.
Nasenbaer,

3

Avevo bisogno di impostare la dimensione massima della mia applicazione per finestre. Questo potrebbe cambiare di conseguenza l'applicazione è stata mostrata nella schermata principale o nella schermata secondaria. Per ovviare a questo problema, abbiamo creato un metodo semplice che ti mostro in seguito:

/// <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 winform C # ho il punto di partenza (nel caso in cui abbiamo diversi monitor / diplay e un modulo ne chiama un altro) con l'aiuto del seguente metodo:

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

Per le configurazioni multi-monitor dovrai anche tenere conto della posizione X e Y:

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

0

Questo codice di debug dovrebbe fare bene il trucco:

Puoi esplorare le proprietà della classe schermo

Metti tutti i display in un array o in un elenco usando Screen.AllScreens quindi acquisisce l'indice del display corrente e le sue proprietà.

inserisci qui la descrizione dell'immagine

C # (Convertito da VB da Telerik - Per favore ricontrolla)

        {
    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 (codice originale)

 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)

Elenco schermate

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.