Bagaimana saya bisa mendapatkan dimensi layar aktif?

142

Apa yang saya cari sama System.Windows.SystemParameters.WorkAreadengan monitor yang sedang aktif di jendela.

Klarifikasi: Jendela yang dimaksud adalah WPF, bukan WinForm.

chilltemp
sumber
2
Mengubah jawaban yang diterima untuk mencerminkan cara terbaik untuk melakukan ini dari WPF. System.Windows.SystemParameters. *
chilltemp
1
Obsesi untuk tidak menggunakan namespace WinForms tampaknya aneh bagi saya, itu tidak memberi Anda apa-apa; sebaliknya, ia meninggalkan Anda tanpa alat yang Anda butuhkan untuk menyelesaikan masalah dengan benar.
Jeff Yates
4
Bagi saya, ini bukan tentang WinForms vs WPF. Ini tentang mempelajari sesuatu yang baru. Saya tidak bisa memutuskan jalan mana yang lebih baik jika saya tidak belajar keduanya.
chilltemp
3
Nah, dalam skenario ini tidak ada "dua arah" karena hanya ada satu cara untuk melakukan ini, yaitu menggunakan barang-barang WinForms.
Jeff Yates
@ Jeff Yates: Anda benar. Saya menggali proyek asli yang saya ajukan pertanyaan ini, dan menemukan bahwa saya menggunakan properti PrimaryScreen *. Mereka memecahkan kebutuhan saya hari itu, tetapi bukan pertanyaan sebenarnya yang saya tanyakan. Maaf atas kesalahannya; Saya telah mengubah jawaban yang diterima sesuai.
chilltemp

Jawaban:

143

Screen.FromControl, Screen.FromPointdan Screen.FromRectangleakan membantu Anda dengan ini. Sebagai contoh di WinForms adalah:

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

Saya tidak tahu panggilan setara untuk WPF. Karena itu, Anda perlu melakukan sesuatu seperti metode ekstensi ini.

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
sumber
1
Mungkin penandaan saya tidak menjelaskan bahwa saya menggunakan windows WPF, bukan WinForms. Saya tidak memiliki referensi System.Windows.Forms.dll, dan itu tidak akan berhasil karena WPF memiliki pohon warisannya sendiri.
chilltemp
1
Sama-sama. Permintaan maaf saya karena tidak langsung menjawabnya - saya harus menyelidiki apa yang tersedia di WPF sebelum saya memperbarui posting saya.
Jeff Yates
Ini berfungsi untuk meletakkan jendela di tepi kanan: var bounds = this.GetScreen (). WorkingArea; this.Left = bounds.Right - this.Width; Tetapi membutuhkan referensi untuk System.Windows.Forms dan System.Drawing, yang tidak ideal.
Anthony
1
@devios Berhati-hatilah bahwa panggilan ini tidak menyadari DPI; Anda harus melakukan perhitungan.
Lynn Crumbling
6
Dalam saya VS 2015 WPF aplikasi menargetkan NET 4.5 pada sistem 4-monitor saya pada Windows 10 Pro (v10.0.14393) dengan windowmonitor di atas Primer saya (misalnya, yang Top < 0), FromHandlemengembalikan Screenmonitor Primer saya (meskipun windowitu benar-benar dalam monitor Sekunder)!?! Mendesah. Sepertinya saya harus mencari Screen.AllScreenssendiri Array. Mengapa hal-hal "tidak berfungsi"?!? Arrrrgh.
Tom
62

Anda dapat menggunakan ini untuk mendapatkan batas ruang kerja desktop dari layar utama:

System.Windows.SystemParameters.WorkArea

Ini juga berguna untuk mendapatkan ukuran layar utama:

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

