简体   繁体   English

如何在 .NET 中确定我的监视器的真实像素大小?

[英]How do I determine the true pixel size of my Monitor in .NET?

I want to display an image at 'true size' in my application.我想在我的应用程序中以“真实大小”显示图像。 For that I need to know the pixel size of the display.为此,我需要知道显示器的像素大小。

I know windows display resolution is nominally 96dpi, but for my purposes I want a better guess.我知道 Windows 显示分辨率名义上是 96dpi,但出于我的目的,我想要一个更好的猜测。 I understand this information may not always be available or accurate (eg older CRT displays), but I imagine with the prevelance of LCD displays that this should be possible!我知道这些信息可能并不总是可用或准确(例如旧的 CRT 显示器),但我想随着 LCD 显示器的普及,这应该是可能的!

Is there a way to get the pixel size of my display?有没有办法获得我的显示器的像素大小?

Is there a way to determine if the pixel size is accurate?有没有办法确定像素大小是否准确?

.NET API's preferred (I couldn't find them), but Win32 is OK too, I'm happy to P/Invoke. .NET API 的首选(我找不到它们),但 Win32 也可以,我很高兴 P/Invoke。

For the display size you'll want Screen .PrimaryScreen.Bounds.Size (or Screen.GetBounds(myform) ).对于显示器尺寸,你会希望Screen .PrimaryScreen.Bounds.Size (或Screen.GetBounds(myform) )。

If you want the DPI, use the DpiX and DpiY properties of Graphics :如果需要 DPI,请使用GraphicsDpiXDpiY属性:

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

Oh, wait!等一下! You wanted actual, hold a ruler up to the monitor and measure, size?!您想要实际的,将尺子放在显示器上并测量尺寸?! No. Not possible using any OS services.不可以。不能使用任何操作系统服务。 The OS doesn't know the actual dimensions of the monitor, or how the user has it calibrated.操作系统不知道显示器的实际尺寸,也不知道用户如何校准它。 Some of this information is theoretically detectable, but it's not deterministic enough for the OS to use it reliably, so it doesn't.其中一些信息在理论上是可检测的,但它的确定性不足以让操作系统可靠地使用它,所以它没有。

