How to get DPI scale for all screens?

后端 未结 1 529
执念已碎
执念已碎 2020-12-01 13:22

I need to get the DPI scale, as set from Control Panel > Display, for each of the screens connected to the computer, even those that do not have a WPF window open. I have se

相关标签:
1条回答
  • 2020-12-01 13:26

    I found a way to get the dpi’s with the WinAPI. As first needs references to System.Drawing and System.Windows.Forms. It is possible to get the monitor handle with the WinAPI from a point on the display area - the Screen class can give us this points. Then the GetDpiForMonitor function returns the dpi of the specified monitor.

    public static class ScreenExtensions
    {
        public static void GetDpi(this System.Windows.Forms.Screen screen, DpiType dpiType, out uint dpiX, out uint dpiY)
        {
            var pnt = new System.Drawing.Point(screen.Bounds.Left + 1, screen.Bounds.Top + 1);
            var mon = MonitorFromPoint(pnt, 2/*MONITOR_DEFAULTTONEAREST*/);
            GetDpiForMonitor(mon, dpiType, out dpiX, out dpiY);
        }
    
        //https://msdn.microsoft.com/en-us/library/windows/desktop/dd145062(v=vs.85).aspx
        [DllImport("User32.dll")]
        private static extern IntPtr MonitorFromPoint([In]System.Drawing.Point pt, [In]uint dwFlags);
    
        //https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510(v=vs.85).aspx
        [DllImport("Shcore.dll")]
        private static extern IntPtr GetDpiForMonitor([In]IntPtr hmonitor, [In]DpiType dpiType, [Out]out uint dpiX, [Out]out uint dpiY);
    }
    
    //https://msdn.microsoft.com/en-us/library/windows/desktop/dn280511(v=vs.85).aspx
    public enum DpiType
    {
        Effective = 0,
        Angular = 1,
        Raw = 2,
    }
    

    There are three types of scaling, you can find a description in the MSDN.

    I tested it quickly with a new WPF application:

    private void Window_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
        var sb = new StringBuilder();
        sb.Append("Angular\n");
        sb.Append(string.Join("\n", Display(DpiType.Angular)));
        sb.Append("\nEffective\n");
        sb.Append(string.Join("\n", Display(DpiType.Effective)));
        sb.Append("\nRaw\n");
        sb.Append(string.Join("\n", Display(DpiType.Raw)));
    
        this.Content = new TextBox() { Text = sb.ToString() };
    }
    
    private IEnumerable<string> Display(DpiType type)
    {
        foreach (var screen in System.Windows.Forms.Screen.AllScreens)
        {
            uint x, y;
            screen.GetDpi(type, out x, out y);
            yield return screen.DeviceName + " - dpiX=" + x + ", dpiY=" + y;
        }
    }
    

    I hope it helps!

    0 讨论(0)
提交回复
热议问题