ฉันจะรับขนาดหน้าจอที่ใช้งานอยู่ได้อย่างไร?


142

สิ่งที่ฉันกำลังมองหาคือสิ่งที่เทียบเท่าSystem.Windows.SystemParameters.WorkAreaกับจอภาพที่หน้าต่างเปิดอยู่

ชี้แจง: หน้าต่างในคำถามคือไม่WPFWinForm


2
เปลี่ยนคำตอบที่ยอมรับเพื่อสะท้อนวิธีที่ดีที่สุดในการทำเช่นนี้จาก WPF System.Windows.SystemParameters. *
chilltemp

1
ความหลงใหลในการไม่ใช้เนมสเปซ WinForms ดูแปลกสำหรับฉันมันไม่ได้อะไรเลย แต่จะทำให้คุณไม่มีเครื่องมือที่จำเป็นในการแก้ปัญหาอย่างถูกต้อง
Jeff Yates

4
สำหรับฉันมันไม่เกี่ยวกับ WinForms vs. WPF มันเกี่ยวกับการเรียนรู้สิ่งใหม่ ฉันไม่สามารถตัดสินใจได้ว่าวิธีไหนดีกว่าถ้าฉันไม่เรียนรู้ทั้งสองวิธี
chilltemp

3
ในสถานการณ์นี้ไม่มี "ทั้งสองวิธี" เนื่องจากมีวิธีเดียวเท่านั้นที่จะทำเช่นนี้ซึ่งก็คือการใช้ WinForms
Jeff Yates

@Jeff Yates: คุณถูกต้อง ฉันขุดโครงการดั้งเดิมที่ฉันถามคำถามนี้และพบว่าฉันใช้คุณสมบัติ PrimaryScreen * พวกเขาแก้ไขความต้องการของฉันในวันนี้ แต่ไม่ใช่คำถามจริงที่ฉันถาม ขออภัยสำหรับรอบการทำงาน ฉันเปลี่ยนคำตอบที่ยอมรับแล้ว
chilltemp

คำตอบ:


143

Screen.FromControl, Screen.FromPointและScreen.FromRectangleจะช่วยให้คุณมีนี้ ตัวอย่างเช่นใน WinForms มันจะเป็น:

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

ฉันไม่รู้การเรียก WPF ที่เทียบเท่ากัน ดังนั้นคุณต้องทำอะไรเช่นวิธีการขยายนี้

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

1
บางทีการติดแท็กของฉันไม่ได้ทำให้ชัดเจนว่าฉันใช้ WPF windows ไม่ใช่ WinForms ฉันไม่มี System.Windows.Forms.dll อ้างอิงและมันจะไม่ทำงานต่อไปเนื่องจาก WPF มีแผนผังการสืบทอดของตัวเอง
chilltemp

1
ไม่เป็นไร คำขอโทษของฉันที่ไม่ตรงกับคำตอบ - ฉันต้องตรวจสอบสิ่งที่มีอยู่ใน WPF ก่อนที่จะอัปเดตโพสต์ของฉัน
Jeff Yates

การทำงานนี้จะวางหน้าต่างไว้ที่ขอบด้านขวา: var bounds = this.GetScreen () WorkingArea; this.Left = bounds.Right - this.Width; แต่มันต้องมีการอ้างอิงถึง System.Windows.Forms และ System.Drawing ซึ่งไม่เหมาะ
Anthony

1
@devios ระวังว่าการโทรนี้ไม่ใช่การรับรู้ DPI คุณจะต้องทำการคำนวณ
Lynn Crumbling

6
ในของฉัน VS 2015 WPF แอปกำหนดเป้าหมาย .NET 4.5 ในระบบ 4 ตรวจสอบของฉันบน Windows 10 Pro (v10.0.14393) กับwindowบนจอภาพด้านบนของหลักของฉัน (เช่นของมันTop < 0) FromHandleกลับมาScreenสำหรับจอแสดงผลหลักของฉัน (แม้ว่าwindowเป็นอย่างสมบูรณ์ภายใน จอแสดงผลรอง)!?! ถอนหายใจ ดูเหมือนว่าฉันจะต้องค้นหาScreen.AllScreensอาร์เรย์ด้วยตัวเอง เหตุใดสิ่งที่ "เพิ่งใช้งานไม่ได้"?! Arrrrgh
ทอม

62

คุณสามารถใช้สิ่งนี้เพื่อรับขอบเขตพื้นที่ทำงานเดสก์ท็อปของหน้าจอหลัก:

System.Windows.SystemParameters.WorkArea

สิ่งนี้ยังมีประโยชน์ในการเพิ่มขนาดหน้าจอหลัก:

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


19
ฉันสับสน ... ดูเหมือนว่าจะส่งคืนขนาดหน้าจอหลักเท่านั้น ฉันต้องการทราบขนาดของหน้าจอหน้าต่างปัจจุบันที่ ...
VitalyB

1
นี่ไม่ตอบคำถามและแม้ว่าคุณเพียงต้องการให้ขนาดของจอแสดงผลหลักที่ SystemParameters (ใน WPF) ไม่ถูกต้อง พวกเขาคืนหน่วยอุปกรณ์อิสระและไม่พิกเซล สำหรับการใช้งานที่ดีขึ้นดูคำตอบนี้: stackoverflow.com/questions/254197/…
Patrick Klug

