You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取WPF应用当前所在显示器的DPI缩放比例?

获取WPF窗口当前所在显示器的DPI缩放比例

问题原因

VisualTreeHelper.GetDpi(Window)返回的是窗口创建时所在显示器的DPI,当窗口移动到其他显示器后,该值不会自动更新,因此你会一直得到主显示器的缩放比例。

两种可行解决方案

方案1:依赖System.Windows.Forms实现

先在项目中安装NuGet包System.Windows.Forms,然后通过Screen类定位当前窗口所在显示器,再计算DPI缩放比例:

using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;

public static class DpiHelper
{
    public static DpiScale GetCurrentMonitorDpi(Window targetWindow)
    {
        // 获取窗口句柄对应的屏幕
        var windowHandle = new System.Windows.Interop.WindowInteropHelper(targetWindow).Handle;
        Screen currentScreen = Screen.FromHandle(windowHandle);
        
        // 计算DPI缩放比例(默认96为100%缩放)
        double dpiScaleX = (96.0 * currentScreen.Bounds.Width) / currentScreen.WorkingArea.Width;
        double dpiScaleY = (96.0 * currentScreen.Bounds.Height) / currentScreen.WorkingArea.Height;
        
        return new DpiScale(dpiScaleX / 96, dpiScaleY / 96);
    }
}

调用示例:

// 在窗口类中调用
var currentDpiScale = DpiHelper.GetCurrentMonitorDpi(this);
double scaleFactor = currentDpiScale.DpiScaleX; // 1.0=100%,2.0=200%

方案2:调用Win32 API实现(无额外依赖)

如果不想引入System.Windows.Forms,可以直接调用Win32原生API获取当前显示器的准确DPI:

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;

public static class DpiHelper
{
    [DllImport("user32.dll")]
    private static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);

    [DllImport("shcore.dll")]
    private static extern int GetDpiForMonitor(IntPtr hmonitor, MonitorDpiType dpiType, out uint dpiX, out uint dpiY);

    public enum MonitorDpiType
    {
        MDT_EFFECTIVE_DPI = 0, // 获取系统生效的DPI(对应显示设置中的缩放比例)
        MDT_ANGULAR_DPI = 1,
        MDT_RAW_DPI = 2
    }

    public static DpiScale GetCurrentMonitorDpi(Window targetWindow)
    {
        var windowHandle = new System.Windows.Interop.WindowInteropHelper(targetWindow).Handle;
        // 获取窗口最近的显示器句柄
        IntPtr monitorHandle = MonitorFromWindow(windowHandle, 0x00000002);

        if (GetDpiForMonitor(monitorHandle, MonitorDpiType.MDT_EFFECTIVE_DPI, out uint dpiX, out uint dpiY) == 0)
        {
            return new DpiScale(dpiX / 96.0, dpiY / 96.0);
        }
        // 调用失败时回退到VisualTreeHelper的结果
        return VisualTreeHelper.GetDpi(targetWindow);
    }
}

补充说明

  • 当窗口跨多个显示器时,上述方法会返回窗口中心或最近的显示器的DPI。
  • 若需要监听窗口跨显示器移动后的DPI变化,可以订阅窗口的LocationChanged事件,在事件触发时重新获取DPI。

内容的提问来源于stack exchange,提问作者wforl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 11:11:24