As a work around, you can try a couple of things.作为解决方法,您可以尝试一些方法。

  • You can try to query the display string of the installed monitor device (I'm not sure how to do that) and see if you can parse out a sensible size out of that.您可以尝试查询已安装的监视器设备的显示字符串(我不知道该怎么做),看看是否可以从中解析出合理的大小。 For example, the monitor might be a "ValueBin E17p", and you might deduce that it's a 17" monitor from that. Of course, this display string is likely to be "Plug and Play Monitor". This scheme is pretty sketchy at best.例如,监视器可能是“ValueBin E17p”,您可以从中推断出它是 17" 监视器。当然,这个显示字符串很可能是“即插即用监视器”。这个方案充其量是非常粗略的.
  • You could ask the user what size monitor they have.您可以询问用户他们有什么尺寸的显示器。 Maybe they'll know.也许他们会知道。

Once you know (or think you know) the monitor's diagonal size, you need to find its physical aspect ratio.一旦您知道(或认为您知道)显示器的对角线尺寸,您就需要找到它的物理纵横比。 Again, a couple of things:再次,有几件事:

  • Assume the current pixel aspect ratio matches the monitor's physical aspect ratio.假设当前像素纵横比与显示器的物理纵横比相匹配。 This assumes that (A) the user has chosen a resolution that is ideal for their monitor, and that (B) the monitor has square pixels.这假设 (A) 用户选择了适合其显示器的分辨率,并且 (B) 显示器具有方形像素。 I don't know of a current consumer-oriented computer monitor that doesn't have square pixels, but older ones did and newer ones might.我不知道目前有没有方形像素的面向消费者的计算机显示器,但旧的有,新的可能。
  • Ask the user.询问用户。 Maybe they'll know.也许他们会知道。

Once you know (or think you know) what the monitor's diagonal size and physical aspect ratio are, then you you can calculate it's physical width and height.一旦您知道(或认为您知道)显示器的对角线尺寸和物理纵横比是多少,那么您就可以计算它的物理宽度和高度。 A 2 + B 2 = C 2 , so a few calculations will give it to you good: A 2 + B 2 = C 2 ,所以一些计算会给你带来好处:

If you found out that it's a 17" monitor, and its current resolution is 1280 x 1024:如果您发现它是 17" 显示器,并且其当前分辨率为 1280 x 1024:
1280 2 + 1024 2 = 2686976 1280 2 + 1024 2 = 2686976
Sqrt(2686976) = 1639.1998047828092637409837247032平方(2686976)= 1639.1998047828092637409837247032
17" * 1280 / 1639.2 = 13.274768179599804782820888238165" 17" * 1280 / 1639.2 = 13.274768179599804782820888238165"
17" * 1024 / 1639.2 = 10.619814543679843826256710590532" 17" * 1024 / 1639.2 = 10.619814543679843826256710590532"

This puts the physical width at 13.27" and the physical height at 10.62".这使物理宽度为 13.27",物理高度为 10.62"。 This makes the pixels 13.27" / 1280 = 10.62" / 1024 = 0.01037" or about 0.263 mm.这使得像素为 13.27" / 1280 = 10.62" / 1024 = 0.01037" 或大约 0.263 毫米。

Of course, all of this is invalid if the user doesn't have a suitable resolution, the monitor has wacky non-square pixels, or it's an older analog monitor and the controls aren't adjusted properly for the display to fill the entire physical screen.当然,如果用户没有合适的分辨率,显示器有古怪的非方形像素,或者它是一个较旧的模拟显示器并且控件没有正确调整以使显示器填充整个物理,所有这些都是无效的屏幕。 Or worse, it could be a projector.或者更糟的是,它可能是一台投影仪。

In the end, you may be best off performing a calibration step where you have the user actually hold a ruler up to the screen , and measure the size of something for you.最后,您最好执行校准步骤,让用户实际将尺子举到屏幕上,并为您测量某物的大小。 You could:你可以:

  • Have the user click the mouse on any two points an inch (or a centimeter) apart.让用户在相距一英寸(或一厘米)的任意两点上单击鼠标。
  • Draw a box on the screen and have the user press the up and down arrows to adjust its height, and the left and right arrows to adjust its width, until the box is exactly one inch (or centimeter) square according to their ruler.在屏幕上画一个盒子,让用户按向上和向下箭头调整其高度,按左右箭头调整其宽度,直到盒子根据他们的标尺正好是一英寸(或厘米)平方。
  • Draw a box on the screen and have the user tell you how many inches/centimeters it is in each dimension.在屏幕上画一个盒子,让用户告诉你它在每个维度上有多少英寸/厘米。

No matter what you do , don't expect your results to be 100% accurate.无论您做什么,都不要期望您的结果是 100% 准确的。 There are way too many factors at play for you (or the user) to get this exactly correct, every time.有太多的因素在起作用,您(或用户)每次都无法完全正确地做到这一点。

Be aware that 96 dpi is usually pretty close to accurate.请注意,96 dpi 通常非常接近准确。 Modern pixels on non-projected screens all tend to be about 0.25 mm, give or take, so you usually end up with about 100 physical pixels per inch, give or take, if the monitor is set to its native resolution.非投影屏幕上的现代像素通常都在 0.25 毫米左右,因此如果显示器设置为其原始分辨率,通常每英寸会有大约100 个物理像素。 (Of course, this is a huge generalization and does not apply to all monitors. Eee PCs, for example, have pixels about 0.19 mm in size, if I remember the specs correctly.) (当然,这是一个巨大的概括,并不适用于所有的显示器。的Eee PC机,例如,具有像素约0.19毫米大小,如果我没有记错的规格。)

sorry, you've got to P/Invoke for this information.抱歉,您必须通过 P/Invoke 获取此信息。

Here's the link that I utilized for it a while ago: http://www.davidthielen.info/programming/2007/05/get_screen_dpi_.html这是我不久前使用的链接: http : //www.davidthielen.info/programming/2007/05/get_screen_dpi_.html

You can check by just manually calculating from your screen size您可以通过从屏幕尺寸手动计算来检查

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

That would give you the pixel width in inches这会给你以英寸为单位的像素宽度

GetDeviceCaps可以被 P/Invoke'd 得到一些数字,但我从来不知道这些数字是值得信赖的......

You may obtain the physical dimensions of the display using the EDID information stored in the registry.您可以使用存储在注册表中的 EDID 信息获取显示器的物理尺寸。 You can obtain the appropriate monitor's registry key using the EnumDisplayDevices windows API call.您可以使用 EnumDisplayDevices Windows API 调用获取相应监视器的注册表项。

Physical Dimensions to the Screen object : Screen 对象的物理尺寸

TL;DR TL; 博士

WPF's True Size = Pixels * DPI Magnification WPF 的真实尺寸 = 像素 * DPI 放大倍数

DPI Magnification: DPI 放大倍数:

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

Discussion讨论

I had trouble solving this question still in 2020. Back when this question was asked/answered in 2009, .NET C# probably meant Windows Forms.我在 2020 年仍然无法解决这个问题。回到 2009 年提出/回答这个问题时,.NET C# 可能意味着 Windows 窗体。 But WPF is the de facto standard of the day...WPF是当今事实上的标准......

By asking about "true size" you have probably already figured out that the operating system does some calculation with actual pixels (say 1366x768, which I understand is usual laptop resolutions) and the DPI (hard to find) in order to give a control's true size.通过询问“真实大小”,您可能已经发现操作系统会使用实际像素(比如 1366x768,我理解这是通常的笔记本电脑分辨率)和 DPI(很难找到)进行一些计算,以便为控件提供真实的尺寸。 And you are trying to make an app that scales to different monitors.您正在尝试制作一个可扩展到不同显示器的应用程序。

This DPI actual number seems to be hidden, but it has been normalized (converted to a percentage).这个 DPI 实际数字似乎是隐藏的,但它已被标准化(转换为百分比)。 Assume 100% = 96 DPI, just because the actual number does not matter anymore.假设 100% = 96 DPI,只是因为实际数字不再重要。 People can easily increase the system-wide text size by going to Desktop on Windows 10 > right click > Display settings > section Scale and layout > change the percentage to magnify text and other elements.人们可以通过转到 Windows 10 上的桌面 > 右键单击​​ > 显示设置 > 部分缩放和布局 > 更改百分比以放大文本和其他元素来轻松增加系统范围的文本大小。

Windows10_RightClickDesktop

Windows10_DisplaySettings_150PercentMagnification_3840x2160

You can find the pixels another way, and multiple/divide the pixel by the DPI percentage in order to get true size.您可以通过另一种方式找到像素,并将像素乘以/除以 DPI 百分比以获得真实大小。 For instance, I want to drag a UserControl around a canvas element of a WPF window with the mouse.例如,我想用鼠标在 WPF 窗口的画布元素周围拖动 UserControl。 The user control's pixel count and the mouse xy-coordinates were off by the normalized DPI.用户控件的像素计数和鼠标 xy 坐标被归一化 DPI 关闭。 In order to keep the mouse moving at the same rate as the user control, I use:为了让鼠标以与用户控件相同的速度移动,我使用:

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM