如何获得所有屏幕的DPI标度? [英] How to get DPI scale for all screens?

查看:153
本文介绍了如何获得所有屏幕的DPI标度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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 seen a number of ways to get DPI (for example, http://dzimchuk.net/post/Best-way-to-get-DPI-value-in-WPF) but these seem to be dependent on either Graphics.FromHwnd(IntPtr.Zero) or PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice.

是否可以获取每个屏幕的DPI设置?

Is there a way to get the DPI settings for each individual screen?

背景-我正在创建一个布局配置编辑器,以便用户可以在启动之前设置其配置。为此,我相对于彼此绘制每个屏幕。对于一种配置,我们使用的是4K显示屏,其尺寸大于默认的DPI标尺设置。与其他屏幕相比,它的绘制要比实际显示的要小得多,因为它报告的分辨率与其他屏幕相同。

Background - I am creating a layout configuration editor so that the user can set up their configuration prior to launch. For this, I draw each of the screens relative to each other. For one configuration we are using a 4K display that has a larger than default DPI scale set. It is drawing much smaller than it physically appears in relation to the other screens because it reports as the same resolution as the other screens.

推荐答案

<我找到了一种使用WinAPI获得dpi的方法。
首先需要引用 System.Drawing System.Windows.Forms 。可以从显示区域的某个点使用WinAPI获取监视器句柄- Screen 类可以为我们提供这一点。然后 GetDpiForMonitor 函数返回指定监视器的dpi。

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

有三种缩放类型,您可以找到MSDN中的说明

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

我使用新的WPF应用程序对其进行了快速测试:

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

我希望它会有所帮助!

这篇关于如何获得所有屏幕的DPI标度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