如何确定.NET中Monitor的真实像素大小?

时间:2009-01-07 21:55:44

标签: c# .net windows

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

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

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

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

.NET API首选(我找不到它们),但Win32也行,我很高兴P / Invoke。

6 个答案:

答案 0 :(得分:27)

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

如果您想要DPI,请使用DpiXDpiYGraphics属性:

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

哦,等等!你想要实际的,拿一把尺子直到显示器并测量尺寸?!不可以。使用任何 OS服务是不可能的。操作系统不知道显示器的实际尺寸,或用户如何校准显示器。其中一些信息在理论上是可检测的,但对于操作系统来说,它不能确定性地可靠地使用它,所以它没有。

作为一种解决方法,你可以尝试一些事情。

  • 您可以尝试查询已安装的监视器设备的显示字符串(我不知道该怎么做)并查看是否可以解析出合理的大小。例如,监视器可能是“ValueBin E17p”,你可能推断它是一个17“监视器。当然,这个显示字符串很可能是”即插即用监视器“。这个方案充其量是非常粗略的。
  • 你可以询问用户他们有什么尺寸的显示器。 也许他们会知道的。

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

  • 假设当前像素长宽比与显示器的物理宽高比相匹配。这假定(A)用户选择了适合其监视器的分辨率,并且(B)监视器具有方形像素。我不知道当前面向消费者的计算机显示器没有方形像素,但是较旧的计算机显示器和新的像素可能。或者
  • 询问用户。 也许他们会知道的。

一旦你知道(或认为你知道)显示器的对角线尺寸和物理长宽比是什么,那么你可以计算它的物理宽度和高度。 2 + B 2 = C 2 ,所以一些计算会给你带来好处:

  

如果您发现它是17“显示器,其当前分辨率为1280 x 1024:
  1280 2 + 1024 2 = 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毫米,给予或拍摄,因此如果显示器设置为其,您通常最终会得到大约每英寸100个物理像素,给予或接受原始分辨率。 (当然,这是一个巨大的概括,适用于所有显示器。例如,如果我没有正确记住规格,Eee PC的像素大小约为0.19毫米。)

答案 1 :(得分:1)

抱歉,您需要P / Invoke来获取此信息。

这是我前一段时间使用的链接: http://www.davidthielen.info/programming/2007/05/get_screen_dpi_.html

答案 2 :(得分:1)

您只需手动计算屏幕尺寸即可查看

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

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

答案 3 :(得分:1)

GetDeviceCaps可以通过P / Invoke来获取一些数字,但我从来不知道数字是值得信赖的......

答案 4 :(得分:0)

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

Physical Dimensions to the Screen object

答案 5 :(得分:0)

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 Forms。但是WPF是当今的事实上的标准...

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

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

Windows10_RightClickDesktop

Windows10_DisplaySettings_150PercentMagnification_3840x2160

您可以用另一种方式找到像素,然后将像素乘以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;