如何获得有效的屏幕尺寸?


142

我正在寻找的是System.Windows.SystemParameters.WorkArea与窗口当前所在的监视器等效的控件。

澄清: 相关窗口WPF不是WinForm


2
更改了已接受的答案,以反映WPF执行此操作的最佳方法。System.Windows.SystemParameters。*
chilltemp 2010年

1
对不使用WinForms命名空间的迷恋对我来说似乎很奇怪,它并没有给您带来任何好处。相反,它使您失去了正确解决问题所需的工具。
杰夫·耶茨

4
对我而言,这与WinForms与WPF无关。这是关于学习新知识的。如果我不学习这两种方法,我无法决定哪种方法更好。
chilltemp 2011年

3
好吧,在这种情况下,没有“两种方式”,因为只有一种方式可以做到这一点,即使用WinForms东西。
杰夫·耶茨

@杰夫·耶茨:你是正确的。我挖了我问这个问题的原始项目,发现我使用了PrimaryScreen *属性。他们解决了我今天的需求,但没有解决我提出的实际问题。对不起,解决方法;我相应地更改了接受的答案。
chilltemp

Answers:


143

Screen.FromControlScreen.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窗口,而不是WinForms。我没有引用System.Windows.Forms.dll,并且由于WPF具有自己的继承树,因此无论如何都无法正常工作。
chilltemp

1
别客气。我很抱歉没有直接回答-在更新我的文章之前,我不得不研究WPF中的可用功能。
杰夫·耶茨

这样可以在右侧边缘放置一个窗口:var bounds = this.GetScreen()。WorkingArea; this.Left = bounds.Right-this.Width; 但是它需要引用System.Windows.Forms和System.Drawing,这并不理想。
安东尼

1
@devios请注意,此调用不支持DPI。您将需要进行计算。
Lynn在2015年

6
在我2015年VS WPF应用程序在Windows 10专业版(v10.0.14393)与我的4监视器系统上针对.NET 4.5 window在监视器上上面我主要的(例如,它的Top < 0),FromHandle返回Screen我的主显示器的(即使window完全内辅助监视器)!?!叹。看来我必须Screen.AllScreens自己搜索Array。为什么事情不能“正常工作”?!啊
汤姆(Tom)

62

您可以使用它来获取主屏幕的桌面工作空间范围:

System.Windows.SystemParameters.WorkArea

这对于仅获取主屏幕的大小也很有用:

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


19
我很困惑...这似乎只是返回主屏幕尺寸。我想知道窗口当前处于屏幕的尺寸...
VitalyB 2011年

1
这不能回答问题,即使您只想获取主显示的大小,SystemParameters(在WPF中)也不正确。它们返回与设备无关的单位,而不是像素。为了更好地实现看这个答案:stackoverflow.com/questions/254197/...
帕特里克·克卢格

1
PrimaryScreenHeight / Width完全按预期工作,并且MSDN上具有以下内容:“获取一个值,该值指示主显示监视器的屏幕高度(以像素为单位)。” WorkArea并未具体说像素,但是文档和用法示例使我相信它也是以像素为单位。您是否有指向某些指示使用设备无关单元的链接?
chilltemp 2011年


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 '19


12

当心窗户的比例系数(100%/ 125%/ 150%/ 200%)。您可以使用以下代码获取实际屏幕尺寸:

SystemParameters.FullPrimaryScreenHeight
SystemParameters.FullPrimaryScreenWidth

1
那是用于主屏幕的-如果您的应用程序窗口位于虚拟(扩展)屏幕上(即,您的PC上连接了一两个外接显示器),该怎么办?
马特

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

这是一个“中心屏幕DotNet 4.5解决方案 ”,使用SystemParameters而不是System.Windows.FormsMy.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 '19

主要问题是关于屏幕位置。像Msi安装程序,Innosetup或其他安装程序一样,我创建了自己的安装程序,其中包含CPU检查,权限检查,驱动程序验证以及更多其他功能,非常易于使用。多数民众赞成在截图。
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类的属性

使用Screen将所有显示置于数组或列表中.AllScreens然后捕获当前显示的索引及其属性。

在此处输入图片说明

C# (由Telerik转换为VB-请仔细检查)

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

屏幕列表

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.