Làm cách nào để có được kích thước màn hình hoạt động?


142

Những gì tôi đang tìm kiếm là tương đương với System.Windows.SystemParameters.WorkArea với màn hình mà cửa sổ hiện đang bật.

Làm rõ: Cửa sổ trong câu hỏi là WPF, không WinForm.


2
Thay đổi câu trả lời được chấp nhận để phản ánh cách tốt nhất để làm điều này từ WPF. System.Windows.SystemParameter. *
chilltemp

1
Nỗi ám ảnh về việc không sử dụng không gian tên WinForms có vẻ xa lạ đối với tôi, nó không mang lại cho bạn bất cứ điều gì; thay vào đó, nó khiến bạn không có các công cụ cần thiết để giải quyết vấn đề.
Jeff Yates

4
Đối với tôi, đó không phải là về WinForms so với WPF. Đó là về việc học một cái gì đó mới. Tôi không thể quyết định cách nào tốt hơn nếu tôi không học cả hai cách.
chilltemp

3
Chà, trong kịch bản này không có "cả hai cách" vì chỉ có một cách để làm điều này, đó là sử dụng công cụ WinForms.
Jeff Yates

@Jeff Yates: Bạn đúng. Tôi đã đào dự án ban đầu mà tôi đã hỏi câu hỏi này và thấy rằng tôi đã sử dụng các thuộc tính PrimaryScreen *. Họ đã giải quyết nhu cầu của tôi trong ngày, nhưng không phải là câu hỏi thực tế tôi đã hỏi. Xin lỗi vì đã chạy vòng quanh; Tôi đã thay đổi câu trả lời được chấp nhận cho phù hợp.
chilltemp

Câu trả lời:


143

Screen.FromControl, Screen.FromPointScreen.FromRectanglesẽ giúp bạn với điều này. Ví dụ: trong WinForms, nó sẽ là:

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

Tôi không biết về một cuộc gọi tương đương cho WPF. Do đó, bạn cần phải làm một cái gì đó như phương pháp mở rộng này.

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

1
Có lẽ việc gắn thẻ của tôi không làm rõ rằng tôi đang sử dụng các cửa sổ WPF chứ không phải WinForms. Tôi không có tham chiếu System.Windows.Forms.dll và dù sao nó cũng không hoạt động vì WPF có cây thừa kế riêng.
chilltemp

1
Không có gì. Tôi xin lỗi vì đã không đi thẳng vào câu trả lời - Tôi đã phải điều tra những gì có sẵn trong WPF trước khi tôi cập nhật bài viết của mình.
Jeff Yates

Điều này hoạt động để đặt một cửa sổ ở cạnh bên phải: var bound = this.GetScreen (). WorkArea; this.Left = Bound.Right - this.Width; Nhưng nó yêu cầu tham chiếu đến System.Windows.Forms và System.Drawing, không lý tưởng.
Anthony

1
@devios Coi chừng cuộc gọi này không nhận biết DPI; bạn sẽ cần phải tính toán.
Lynn sụp đổ

6
Trong VS 2015 WPF nhắm mục tiêu NET 4.5 trên hệ thống 4-màn hình của tôi trên Windows 10 Pro (v10.0.14393) với ứng dụng của tôi windowtrên màn hình ở trên của Chánh không (ví dụ, nó Top < 0), FromHandletrả lại Screencho màn hình tiểu của (mặc dù tôi windowhoàn toàn trong vòng màn hình phụ)!?! Thở dài. Có vẻ như tôi sẽ phải tự tìm kiếm Screen.AllScreensArray. Tại sao những thứ "không thể làm việc"?!? Arrrrgh.
Tom

62

Bạn có thể sử dụng điều này để có được giới hạn không gian làm việc của màn hình chính:

System.Windows.SystemParameters.WorkArea

Điều này cũng hữu ích để chỉ lấy kích thước của màn hình chính:

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


19
Tôi bối rối ... Điều này dường như chỉ để trả về kích thước màn hình chính. Tôi muốn biết kích thước của màn hình hiện tại cửa sổ đang ở ...
VitalyB

1
điều này không trả lời câu hỏi và ngay cả khi bạn chỉ muốn lấy kích thước của màn hình chính thì SystemParameter (trong WPF) không chính xác. họ trả lại các đơn vị thiết bị độc lập và không phải pixel. để thực hiện tốt hơn, hãy xem câu trả lời này: stackoverflow.com/questions/254197/ Khăn
Patrick Klug

