GetDeviceCaps获取的屏幕物理大小并不是我的屏幕实际物理大小。

3
在Windows 7下,我使用以下代码获取屏幕的物理宽度(单位为毫米)。'hSize'是482,远大于实际尺寸(用尺子测量约为310)。为什么会这样呢?
HDC screen = GetDC(NULL);
int hSize=GetDeviceCaps(screen,HORZSIZE);

PS: 我需要DPI值来渲染地图。


5
HORZSIZE返回的值是一个基于配置的DPI和像素数量的近似值。它旨在作为逻辑测量而非物理测量。它可能会有相当大的误差,但您无法对其进行任何更改。 - Mark Ransom
@MarkRansom所说的(我只是AOL-ing)。 - Cheers and hth. - Alf
如果您需要 DPI,请直接请求:LOGPIXELSXLOGPIXELSY 被记录为提供这些值。 (除非我错了,否则请随意纠正我。) - andlabs
@andlabs 我需要“每毫米像素”,用于渲染地图。我可以直接从winapi获取DPI。但是,这里获取的DPI可能不适合地图渲染系统,这让我有些担心。 - Shaobo Zi
您可以通过一些基本的算术运算和英寸与毫米之间的转换系数将像素每英寸转换为像素每毫米。 - andlabs
显示剩余2条评论
1个回答

10
正如评论中所指出的那样,GetDeviceCaps(HORSIZE/VERTSIZE)极不准确。它一直是这样,可能也会一直是这样。你无能为力,所以你只需假装这个API不存在并继续前进。它不能帮助你找到显示器的真实尺寸。最好假设一个固定的默认值,如果需要让用户手动调整尺寸。

幸运的是,已经有人进行了研究并找到了在Windows上查找显示器物理尺寸的更好方法。在一篇名为Reading Monitor Physical Dimensions, or: Getting the EDID, the Right Way的博客文章中,Ofek描述了如何使用Windows的SetupAPI从显示器的EDID中获取更精确的尺寸。该过程的概述如下:
请调用SetupDiGetClassDevsEx来获取一个HDEVINFO句柄。 使用此HDEVINFO在调用SetupDiEnumDeviceInfo以填充SP_DEVINFO_DATA结构体。 同时在调用SetupDiOpenDevRegKey时,使用HDEVICEHDEVINFO来最终获得所需注册表键的HKEY - 即包含EDID块的键。 链接的博客文章包含示例代码以及作者尝试的其他替代方法的信息。
请注意,即使是EDID也不总是准确的。虽然它是显示器本身报告的自身尺寸,但仍有很多机会出现错误。供应商可以轻松地在EDID中犯错,而监视器仍将完美工作,因此几乎没有动力正确获取这些值。

只希望你不需要在多显示器系统上这样做!我曾经有过一台显示器,其EDID偏差如此之大,以至于它甚至没有正确提供其本机分辨率:http://superuser.com/questions/713487/getting-proper-resolution-with-windows-7-and-older-monitor - Mark Ransom
1
博客文章的作者还有一篇关于如何在多显示器系统中检索特定监视器的EDID的文章:http://ofekshilon.com/2014/06/19/reading-specific-monitor-dimensions/ - Ross Ridge

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