Windows 显示设置为 150% 仍显示 96 DPI
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7003316/
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
Windows Display Setting at 150% still shows 96 DPI
提问by Matt
On my laptop running Win7, when I set the display setting to 125%, the DPI shows up as 120 (using both graphics.DpiX and GetDeviceCaps) as expected. However, with the display at 150%, the DPI is 96 (?!), just like it is at 100%. Does anyone know a) why this is the case and b) is there any other way other than checking the DPI to detect if the display is set to anything other than 100%? I'm writing an app that I want to display a message when the display is set to >= 150%.
在运行 Win7 的笔记本电脑上,当我将显示设置设置为 125% 时,DPI 显示为 120(同时使用 graphics.DpiX 和 GetDeviceCaps)。但是,当显示为 150% 时,DPI 为 96 (?!),就像在 100% 时一样。有谁知道 a) 为什么会这样,b) 除了检查 DPI 以检测显示是否设置为 100% 以外,还有其他方法吗?我正在编写一个应用程序,当显示设置为 >= 150% 时,我想显示一条消息。
Thanks.
谢谢。
回答by HappyCat
On Windows Vista and Windows 7, with DPIs above 120 (I think) and applications that it considers to be non-DPI aware, they switch into DPI Virtualization Mode.
在 Windows Vista 和 Windows 7 上,如果 DPI 高于 120(我认为)和它认为是非 DPI 感知的应用程序,它们会切换到 DPI 虚拟化模式。
This does exactly what you're seeing - the application thinks it's running in 96dpi while Windows blows it up and renders everything bigger (and blurrier).
这正是您所看到的 - 应用程序认为它以 96dpi 运行,而 Windows 将其放大并使所有内容变得更大(并且更模糊)。
For more details: https://docs.microsoft.com/en-gb/windows/win32/hidpi
更多详情:https: //docs.microsoft.com/en-gb/windows/win32/hidpi
(original link (now redirects to above): http://msdn.microsoft.com/en-us/library/dd464660(VS.85).aspx#dpi_virtualization)
(原始链接(现在重定向到上面):http: //msdn.microsoft.com/en-us/library/dd464660(VS.85) .aspx#dpi_virtualization)
The article explains how to disable it on a per-application basis.
这篇文章解释了如何在每个应用程序的基础上禁用它。
回答by Gy?rgy K?szeg
I've just struggled the same problem, and though there are a lot of DPI-related questions on StackOverflow, I did not find all the answers in one place.
我刚刚遇到了同样的问题,虽然 StackOverflow 上有很多与 DPI 相关的问题,但我没有在一个地方找到所有的答案。
The answer to question a)is the easier one: Starting with Windows Vista, Windows supports two kinds of DPI-related resizing. If you click on "Set custom text size (DPI)" on Display settings, you can see that by default, 125% uses the Windows XP-compatible resizing, while 150% doesn't.
问题 a)的答案更简单:从 Windows Vista 开始,Windows 支持两种与 DPI 相关的大小调整。如果单击“显示设置”中的“设置自定义文本大小 (DPI)”,您可以看到默认情况下,125% 使用 Windows XP 兼容的调整大小,而 150% 不使用。
Question b)is a trickier one. If you search StackOverflow, usually you can find the following answer:
问题 b)是一个棘手的问题。如果搜索 StackOverflow,通常可以找到以下答案:
using (Graphics screen = Graphics.FromHwnd(IntPtr.Zero))
{
IntPtr hdc = screen.GetHdc();
int dpiX = GetDeviceCaps(hdc, DeviceCaps.LOGPIXELSX);
screen.ReleaseHdc(hdc);
}
However, it will return always 96, regardless of actual DPI settings, unless...
- You use Windows XP or the compatibility mode is checked in at DPI settings. Problem: you cannot enforce it at the users.
- DWM is turned off (you use Basic or Classic themes). Problem: same as above.
- You call SetProcessDPIAwarefunction before using GetDeviceCaps. Problem: This function should be called once, before all other rendering. If you have an existing DPI-unaware app, changing the awareness will ruin the whole appearance. It cannot be turned off once you called the function.
- You call SetProcessDpiAwarenessbefore and after using GetDeviceCaps. Problem: This function requires at least Windows 8.1
但是,无论实际 DPI 设置如何,它将始终返回 96,除非...
- 您使用 Windows XP 或在 DPI 设置中检查了兼容模式。问题:您无法对用户强制执行它。
- DWM 已关闭(您使用基本或经典主题)。问题:同上。
-在使用 GetDeviceCaps 之前调用SetProcessDPIAware函数。问题:这个函数应该在所有其他渲染之前调用一次。如果您有一个现有的 DPI-unaware 应用程序,更改意识将破坏整个外观。一旦调用该函数就无法将其关闭。
-在使用 GetDeviceCaps 之前和之后调用SetProcessDpiAwareness。问题:此功能至少需要 Windows 8.1
The real working solution
真正有效的解决方案
It seems that the GetDeviceCaps functionis not fully documented at MSDN. At least I discovered that pinvoke.netmentions a few further options that can be obtained by the function. At the end I came out with the following solution:
MSDN 上似乎没有完全记录GetDeviceCaps 函数。至少我发现pinvoke.net提到了一些可以通过该函数获得的进一步选项。最后我提出了以下解决方案:
public static int GetSystemDpi()
{
using (Graphics screen = Graphics.FromHwnd(IntPtr.Zero))
{
IntPtr hdc = screen.GetHdc();
int virtualWidth = GetDeviceCaps(hdc, DeviceCaps.HORZRES);
int physicalWidth = GetDeviceCaps(hdc, DeviceCaps.DESKTOPHORZRES);
screen.ReleaseHdc(hdc);
return (int)(96f * physicalWidth / virtualWidth);
}
}
And the required additional code:
以及所需的附加代码:
private enum DeviceCaps
{
/// <summary>
/// Logical pixels inch in X
/// </summary>
LOGPIXELSX = 88,
/// <summary>
/// Horizontal width in pixels
/// </summary>
HORZRES = 8,
/// <summary>
/// Horizontal width of entire desktop in pixels
/// </summary>
DESKTOPHORZRES = 118
}
/// <summary>
/// Retrieves device-specific information for the specified device.
/// </summary>
/// <param name="hdc">A handle to the DC.</param>
/// <param name="nIndex">The item to be returned.</param>
[DllImport("gdi32.dll")]
private static extern int GetDeviceCaps(IntPtr hdc, DeviceCaps nIndex);