在C#中将像素转换为英寸,反之亦然

9

我想要将像素转换成英寸,反之亦然。我知道需要DPI值,但是我不确定如何获取这个信息(例如,我没有Graphics对象,所以这不是一个选项)。

有什么方法吗?


DPI 是指什么?屏幕?打印机?……? - Mehrdad Afshari
3个回答

9

在视频设备上,对于这个问题的任何答案通常都不是非常准确的。最容易用来解释这种情况的例子是投影仪。输出分辨率为1024x768,但DPI根据屏幕距离投影仪光圈的远近而变化。例如,WPF始终假设视频设备的DPI为96。

假设您仍然需要一个答案,无论其准确性如何,并且没有Graphics对象,您可以使用一些P/Invoke从屏幕创建一个并从中获取答案。

Single xDpi, yDpi;

IntPtr dc = GetDC(IntPtr.Zero);

using(Graphics g = Graphics.FromHdc(dc))
{
    xDpi = g.DpiX;
    yDpi = g.DpiY;
}

if (ReleaseDC(IntPtr.Zero) != 0)
{
    // GetLastError and handle...
}


[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hwnd);    
[DllImport("user32.dll")]
private static extern Int32 ReleaseDC(IntPtr hwnd);

6

如果不知道DPI,实际上就没有真正的方法。像素是离散的,而英寸并不是。如果你在谈论显示器上的英寸,你需要知道(至少)分辨率(和像素宽高比)以及可见监视器区域的大小才能计算出DPI。通常可以在某个地方获取分辨率(我不是C#或.NET程序员,所以无法帮助您),但通常无法获取监视器的大小。如果估计值足够好,那么请用户输入监视器的大小(例如21英寸),然后解决DPI:

(resX/DPI)^2 + (resY/DPI)^2 = screenDiagonal^2

假设您已知对角线和分辨率,这是给出的。

DPI = sqrt(resX^2+resY^2)/screenDiagonal

这只是一个估计值,因为显示器通常不会完全是21英寸(或其他尺寸),像素宽高比也很少恰好是1:1。

如果你在谈论纸上的英寸,则自然需要知道打印机的DPI(或更准确地说,当前的打印机设置)。


那么,鉴于我无法访问Graphics对象,我该如何计算DPI? - AngryHacker
假设其余部分已知,请解出DPI的方程。 - falstro
我怎么知道显示器的对角线长度?我的应用程序将在我无法控制的计算机上运行。 - AngryHacker
你可以做一个大致的估算,假设每个人都有一台19英寸或21英寸的显示器;如果这真的很重要,则必须询问用户,没有其他人知道(参见评论投影仪的答案),但在这种情况下,您可能希望使用其他技术来获得更准确的答案。 - falstro
这是一个相当无用的答案。他正在寻找一个系统调用来告诉他Windows认为DPI是多少(我也是)。 - mmr
@mmr - 请查看下面的答案。 - codekaizen

1
您可以简单地调用this.CreateGraphics()(或更一般的Control.CreateGraphics())来创建 Graphics 对象,然后使用 DpiX 和 DpiY 属性,就像您所了解的那样。请记住,在创建完 Graphics 对象后要进行清除(最好使用 Using 语句)。
如果您没有使用 WinForms,请告诉我们它是什么类型的应用程序。

我做不到。我正在编写ActiveReports报表工作表的代码后文件。它没有这些属性。 - AngryHacker
他确实说他正在使用WPF,而不是WinForms。同时使用两者可能会导致严重的问题。 - mmr
@mmr:不,他没有说明他正在使用WPF。实际上,对“Graphic”的引用似乎强烈暗示了WinForms。无论如何,感谢你的负评。 - Noldorin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接