Etkin ekran boyutlarını nasıl alabilirim?


142

Aradığım System.Windows.SystemParameters.WorkAreaşey, pencerenin açık olduğu monitöre eşdeğerdir .

Açıklama: Söz konusu pencere WPFdeğil WinForm.


2
WPF'den bunu yapmanın en iyi yolunu yansıtacak şekilde kabul edilen cevap değiştirildi. System.Windows.SystemParameters. *
chilltemp

1
WinForms ad alanı kullanmama saplantısı bana tuhaf geliyor, size hiçbir şey kazandırmıyor; bunun yerine, sorunu doğru bir şekilde çözmek için ihtiyacınız olan araçlar olmadan sizi bırakır.
Jeff Yates

4
Benim için, WinForms vs. WPF ile ilgili değil. Yeni bir şey öğrenmekle ilgili. Her iki yolu da öğrenmezsem hangi yolun daha iyi olduğuna karar veremem.
chilltemp

3
Peki, bu senaryoda "her iki yol" da yoktur, çünkü bunu yapmanın tek bir yolu vardır, bu da WinForms öğelerini kullanmaktır.
Jeff Yates

@ Jeff Yates: Haklısın. Bu soruyu sorduğum orijinal projeyi kazdım ve PrimaryScreen * özelliklerini kullandığımı fark ettim. Günün ihtiyaçlarımı çözdüler, ama sorduğum asıl soru değil. Etrafta dolaştığım için üzgünüm; Kabul edilen cevabı buna göre değiştirdim.
chilltemp

Yanıtlar:


143

Screen.FromControl, Screen.FromPointVe Screen.FromRectanglebu konuda size yardımcı olacaktır. Örneğin WinForms'da şöyle olur:

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

WPF için eşdeğer bir çağrı bilmiyorum. Bu nedenle, bu uzantı yöntemi gibi bir şey yapmanız gerekir.

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

1
Belki de etiketlemem WinForms'u değil WPF pencerelerini kullandığımı netleştirmedi. Ben System.Windows.Forms.dll başvuru yok ve WPF kendi miras ağacı olduğundan zaten işe yaramaz.
chilltemp

1
Rica ederim. Doğrudan cevaba ulaşmadığım için özür dilerim - yazımı güncellemeden önce WPF'de nelerin mevcut olduğunu araştırmak zorunda kaldım.
Jeff Yates

Bu, sağ kenara bir pencere koymak için çalışır: var bounds = this.GetScreen (). WorkingArea; this.Left = sınırlar.Sağ - this.Width; Ancak, ideal olmayan System.Windows.Forms ve System.Drawing referanslarını gerektirir.
Anthony

1
@devios Bu aramanın DPI uyumlu olmadığına dikkat edin; hesaplamalar yapmanız gerekir.
Lynn Crumbling

6
Windows'un 10 Pro (v10.0.14393) ile benim 4 monitör sistemi üzerinde .NET 4.5 hedeflememi VS 2015 WPF uygulamasında windowmonitörde yukarıda benim İlköğretim yıllardan (örneğin onun Top < 0), FromHandledöndürülen Screenbenim İlköğretim monitör en (olsa bile windowoldu tamamen içinde İkincil monitör)!?! İç çekmek. Screen.AllScreensDiziyi kendim aramam gerekecek gibi görünüyor . Neden işler "sadece işe yaramaz"?!? Arrrrgh.
Tom

62

Birincil ekranın masaüstü çalışma alanı sınırlarını almak için bunu kullanabilirsiniz:

System.Windows.SystemParameters.WorkArea

Bu, yalnızca birincil ekranın boyutunu elde etmek için de yararlıdır:

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


19
Kafam karıştı ... Bu sadece birincil ekran boyutlarını döndürmek için görünüyor. Pencerenin şu anda olduğu ekranın boyutlarını bilmek istiyorum ...
VitalyB

