在运行Win7的笔记本电脑上,当我将显示设置设置为125%时,DPI显示为120(同时使用graphics.DpiX和GetDeviceCaps)。但是,显示为150%时,DPI为96(?!),就像100%一样。有谁知道a)为什么会这样?b)除了检查DPI以检测显示器是否设置为100%以外的任何其他方式之外还有其他方法吗?我正在编写一个应用程序,当显示设置为> = 150%时,我想显示一条消息。
感谢。
答案 0 :(得分:11)
在Windows Vista和Windows 7上,当DPI高于120(我认为)和它认为不支持DPI的应用程序时,它们会切换到DPI虚拟化模式。
这正是您所看到的 - 应用程序认为它以96dpi运行,而Windows将其炸毁并将所有内容渲染得更大(并且更加模糊)。
有关详情:http://msdn.microsoft.com/en-us/library/dd464660(VS.85).aspx#dpi_virtualization
本文介绍了如何在每个应用程序的基础上禁用它。
答案 1 :(得分:8)
我刚刚遇到同样的问题,虽然StackOverflow上有很多与DPI相关的问题,但我没有在一个地方找到所有答案。
问题a)的答案更容易: 从Windows Vista开始,Windows支持两种与DPI相关的大小调整。如果单击“显示设置”中的“设置自定义文本大小(DPI)”,则可以看到默认情况下,125%使用与Windows XP兼容的大小调整,而150%则不使用。
问题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-unaware应用程序,改变意识将破坏整个外观。调用该功能后无法关闭
- 在使用GetDeviceCaps之前和之后调用SetProcessDpiAwareness。 问题:此功能至少需要Windows 8.1
似乎MSDN上没有完整记录GetDeviceCaps function。至少我发现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);