Windows显示设置为150%仍显示96 DPI

时间:2011-08-09 21:38:01

标签: windows dpi

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

感谢。

2 个答案:

答案 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%则不使用。

Custom DPI Settings


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