1

在我的 C# winforms 应用程序中,我使用 Graphics 对象来获取当前 DPI 值,以使我的代码能够缩放某些组件。这很好用,只是一旦我调用 CreateGraphics(),我的 winforms 应用程序的外观和感觉就会发生变化。风格从熟悉的“圆形”按钮到看起来更古老的“锐边”按钮。

为什么会发生这种情况,我能做些什么来防止它发生?

我的代码如下所示:

        Graphics g = this.CreateGraphics();
        try
        {
            if (g.DpiX == 120.0f)
            {
                // scale the components appropriately
            }
        }
        finally
        {
            g.Dispose();
        }

事实上,我可以通过调用 CreateGraphics 然后立即处理它来重现问题。

非常感谢任何帮助或见解!

另一个问题是:有没有在不创建图形对象的情况下获得 DPI 设置?

4

1 回答 1

0

前段时间我正在研究 DPI 问题,当时一位同事开始使用高 DPI 显示器。

我的方法是询问桌面,而不是 Dpi 的特定窗口。当我遇到一些麻烦时,我想出了这段代码(不是很漂亮,但对我来说效果很好):

    /// <summary>
    /// Assesses the Systems Primary Monitor's DPI value
    /// </summary>
    public static double DPI {
        get {
            Graphics g = Graphics.FromHwnd(IntPtr.Zero);
            IntPtr desktop = g.GetHdc();
            int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
            int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);

            float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;

            // dpi1 answers correctly if application is "dpiaware=false"
            int dpi1 = (int)(96.0 * ScreenScalingFactor);
            // dpi2 answers correctly if application is "dpiaware=true"
            int dpi2 = GetDeviceCaps(desktop, (int)DeviceCap.LOGPIXELSX);

            return Math.Max(dpi1, dpi2);
        }
    }

    [DllImport("gdi32.dll")]
    static private extern int GetDeviceCaps(IntPtr hdc, int nIndex);

    private enum DeviceCap {
        VERTRES = 10,
        DESKTOPVERTRES = 117,
        LOGPIXELSX = 88,

        // http://pinvoke.net/default.aspx/gdi32/GetDeviceCaps.html
    }

我特别不喜欢使用 hack 的方法Math.Max(dpi1, dpi2),但目前我没有找到更好的解决方案。

至于你原来的问题,在 Win10 上我看不到视觉效果的变化。抱歉,这里不知道。

于 2017-08-10T16:50:17.420 回答