Jak mogę uzyskać aktywne wymiary ekranu?

142

To, czego szukam, jest odpowiednikiem System.Windows.SystemParameters.WorkAreamonitora, na którym aktualnie jest wyświetlane okno.

Wyjaśnienie: okno, o którym mowa WPF, nie WinForm.

chilltemp
źródło
2
Zmieniono zaakceptowaną odpowiedź, aby odzwierciedlić najlepszy sposób zrobienia tego z WPF. System.Windows.SystemParameters. *
chilltemp
1
Obsesja na punkcie nieużywania przestrzeni nazw WinForms wydaje mi się dziwna, nic nie daje; zamiast tego pozostawia Cię bez narzędzi potrzebnych do prawidłowego rozwiązania problemu.
Jeff Yates,
4
Dla mnie nie chodzi o WinForms vs. WPF. Chodzi o nauczenie się czegoś nowego. Nie mogę zdecydować, który sposób jest lepszy, jeśli nie nauczę się obu sposobów.
chilltemp
3
Cóż, w tym scenariuszu nie ma „obu sposobów”, ponieważ jest tylko jeden sposób, aby to zrobić, a mianowicie użycie elementów WinForms.
Jeff Yates,
@Jeff Yates: Masz rację. Wykopałem oryginalny projekt, dla którego zadałem to pytanie, i stwierdziłem, że użyłem właściwości PrimaryScreen *. Rozwiązali moje potrzeby dnia, ale nie pytanie, które zadałem. Przepraszam za bieganie; Odpowiednio zmieniłem zaakceptowaną odpowiedź.
chilltemp

Odpowiedzi:

143

Screen.FromControl, Screen.FromPointI Screen.FromRectanglepowinien w tym pomóc. Na przykład w WinForms byłoby to:

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

Nie znam równoważnego wywołania WPF. Dlatego musisz zrobić coś takiego jak ta metoda rozszerzenia.

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
źródło
1
Być może moje tagowanie nie wyjaśniło, że używam okien WPF, a nie WinForms. Nie mam odwołania do System.Windows.Forms.dll, a mimo to nie zadziała, ponieważ WPF ma własne drzewo dziedziczenia.
chilltemp
1
Nie ma za co. Przepraszam, że nie otrzymałem od razu odpowiedzi - musiałem sprawdzić, co było dostępne w WPF, zanim zaktualizowałem mój post.
Jeff Yates,
Działa to w celu umieszczenia okna na prawej krawędzi: var bounds = this.GetScreen (). WorkingArea; this.Left = bounds.Right - this.Width; Ale wymaga odwołań do System.Windows.Forms i System.Drawing, co nie jest idealne.
Anthony
1
@devios Uwaga, to wywołanie nie obsługuje DPI; będziesz musiał wykonać obliczenia.
Lynn Crumbling
6
W mojej aplikacji WPF VS 2015 kierowania .NET 4.5 w moim systemie 4-monitora w systemie Windows 10 Pro (v10.0.14393) z windowmonitora nad moim głównym (np ITS Top < 0), FromHandlepowrócił Screendo mojego głównego monitora (choć windowbył całkowicie w ciągu monitor pomocniczy)!?! Westchnienie. Wygląda na to, że będę musiał sam przeszukać Screen.AllScreensArray. Dlaczego rzeczy nie mogą „po prostu działać”?!? Arrrrgh.
Tom
62

Możesz użyć tego, aby uzyskać granice obszaru roboczego pulpitu na ekranie głównym:

System.Windows.SystemParameters.WorkArea

Jest to również przydatne do uzyskania rozmiaru ekranu głównego:

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

Pyttroll
źródło
19
Jestem zdezorientowany… To wydaje się zwracać tylko podstawowe wymiary ekranu. Chcę poznać wymiary ekranu, w którym obecnie znajduje się okno ...
WitalijB
1
nie odpowiada to na pytanie, a nawet jeśli chcesz tylko uzyskać rozmiar podstawowego wyświetlacza, parametry SystemParameters (w WPF) są niepoprawne. zwracają jednostki niezależne od urządzenia, a nie piksele. aby uzyskać lepszą implementację, zobacz tę odpowiedź: stackoverflow.com/questions/254197/ ...
Patrick Klug,
1
PrimaryScreenHeight / Width działały dokładnie zgodnie z oczekiwaniami, a MSDN zawiera następujące informacje: „Pobiera wartość wskazującą wysokość ekranu głównego monitora w pikselach”. WorkArea nie mówi konkretnie o pikselach, ale dokumentacja i przykłady użycia pozwalają mi uwierzyć, że jest to również piksele. Czy masz link do czegoś wskazującego na użycie jednostek niezależnych od urządzenia?
chilltemp
17