1
PrimaryScreenHeight / Width hoạt động chính xác như mong đợi và MSDN có thông tin sau: "Nhận giá trị cho biết chiều cao màn hình, tính bằng pixel, của màn hình hiển thị chính." WorkArea không nói cụ thể về pixel, nhưng các ví dụ về tài liệu và cách sử dụng khiến tôi tin rằng nó cũng bằng pixel. Bạn có một liên kết đến một cái gì đó chỉ ra việc sử dụng các đơn vị độc lập thiết bị?
chilltemp


17

Thêm một giải pháp không sử dụng WinForms mà thay vào đó là NativeMethods. Đầu tiên bạn cần xác định các phương thức riêng cần thiết.

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

Và sau đó lấy tay cầm màn hình và thông tin màn hình như thế này.

        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
Bạn có thể có được kích thước màn hình thực nếu có hệ số tỷ lệ của các cửa sổ của bạn (100% / 125% / 150% / 200%) không?
Kiquenet


12

Cảnh giác với hệ số tỷ lệ của các cửa sổ của bạn (100% / 125% / 150% / 200%). Bạn có thể lấy kích thước màn hình thực bằng cách sử dụng mã sau:

SystemParameters.FullPrimaryScreenHeight
SystemParameters.FullPrimaryScreenWidth

1
Đó là cho màn hình chính - điều gì sẽ xảy ra nếu cửa sổ ứng dụng của bạn nằm trên màn hình ảo (mở rộng) (tức là bạn có một hoặc hai màn hình ngoài được gắn vào PC)?
Matt

4

Tôi muốn có độ phân giải màn hình trước khi mở cửa sổ đầu tiên, vì vậy đây là giải pháp nhanh để mở cửa sổ vô hình trước khi thực sự đo kích thước màn hình (bạn cần điều chỉnh các tham số cửa sổ với cửa sổ của mình để đảm bảo cả hai đều mở cùng một màn hình - chủ yếu WindowStartupLocationlà quan trọng)

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

Đây là " Giải pháp DotNet 4.5 trên màn hình trung tâm ", sử dụng SystemParameter thay vì System.Windows.Forms hoặc My.Compuer.Screen : Vì Windows 8 đã thay đổi cách tính kích thước màn hình, cách duy nhất nó hoạt động đối với tôi (tính toán trên thanh tác vụ bao gồm):

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

Màn hình trung tâm WPF XAML


cài đặt cài đặt trong WPF?
Kiquenet

Câu hỏi chính là về vị trí màn hình. Giống như trình cài đặt Msi, Innosetup hoặc các trình cài đặt khác, tôi đã tạo trình cài đặt của riêng mình với kiểm tra CPU, kiểm tra quyền, xác minh trình điều khiển và nhiều hơn nữa, rất đơn giản để sử dụng. Đó là ảnh chụp màn hình về.
Nasenbaer

3

Tôi cần phải đặt kích thước tối đa của ứng dụng cửa sổ của mình. Điều này có thể thay đổi cho phù hợp ứng dụng được hiển thị trong màn hình chính hoặc trong phụ. Để khắc phục vấn đề này, tôi đã tạo ra một phương pháp đơn giản mà tôi sẽ chỉ cho bạn tiếp theo:

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

trong winforms C # tôi đã có điểm bắt đầu (đối với trường hợp khi chúng tôi có một số màn hình / bằng tốt nghiệp và một hình thức đang gọi một hình thức khác) với sự trợ giúp của phương pháp sau:

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

Đối với thiết lập nhiều màn hình, bạn cũng sẽ cần tài khoản cho vị trí X và Y:

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

0

Gỡ lỗi nàyMã nên thực hiện thủ thuật tốt:

Bạn có thể khám phá các thuộc tính của Lớp màn hình

Đặt tất cả các màn hình vào một mảng hoặc danh sách bằng Screen.AllScreen sau đó nắm bắt chỉ mục của màn hình hiện tại và các thuộc tính của nó.

nhập mô tả hình ảnh ở đây

C # (Được chuyển đổi từ VB bởi Telerik - Vui lòng kiểm tra lại)

        {
    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 (Mã gốc)

 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)

Danh sách màn hình

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.