C++ 在windows下获取实际屏幕dpi/ppi

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12652835/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:28:50  来源:igfitidea点击:

Getting actual screen dpi/ppi under windows

c++windowsscreendpippi

提问by Andy Li

I would like to get the actualscreen dpi/ppi, not the dpi setting used for font in C++.

我想获得实际的屏幕 dpi/ppi,而不是用于 C++ 字体的 dpi 设置。

I tried with the following codes:

我尝试使用以下代码:

Version 1, reports 72 dpi, which is wrong.

版本 1,报告 72 dpi,这是错误的。

SetProcessDPIAware(); //true
HDC screen = GetDC(NULL);
double hSize = GetDeviceCaps(screen, HORZSIZE);
double vSize = GetDeviceCaps(screen, VERTSIZE);
double hRes = GetDeviceCaps(screen, HORZRES);
double vRes = GetDeviceCaps(screen, VERTRES);
double hPixelsPerInch = hRes / hSize * 25.4;
double vPixelsPerInch = vRes / vSize * 25.4;
ReleaseDC(NULL, screen);
return (hPixelsPerInch + vPixelsPerInch) * 0.5;

Version 2, reports 96 dpi, which is the Windows dpi setting for font, but not the actual screen dpi.

版本 2,报告 96 dpi,这是字体的 Windows dpi 设置,但不是实际的屏幕 dpi。

SetProcessDPIAware(); //true
HDC screen = GetDC(NULL);
double hPixelsPerInch = GetDeviceCaps(screen,LOGPIXELSX);
double vPixelsPerInch = GetDeviceCaps(screen,LOGPIXELSY);
ReleaseDC(NULL, screen);
return (hPixelsPerInch + vPixelsPerInch) * 0.5;

回答by Adrian McCarthy

What you're asking for is, unfortunately, not possible in the general case.

不幸的是,您所要求的在一般情况下是不可能的。

Windows doesn't know the physical screen size. Windows might know that your screen has 1024x768 pixels, but it doesn't know how big the screen actually is. You might pull the cable out of your old 13" screen and connect it to a 19" monitor without changing the resolution. The DPI would be different, but Windows won't notice that you changed monitors.

Windows 不知道物理屏幕大小。Windows 可能知道您的屏幕有 1024x768 像素,但它不知道屏幕实际有多大。您可以将电缆从旧的 13" 屏幕中拉出并将其连接到 19" 显示器而不更改分辨率。DPI 会有所不同,但 Windows 不会注意到您更改了显示器。

You can get the true physical dimensions and DPI for a printer (assuming the driver isn't lying), but not for a screen. At least not reliably.

您可以获得打印机的真实物理尺寸和 DPI(假设驱动程序没有说谎),但不能获得屏幕的真实尺寸和 DPI。至少不可靠。

UPDATED

更新

As others have pointed out, there are standards for two-way communication between newer monitors and the OS (EDID), that might make this information available for some devices. But I haven't yet found a monitor that provides this information.

正如其他人指出的那样,较新的显示器和操作系统 (EDID) 之间存在双向通信的标准,这可能使某些设备可以使用此信息。但我还没有找到提供这些信息的监视器。

Even if EDID were universally available, it's still not solvable in the general case, as the display could be a video projector, where the DPI would depend on the zoom, the focus, the lens type, and the throw distance. A projector is extremely unlikely to know the throw distance, so there's no way for it to report the actual DPI.

即使 EDID 普遍可用,在一般情况下仍然无法解决,因为显示器可能是视频投影仪,其中 DPI 将取决于变焦、焦点、镜头类型和投射距离。投影仪极不可能知道投射距离,因此它无法报告实际 DPI。

回答by Katastic Voyage

I'm honestly confused by the answers here.

老实说,我对这里的答案感到困惑。

Microsoft has a GetDpiForMonitor method:

微软有一个 GetDpiForMonitor 方法:

https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510(v=vs.85).aspx

https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510(v=vs.85).aspx

And monitors DO expose their physical dimensions to tools. You can read your monitors width and height, in centimeters, using the HWiNFO64 tool. So if they're getting it (DDI?), it stands to reason that you can access that information yourself.

并且监视器确实会将它们的物理尺寸暴露给工具。您可以使用 HWiNFO64 工具以厘米为单位读取显示器的宽度和高度。所以如果他们得到它(DDI?),你可以自己访问这些信息是合情合理的。

Even a different Stack Overflow post mentions using WmiMonitorBasicDisplayParams to get the data.

甚至不同的 Stack Overflow 帖子也提到使用 WmiMonitorBasicDisplayParams 来获取数据。

How to get monitor size

如何获得显示器尺寸

So the top post is flat-out, 100%, wrong.

所以顶帖是平的,100%,错了。

回答by MGR

Getting DPI information is found to produce exact value using the below method.

发现获取 DPI 信息可以使用以下方法产生精确值。

ID2D1Factory* m_pDirect2dFactory;
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pDirect2dFactory);
FLOAT dpiX, dpiY;
m_pDirect2dFactory->GetDesktopDpi( &dpiX, &dpiY );

回答by James Bedford

I think what you're after is:

我认为你所追求的是:

GetDeviceCaps(hdcScreen, LOGPIXELSX); GetDeviceCaps(hdcScreen, LOGPIXELSY);

GetDeviceCaps(hdcScreen, LOGPIXELSX); GetDeviceCaps(hdcScreen, LOGPIXELSY);