如何获得所有屏幕的DPI比例?

我需要从控制面板>显示设置中获得每台连接到计算机的屏幕的DPI比例,即使那些没有打开WPF窗口的屏幕也是如此。 我已经看到了一些获得DPI的方法(例如http://dzimchuk.net/post/Best-way-to-get-DPI-value-in-WPF ),但是这些似乎都依赖于Graphics.FromHwnd(IntPtr.Zero)PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice

有没有办法让每个单独的屏幕DPI设置?

背景 – 我正在创build一个布局configuration编辑器,以便用户可以在启动之前设置其configuration。 为此,我绘制每个屏幕相对于彼此。 对于一种configuration,我们使用的是具有比默认DPI比例设置更大的4K显示。 它比其他屏幕的物理显示要小得多,因为它报告与其他屏幕相同的分辨率。

我找到了一种方法来获得与WinAPI的dpi的。 首先需要引用System.DrawingSystem.Windows.Forms 。 从显示区上的一点可以获得显示器句柄的WinAPI – Screen类可以给我们这个点。 然后GetDpiForMonitor函数返回指定监视器的dpi。

 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, } 

有三种缩放类型,你可以在MSDN中找到一个描述 。

我用一个新的WPF应用程序快速测试了它:

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

我希望它有帮助!