1
PrimaryScreenHeight / Width ทำงานได้อย่างที่คาดไว้และ MSDN มีสิ่งต่อไปนี้: "ได้รับค่าที่ระบุความสูงของหน้าจอเป็นพิกเซลของจอแสดงผลหลัก" WorkArea ไม่ได้บอกว่าพิกเซลเป็นพิเศษ แต่ตัวอย่างเอกสารและการใช้งานทำให้ฉันเชื่อว่ามันเป็นพิกเซลเช่นกัน คุณมีลิงค์ไปยังสิ่งที่ระบุถึงการใช้งานของอุปกรณ์ที่เป็นอิสระหรือไม่?
chilltemp

34

นอกจากนี้คุณอาจต้อง:

เพื่อให้ได้ขนาดที่รวมกันของจอภาพทั้งหมดและไม่ใช่ขนาดเดียว


1
คำแนะนำ:ในการใช้งานนั้นจำเป็นต้องเพิ่มการอ้างอิงPresentationFramework.dllและusing System.Windows;
แมตต์

17

การเพิ่มโซลูชันที่ไม่ได้ใช้ WinForms แต่เป็น NativeMethods แทน ก่อนอื่นคุณต้องกำหนดวิธีการเนทีฟที่จำเป็น

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

จากนั้นรับตัวจัดการจอภาพและข้อมูลมอนิเตอร์เช่นนี้

        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
คุณจะได้ขนาดหน้าจอจริงหรือไม่หากมีมาตราส่วนของหน้าต่าง (100% / 125% / 150% / 200%)
Kiquenet


12

ระวังตัวคูณสเกลของหน้าต่างของคุณ (100% / 125% / 150% / 200%) คุณสามารถรับขนาดหน้าจอจริงโดยใช้รหัสต่อไปนี้:

SystemParameters.FullPrimaryScreenHeight
SystemParameters.FullPrimaryScreenWidth

1
สำหรับหน้าจอหลัก - จะเป็นอย่างไรถ้าหน้าต่างแอปของคุณอยู่บนหน้าจอเสมือน (ขยาย) (เช่นคุณมีจอภาพภายนอกหนึ่งหรือสองจอติดอยู่กับพีซีของคุณ)
Matt

4

ฉันต้องการให้มีความละเอียดหน้าจอก่อนที่จะเปิดหน้าต่างแรกของฉันดังนั้นนี่เป็นวิธีแก้ปัญหาอย่างรวดเร็วในการเปิดหน้าต่างที่มองไม่เห็นก่อนที่จะวัดขนาดหน้าจอจริง (คุณต้องปรับพารามิเตอร์หน้าต่างกับหน้าต่างของคุณเพื่อให้แน่ใจว่าทั้งสองเปิดอยู่ หน้าจอเดียวกัน - ส่วนใหญ่WindowStartupLocationเป็นสิ่งสำคัญ)

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

นี่คือ " โซลูชัน Center Screen DotNet 4.5 " โดยใช้SystemParametersแทนSystem.Windows.FormsหรือMy.Compuer.Screen : เนื่องจากWindows 8 มีการเปลี่ยนแปลงการคำนวณขนาดหน้าจอวิธีเดียวที่ทำงานสำหรับฉันดูเหมือนว่า (การคำนวณแถบงาน รวม):

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

หน้าจอกลาง WPF XAML


ตั้งค่าตัวติดตั้งใน WPF หรือไม่
Kiquenet

คำถามหลักคือเกี่ยวกับตำแหน่งหน้าจอ เช่นเดียวกับตัวติดตั้ง Msi, Innosetup หรืออื่น ๆ ฉันสร้างตัวติดตั้งของตัวเองด้วย CPU-check, การตรวจสอบสิทธิ์, การตรวจสอบไดรเวอร์และอีกมากมายใช้งานง่ายมาก นั่นเป็นภาพหน้าจอเกี่ยวกับ
Nasenbaer

3

ฉันต้องการกำหนดขนาดสูงสุดของแอปพลิเคชันหน้าต่างของฉัน สิ่งนี้สามารถเปลี่ยนแปลงได้ตามที่แอปพลิเคชันถูกแสดงในหน้าจอหลักหรือในรอง เพื่อเอาชนะปัญหานี้ e ได้สร้างวิธีการง่ายๆที่ฉันแสดงให้คุณเห็นต่อไป:

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

ใน C # winforms ฉันได้รับจุดเริ่มต้น (สำหรับกรณีที่เรามีมอนิเตอร์ / เอกสารหลายฉบับและแบบฟอร์มหนึ่งเรียกอีกแบบหนึ่ง) ด้วยความช่วยเหลือของวิธีการต่อไปนี้:

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

สำหรับการตั้งค่าหลายจอภาพคุณจะต้องมีบัญชีสำหรับตำแหน่ง X และ Y:

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

0

รหัสการแก้จุดบกพร่องนี้ควรทำเคล็ดลับดี:

คุณสามารถสำรวจคุณสมบัติของScreen Class

ใส่จอแสดงผลทั้งหมดในอาร์เรย์หรือรายการโดยใช้Screen.AllScreensจากนั้นจับดัชนีของจอแสดงผลปัจจุบันและคุณสมบัติ

ป้อนคำอธิบายรูปภาพที่นี่

C # (แปลงจาก VB โดย Telerik - โปรดตรวจสอบอีกครั้ง)

        {
    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 (รหัสดั้งเดิม)

 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)

รายการหน้าจอ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.