WPF 获取系统 DPI 的多种方法

原文:WPF 获取系统 DPI 的多种方法

由于 WPF 的尺寸单位和系统的 DPI 相关,我们有时需要获取 DPI 值来进行一些界面布局的调整,本文汇总了一些 WPF 程序中获取系统 DPI 的方法。

首先,定义如下结构体来分别保存 X 方向 和 Y 方向的分量值,通常情况下两个值是一致的。

public struct Dpi
{
    public double X { get; set; }

    public double Y { get; set; }

    public Dpi(double x, double y)
    {
        X = x;
        Y = y;
    }
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

CompositionTarget

public static Dpi GetDpiFromVisual(Visual visual)
{
    var source = PresentationSource.FromVisual(visual);

    var dpiX = 96.0;
    var dpiY = 96.0;

    if (source?.CompositionTarget != null)
    {
        dpiX = 96.0 * source.CompositionTarget.TransformToDevice.M11;
        dpiY = 96.0 * source.CompositionTarget.TransformToDevice.M22;
    }

    return new Dpi(dpiX, dpiY);
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Win32 API

private const int LOGPIXELSX = 88;
private const int LOGPIXELSY = 90;

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

[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hWnd);

[DllImport("user32.dll")]
private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDc);

public static Dpi GetDpiByWin32()
{
    var hDc = GetDC(IntPtr.Zero);

    var dpiX = GetDeviceCaps(hDc, LOGPIXELSX);
    var dpiY = GetDeviceCaps(hDc, LOGPIXELSY);

    ReleaseDC(IntPtr.Zero, hDc);
    return new Dpi(dpiX, dpiY);
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

SystemParameters

public static Dpi GetDpiBySystemParameters()
{
    const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Static;

    var dpiXProperty = typeof(SystemParameters).GetProperty("DpiX", bindingFlags);
    var dpiYProperty = typeof(SystemParameters).GetProperty("DpiY", bindingFlags);

    var dpiX = 96.0;
    var dpiY = 96.0;

    if (dpiXProperty != null)
    {
        dpiX = (double)dpiXProperty.GetValue(null, null);
    }

    if (dpiYProperty != null)
    {
        dpiY = (double)dpiYProperty.GetValue(null, null);
    }

    return new Dpi(dpiX, dpiY);
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

Graphics

添加 System.Drawing 引用

public static Dpi GetDpiByGraphics()
{
    double dpiX;
    double dpiY;

    using (var graphics = Graphics.FromHwnd(IntPtr.Zero))
    {
        dpiX = graphics.DpiX;
        dpiY = graphics.DpiY;
    }

    return new Dpi(dpiX, dpiY);
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

ManagementClass

System.Management 引用

public static Dpi GetDpiByManagement()
{
    var dpiX = 96.0;
    var dpiY = 96.0;

    using (var mc = new ManagementClass("Win32_DesktopMonitor"))
    {
        using (var moc = mc.GetInstances())
        {
            // there may be many, to filter the ones you are interested in
            foreach (var mo in moc)
            {
                dpiX = double.Parse(mo.Properties["PixelsPerXLogicalInch"].Value.ToString());
                dpiY = double.Parse(mo.Properties["PixelsPerYLogicalInch"].Value.ToString());
            }
        }
    }

    return new Dpi(dpiX, dpiY);
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

处于 跨平台、多屏幕、性能 等方面的综合考虑,推荐使用 CompositionTarget 方法。另外,监听系统 DPI 变化的方法:

SystemEvents.DisplaySettingsChanged - SystemEvents Class

WM_DPICHANGED message

参考资料

Best way to get DPI value in WPF

How can I get the DPI in WPF?

————————————————

版权声明:本文为CSDN博主「Iron_Ye」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/Iron_Ye/article/details/83053393


JackieLaw1990

发布了3 篇原创文章 · 获赞 0 · 访问量 968

私信
关注

原文地址:https://www.cnblogs.com/lonelyxmas/p/12075358.html

时间: 2024-08-27 02:32:47

WPF 获取系统 DPI 的多种方法的相关文章

php获取当前页面地址多种方法(附教程)

php获取当前页面地址多种方法 有关php取得当前页面地址的多种方法,包括收集的一些实例教程,记录下. 参考教程: PHP中获取当前页面的完整URL php获取当前页面地址参数的三种方法 php获取url地址栏与详细参数实例 php获取当前域名与url地址的例子 php获取当前URL地址 php取得当前页面完整url地址的例子 PHP代码: //获取域名或主机地址 echo $_SERVER['HTTP_HOST']."<br>"; #localhost //获取网页地址

C# API 获取系统DPI缩放倍数跟分辨率大小

原文:C# API 获取系统DPI缩放倍数跟分辨率大小 using System; using System.Drawing; using System.Runtime.InteropServices; namespace XYDES { public class PrimaryScreen { #region Win32 API [DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr ptr); [DllImport(&

Darwin获取系统处理器数量的方法

阅读Darwin源码的时候看到这个方法,感觉挺有用处,且考虑了多种平台下的实现方式,直接贴代码,以后说不定会用到~ 单一种平台下的实现方法可能很容易,但是把这些个系统都收集在一起,在一个函数中实现还是极好的 UInt32 OS::GetNumProcessors() { #if (__Win32__) SYSTEM_INFO theSystemInfo; ::GetSystemInfo(&theSystemInfo); return (UInt32)theSystemInfo.dwNumberO

通过Rest service获取后台数据的多种方法

开发在开发网页的时候用Rest service来获取Json数据,然后对数据进行组织后显示在网页上,那我们在做自动化测试的时候对这种情况需要验证的有以下2点: 1. Service的数据可以正常被获取到 2. 数据都正确的被网页显示出来并且显示在正确的地方 那么要做这2点验证,自动化测试的具体步骤如下 1. 通过方法获取到这个service中的数据(json,xml) 2.通过解析json或xml来对数据进行整理和提取 3. 验证这些整理过的数据都显示在正确的地方 后面2点再说,对于第一点获取的

C#获取系统时间的所有方法

C# 获取时间,日期 //C# 里内置的 DateTime 基本上都可以实现这些功能,巧用 DateTime 会使你处理这些事来变轻松多了       // 今天                  DateTime.Now.Date.ToShortDateString();     // 昨天,就是今天的日期减一                  DateTime.Now.AddDays(-1).ToShortDateString();     // 明天,同理,加一              

Android : apk系统签名的多种方法

方法一:使用自己的Android签名工具给apk重新签名: (1)该目录下有 media.pk8.media.x509.pem.platform.pk8.platform.x509.pem.shared.pk8.shared.x509.pem.testkey.pk8.testkey.x509.pem等签名文件,不同的签名文件,对应不同的权限.Android默认的签名文件为testkey.pk8.testkey.x509.pem. (2) Android自带的签名工具为 signapk.jar,

oc之获取系统当前时间的方法

NSDate *date = [NSDate date];//这个是NSDate类型的日期,所要获取的年月日都放在这里: NSCalendar *cal = [NSCalendar currentCalendar]; unsigned int unitFlags = NSCalendarUnitYear|NSCalendarUnitMonth| NSCalendarUnitDay;//这句是说你要获取日期的元素有哪些.获取年就要写NSYearCalendarUnit,获取小时就要写NSHourC

android获取系统应用大小的方法

<span style="font-family: Arial, Helvetica, sans-serif;"><span style="font-size:18px;"></span></span><pre name="code" class="java">List<PackageInfo> packages = getPackageManager()

IOS,中获取系统内存占有率的方法

#import <mach/mach.h> - (float)__getMemoryUsedPer1 { struct mach_task_basic_info info; mach_msg_type_number_t size = sizeof(info); kern_return_t kerr = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &size); if (kerr ==