1
bu soruya cevap vermez ve sadece birincil ekranın boyutunu almak isteseniz bile SystemParameters (WPF'de) yanlıştır. pikselden değil aygıttan bağımsız birimler döndürürler . daha iyi bir uygulama için şu cevaba bakınız: stackoverflow.com/questions/254197/…
Patrick Klug

1
PrimaryScreenHeight / Width tam olarak beklendiği gibi çalıştı ve MSDN'de aşağıdakiler var: "Birincil ekran monitörünün ekran yüksekliğini piksel cinsinden gösteren bir değer alır." WorkArea özellikle pikselleri söylemez, ancak belgeler ve kullanım örnekleri bana piksellerde olduğuna inanmamı sağlıyor. Cihazdan bağımsız birimlerin kullanımını belirten bir şeye bağlantınız var mı?
chilltemp


17

Bunun yerine WinForms yerine NativeMethods kullanmayan bir çözüm ekleme. Öncelikle gerekli olan yerel yöntemleri tanımlamanız gerekir.

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

Ardından monitör kolunu ve bunun gibi monitör bilgilerini alın.

        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
Pencerelerinizin ölçek faktörü varsa (% 100 /% 125 /% 150 /% 200) gerçek ekran boyutunu alabilir misiniz?
Kiquenet


12

Pencerelerinizin ölçek faktörüne dikkat edin (% 100 /% 125 /% 150 /% 200). Aşağıdaki kodu kullanarak gerçek ekran boyutunu elde edebilirsiniz:

SystemParameters.FullPrimaryScreenHeight
SystemParameters.FullPrimaryScreenWidth

1
Bu birincil ekran içindir - uygulama pencereniz sanal (genişletilmiş) bir ekrandaysa (yani, bilgisayarınıza bağlı bir veya iki harici monitörünüz varsa)?
Mat

4

Pencerelerimin ilkini açmadan önce ekran çözünürlüğüne sahip olmak istedim, bu yüzden ekran boyutlarını gerçekten ölçmeden önce görünmez bir pencere açmak için hızlı bir çözüm (her ikisinin de açık olduğundan emin olmak için pencere parametrelerini pencerenize uyarlamanız gerekir aynı ekran - esas WindowStartupLocationolarak önemlidir)

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

Bu, System.Windows.Forms veya My.Compuer.Screen yerine SystemParameters kullanan bir "Orta Ekran DotNet 4.5 çözümüdür " : Windows 8 ekran boyut hesaplamasını değiştirdiğinden , benim için çalışmanın tek yolu şöyle görünüyor (Görev çubuğu hesaplama) dahil):

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

Orta Ekran WPF XAML


WPF'de yükleyici kurulumu?
Kiquenet

Ana soru ekran konumu hakkında. Msi yükleyicisi, Innosetup veya diğerleri gibi, CPU kontrolü, İzin kontrolü, sürücü doğrulama ve çok daha fazlası ile kendi yükleyicimi oluşturdum, kullanımı çok basit. Ekran görüntüsü hakkında.
Nasenbaer

3

Pencere uygulamamın maksimum boyutunu ayarlamam gerekiyordu. Buna göre uygulama değiştirilebilir birincil ekranda veya ikincil ekranda gösterilir. Bu sorunun üstesinden gelmek için bir sonraki adımda göstereceğim basit bir yöntem oluşturduk:

/// <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 Ben aşağıdaki yöntem yardımıyla (birkaç monitör / diplay ve bir form başka bir çağırıyor durumunda) başlangıç ​​noktası var:

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

Çoklu monitör kurulumları için X ve Y konumlarını da dikkate almanız gerekir:

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

0

Bu hata ayıklama kodu hile iyi yapmalıdır:

Screen Class'ın özelliklerini keşfedebilirsiniz

Screen.AllScreens öğesini kullanarak tüm görüntüleri bir diziye veya listeye yerleştirin , ardından geçerli ekranın ve özelliklerinin dizinini yakalayın.

resim açıklamasını buraya girin

C # (Telerik tarafından VB'den dönüştürüldü - Lütfen tekrar kontrol edin)

        {
    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 (Orijinal 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)

Ekran Listesi

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.