Pyttroll
sumber
19
Saya bingung ... Ini sepertinya hanya mengembalikan dimensi layar utama. Saya ingin tahu dimensi layar saat ini di jendela ...
VitalyB
1
ini tidak menjawab pertanyaan dan bahkan jika Anda hanya ingin mendapatkan ukuran tampilan utama, SystemParameters (dalam WPF) salah. mereka mengembalikan unit perangkat independen dan bukan piksel. untuk implementasi yang lebih baik lihat jawaban ini: stackoverflow.com/questions/254197/…
Patrick Klug
1
PrimaryScreenHeight / Width bekerja persis seperti yang diharapkan, dan MSDN memiliki yang berikut pada mereka: "Mendapat nilai yang menunjukkan ketinggian layar, dalam piksel, dari monitor tampilan utama." WorkArea tidak secara khusus mengatakan piksel, tetapi dokumentasi dan contoh penggunaan membuat saya percaya bahwa itu juga dalam piksel. Apakah Anda memiliki tautan ke sesuatu yang menunjukkan penggunaan unit independen perangkat?
chilltemp
17

Menambahkan solusi yang tidak menggunakan WinForms tetapi NativeMethods sebagai gantinya. Pertama, Anda perlu mendefinisikan metode asli yang dibutuhkan.

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

Dan kemudian dapatkan pegangan monitor dan info monitor seperti ini.

        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
sumber
1
Bisakah Anda mendapatkan ukuran layar nyata jika ada faktor skala windows Anda (100% / 125% / 150% / 200%)?
Kiquenet
12

Tambahkan ke ffpf

Screen.FromControl(this).Bounds
salah
sumber
12

Waspadai faktor skala jendela Anda (100% / 125% / 150% / 200%). Anda bisa mendapatkan ukuran layar nyata dengan menggunakan kode berikut:

SystemParameters.FullPrimaryScreenHeight
SystemParameters.FullPrimaryScreenWidth
aDoubleSo
sumber
1
Itu untuk layar utama - bagaimana jika jendela aplikasi Anda berada di layar virtual (diperluas) (yaitu Anda memiliki satu atau dua monitor eksternal yang terpasang pada PC Anda)?
Mat
4

Saya ingin memiliki resolusi layar sebelum membuka jendela pertama saya, jadi di sini solusi cepat untuk membuka jendela tak terlihat sebelum benar-benar mengukur dimensi layar (Anda perlu menyesuaikan parameter jendela ke jendela Anda untuk memastikan bahwa keduanya terbuka pada layar yang sama - terutama yang WindowStartupLocationpenting)

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
sumber
3

Ini adalah " solusi Tengah Layar DotNet 4.5 ", menggunakan SystemParameters bukan System.Windows.Forms atau My.Compuer.Screen : Karena Windows 8 telah mengubah perhitungan dimensi layar, satu-satunya cara kerjanya bagi saya terlihat seperti itu (perhitungan Taskbar) termasuk):

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

Layar Tengah WPF XAML

Nasenbaer
sumber
pengaturan installer di WPF?
Kiquenet
Pertanyaan utamanya adalah tentang posisi layar. Seperti installer Msi, Innosetup atau yang lain, saya membuat installer saya sendiri dengan pemeriksaan CPU, pemeriksaan izin, verifikasi driver dan banyak lagi, sangat mudah digunakan. Thats screenshot tentang.
Nasenbaer
3

Saya perlu mengatur ukuran maksimum aplikasi jendela saya. Yang satu ini bisa berubah sesuai dengan aplikasi yang ditunjukkan di layar utama atau di layar sekunder. Untuk mengatasi masalah ini, kami membuat metode sederhana yang saya tunjukkan selanjutnya:

/// <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
sumber
1

di C # winforms saya sudah mendapatkan titik awal (untuk kasus ketika kita memiliki beberapa monitor / diplay dan satu formulir memanggil yang lain) dengan bantuan metode berikut:

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
sumber
1

WinForms

Untuk pengaturan multi-monitor, Anda juga memerlukan akun untuk posisi X dan Y:

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

Kode debug ini harus melakukan trik dengan baik:

Anda dapat menjelajahi properti dari Kelas Layar

Letakkan semua display dalam array atau daftar menggunakan Screen.AllScreens lalu ambil indeks tampilan saat ini dan propertinya.

masukkan deskripsi gambar di sini

C # (Dikonversi dari VB oleh Telerik - Silakan periksa kembali)

        {
    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 (kode asli)

 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)

Daftar Layar

Daniel Santos
sumber