【问题标题】:How do I determine the true pixel size of my Monitor in .NET?如何在 .NET 中确定监视器的真实像素大小?
【发布时间】:2009-01-07 21:55:43
【问题描述】:

我想在我的应用程序中以“真实大小”显示图像。为此,我需要知道显示器的像素大小。

我知道 Windows 显示分辨率名义上是 96dpi,但出于我的目的,我想要一个更好的猜测。我知道这些信息可能并不总是可用或准确的(例如旧的 CRT 显示器),但我想随着 LCD 显示器的普及,这应该是可能的!

有没有办法获得我的显示器的像素大小?

有没有办法判断像素大小是否准确?

.NET API 的首选(我找不到),但 Win32 也可以,我很高兴 P/Invoke。

【问题讨论】:

    标签: c# .net windows


    【解决方案1】:

    对于您想要的显示尺寸Screen.PrimaryScreen.Bounds.Size(或Screen.GetBounds(myform))。

    如果您需要 DPI,请使用 GraphicsDpiXDpiY 属性:

    PointF dpi = PointF.Empty;
    using(Graphics g = this.CreateGraphics()){
        dpi.X = g.DpiX;
        dpi.Y = g.DpiY;
    }
    

    哦,等等!您想要实际的,将尺子举到显示器上并测量尺寸?!不可以。使用 any 操作系统服务是不可能的。操作系统不知道显示器的实际尺寸,或者用户如何校准它。其中一些信息在理论上是可以检测到的,但它的确定性不足以让操作系统可靠地使用它,所以它不能。

    作为一种变通方法,您可以尝试一些方法。

    • 您可以尝试查询已安装监控设备的显示字符串(我不知道该怎么做),看看您是否可以从中解析出合理的大小。例如,显示器可能是“ValueBin E17p”,您可能由此推断它是 17" 显示器。当然,这个显示字符串很可能是“Plug and Play Monitor”。这个方案充其量是相当粗略的。
    • 您可以询问用户他们有多大尺寸的显示器。 也许他们会知道的。

    一旦您知道(或认为您知道)显示器的对角线尺寸,您就需要找到它的物理纵横比。同样,有几件事:

    • 假设当前像素纵横比与显示器的物理纵横比相匹配。这假设 (A) 用户选择了适合其显示器的分辨率,并且 (B) 显示器具有方形像素。我不知道目前面向消费者的电脑显示器没有方形像素,但旧款有,新款可能有。
    • 询问用户。 也许他们会知道的。

    一旦您知道(或认为您知道)显示器的对角线尺寸和物理纵横比是多少,您就可以计算它的物理宽度和高度。 A2 + B2 = C2,所以一些计算会给你带来好处:

    如果您发现它是 17 英寸显示器,并且其当前分辨率为 1280 x 1024:
    12802 + 10242 = 2686976
    Sqrt(2686976) = 1639.1998047828092637409837247032
    17" * 1280 / 1639.2 = 13.274768179599804782820888238165"
    17" * 1024 / 1639.2 = 10.619814543679843826256710590532"

    这使物理宽度为 13.27 英寸,物理高度为 10.62 英寸。这使得像素 13.27" / 1280 = 10.62" / 1024 = 0.01037" 或大约 0.263 mm。

    当然,如果用户没有合适的分辨率,显示器有古怪的非方形像素,或者它是较旧的模拟显示器并且没有正确调整控件以填充显示器,所有这些都是无效的整个物理屏幕。或者更糟的是,它可能是一台投影仪。

    最后,您最好执行校准步骤,让用户实际上将尺子举到屏幕上,然后为您测量物体的大小。你可以:

    • 让用户在相距一英寸(或一厘米)的任意两个点上单击鼠标。
    • 在屏幕上画一个盒子,让用户按上下箭头调整它的高度,按左右箭头调整它的宽度,直到根据他们的要求,这个盒子正好是一英寸(或厘米)的正方形尺子。
    • 在屏幕上画一个框,让用户告诉您它在每个维度中的英寸/厘米。

    无论您做什么,都不要期望您的结果是 100% 准确的。您(或用户)有太多因素在起作用,每次都无法完全正确地做到这一点。

    请注意,96 dpi 通常非常接近准确。非投影屏幕上的现代像素都趋向于大约 0.25 毫米,给或取,所以如果显示器设置为原始分辨率。 (当然,这是一个很大的概括,并非适用于所有显示器。例如,Eee PC 的像素大小约为 0.19 毫米,如果我没记错规格的话。)

    【讨论】:

      【解决方案2】:

      抱歉,您必须通过 P/Invoke 获取此信息。

      这是我不久前使用的链接: http://www.davidthielen.info/programming/2007/05/get_screen_dpi_.html

      【讨论】:

      • 这看起来就像它只是获取任何窗口的 dpi 设置,无论屏幕大小和分辨率如何,通常都是 96dpi。
      • 这是 Graphics 实例将返回的内容(请参阅 P Daddy 的答案)。无需 P/Invoke。
      【解决方案3】:

      您可以通过手动计算屏幕尺寸来检查

      cos(45)*LCD_SCREEN_DIAGONAL_IN_INCHES/sqrt(HORZ_RES^2 + VERT_RES^2)
      

      这将为您提供以英寸为单位的像素宽度

      【讨论】:

      • 我认为问题是如何以编程方式获取 LCD_SCREEN_DIAGONAL_IN_INCHES
      • 因此“检查”这个词,他要求在获得 dpi 后进行检查
      【解决方案4】:

      GetDeviceCaps 可以通过 P/Invoke'd 获取一些数据,但我从来不知道这些数据是那么值得信赖...

      【讨论】:

        【解决方案5】:

        您可以使用存储在注册表中的 EDID 信息来获取显示器的物理尺寸。您可以使用 EnumDisplayDevices windows API 调用获取适当的监视器注册表项。

        Physical Dimensions to the Screen object:

        【讨论】:

          【解决方案6】:

          TL;DR

          WPF 的真实尺寸 = 像素 * DPI 放大率

          DPI 放大倍率:

          Matrix dpiMagnification
          = PresentationSource.FromVisual(MyUserControl).CompositionTarget.TransformToDevice;
          double magnificationX = dpiMagnification.M11;
          double magnificationY = dpiMagnification.M22;
          

          讨论

          我在 2020 年仍然无法解决这个问题。回到 2009 年提出/回答这个问题时,.NET C# 可能意味着 Windows 窗体。但是WPF 是当时的事实标准......

          通过询问“真实尺寸”,您可能已经发现操作系统使用实际像素(比如 1366x768,我理解这是通常的笔记本电脑分辨率)和 DPI(很难找到)进行一些计算,以便给出控件的真实大小。而且您正在尝试制作一个可以扩展到不同显示器的应用程序。

          这个 DPI 实际数字似乎是隐藏的,但它已被标准化(转换为百分比)。假设 100% = 96 DPI,因为实际数字不再重要。人们可以通过转到 Windows 10 上的桌面 > 右键单击​​ > 显示设置 > 比例和布局部分 > 更改百分比以放大文本和其他元素来轻松增加系统范围的文本大小。

          您可以通过其他方式找到像素,然后将像素乘以/除以 DPI 百分比以获得真实大小。例如,我想用鼠标在 WPF 窗口的画布元素周围拖动 UserControl。用户控件的像素计数和鼠标 xy 坐标被标准化 DPI 关闭。为了让鼠标以与用户控件相同的速率移动,我使用:

          double newXCoord = System.Windows.Forms.Cursor.Position.X;
          double newYCoord = System.Windows.Forms.Cursor.Position.Y;
          double deltaX = newXCoord - oldXCoord;
          double deltaY = newYCoord - oldYCoord;
          
          double magnificationX = 1;
          double magnificationY = 1;
          Matrix dpiMagnification
          = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice;
          if (magnificationMatrix != null)
          {
              magnificationX = dpiMagnification.M11;
              magnificationY = dpiMagnification.M22;
          }
          PixelsFromLeft += deltaX / m_magnificationX;
          PixelsFromTop += deltaY / m_magnificationY;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-07-03
            • 1970-01-01
            • 2015-08-14
            • 2011-02-09
            • 1970-01-01
            相关资源
            最近更新 更多