Dodanie rozwiązania, które nie używa WinForms, ale zamiast tego NativeMethods. Najpierw musisz zdefiniować potrzebne metody natywne.

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

A następnie zdobądź uchwyt monitora i takie informacje o monitorze.

        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
źródło
1
Czy możesz uzyskać rzeczywisty rozmiar ekranu, jeśli istnieją współczynniki skali twoich okien (100% / 125% / 150% / 200%)?
Kiquenet
12

Dodaj do ffpf

Screen.FromControl(this).Bounds
wadliwy
źródło
12

Uważaj na współczynnik skalowania swoich okien (100% / 125% / 150% / 200%). Możesz uzyskać rzeczywisty rozmiar ekranu, używając następującego kodu:

SystemParameters.FullPrimaryScreenHeight
SystemParameters.FullPrimaryScreenWidth
aDoubleSo
źródło
1
Dotyczy to ekranu głównego - co, jeśli okno aplikacji znajduje się na wirtualnym (rozszerzonym) ekranie (tj. Masz jeden lub dwa zewnętrzne monitory podłączone do komputera)?
Matt
4

Chciałem mieć rozdzielczość ekranu przed otwarciem pierwszego z moich okien, więc tutaj szybkie rozwiązanie, aby otworzyć niewidoczne okno przed faktycznym pomiarem wymiarów ekranu (musisz dostosować parametry okna do swojego okna, aby upewnić się, że oba są otwarte ten sam ekran - przede wszystkim WindowStartupLocationważny)

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
źródło
3

To jest " rozwiązanie DotNet 4.5 ekranu centralnego ", używające SystemParameters zamiast System.Windows.Forms lub My.Compuer.Screen : Ponieważ Windows 8 zmienił obliczanie wymiarów ekranu, jedyny sposób, w jaki to działa dla mnie wygląda tak (Obliczanie paska zadań w zestawie):

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

Środkowy ekran WPF XAML

Nasenbaer
źródło
instalacja instalatora w WPF?
Kiquenet
Główne pytanie dotyczy pozycji ekranu. Podobnie jak instalator Msi, Innosetup lub inne, stworzyłem własny instalator z kontrolą procesora, kontrolą uprawnień, weryfikacją sterowników i wieloma innymi, bardzo prostymi w użyciu. O tym jest zrzut ekranu.
Nasenbaer
3

Musiałem ustawić maksymalny rozmiar mojej aplikacji okiennej. Ten można odpowiednio zmienić, aplikacja jest wyświetlana na głównym ekranie lub w drugim. Aby rozwiązać ten problem, stworzyliśmy prostą metodę, którą pokażę dalej:

/// <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
źródło
1

w C # winforms mam punkt startowy (w przypadku gdy mamy kilka monitorów / diplay i jeden formularz wywołuje inny) za pomocą następującej metody:

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
źródło
1

WinForms

W przypadku konfiguracji z wieloma monitorami konieczne będzie również uwzględnienie pozycji X i Y:

Rectangle activeScreenDimensions = Screen.FromControl(this).Bounds;
this.Size = new Size(activeScreenDimensions.Width + activeScreenDimensions.X, activeScreenDimensions.Height + activeScreenDimensions.Y);
user3424480
źródło
0

Ten kod debugujący powinien dobrze załatwić sprawę:

Możesz zbadać właściwości klasy ekranu

Umieść wszystkie ekrany w tablicy lub liście za pomocą Screen.AllScreens, a następnie przechwyć indeks bieżącego ekranu i jego właściwości.

wprowadź opis obrazu tutaj

C # (przekonwertowany z VB przez Telerik - sprawdź dokładnie)

        {
    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 (oryginalny kod)

 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)

Lista ekranów

Daniel Santos
źródło