在150%的Windows显示设置仍然显示96 DPI

在运行Win7的笔记本电脑上,当我将显示设置设置为125%时,DPI显示为120(同时使用graphics.DpiX和GetDeviceCaps)。 但是,在150%的显示下,DPI是96(?!),就像是100%。 有没有人知道a)为什么是这种情况,b)除了检查DPI以检测显示器是否设置为100%以外,还有其他方法吗? 我正在编写一个应用程序,当显示设置为> = 150%时,我想显示一条消息。

谢谢。

在Windows Vista和Windows 7上,如果DPI大于120(我认为)以及它认为不支持DPI的应用程序,则会切换到DPI虚拟化模式。

这正是你所看到的 – 应用程序认为它运行在96dpi而Windows吹起来,并呈现一切更大(和模糊)。

有关更多详细信息,请访问: http : //msdn.microsoft.com/en-us/library/dd464660(VS.85).aspx#dpi_virtualization

文章解释了如何在每个应用程序的基础上禁用它。

我刚才也遇到了同样的问题,虽然在StackOverflow中有很多与DPI相关的问题,但我并没有在一个地方找到所有答案。

问题a)的答案更容易:从Windows Vista开始,Windows支持两种与DPI相关的调整大小。 如果在“显示设置”上单击“设置自定义文本大小(DPI)”,则可以看到默认情况下,125%使用与Windows XP兼容的调整大小,而150%则不使用。

自定义DPI设置

问题b)是一个棘手的问题 。 如果您搜索StackOverflow,通常可以找到以下答案:

using (Graphics screen = Graphics.FromHwnd(IntPtr.Zero)) { IntPtr hdc = screen.GetHdc(); int dpiX = GetDeviceCaps(hdc, DeviceCaps.LOGPIXELSX); screen.ReleaseHdc(hdc); } 

但是,无论实际的DPI设置如何,它将始终返回96,除非…
– 使用Windows XP或在DPI设置中检入兼容模式。 问题 :您无法在用户处执行此操作。
– DWM已关闭(您使用基本或经典主题)。 问题 :同上。
– 在使用GetDeviceCaps之前调用SetProcessDPIAware函数。 问题 :这个函数应该在所有其他渲染之前调用一次。 如果你有一个现有的DPI-不知道的应用程序,改变意识将毁了整个外观。 一旦你调用函数,它就不能被关闭。
– 在使用GetDeviceCaps之前和之后调用SetProcessDpiAwareness 。 问题 :此功能至少需要Windows 8.1

真正的工作解决方案

看来GetDeviceCaps函数在MSDN上没有完整的记录。 至少我发现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); } } 

而所需的附加代码:

 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);