获取Windows单显示器缩放比例的技术咨询
获取Windows显示设置中的显示器缩放比例(.NET 6 C#)
核心解决思路:正确调用GetDpiForMonitor接口
你遇到的问题核心是没指定正确的DPI类型参数。GetDpiForMonitor返回的三个DPI值对应不同用途:
MDT_RAW_DPI:显示器物理硬件DPI,和系统缩放设置无关MDT_ANGULAR_DPI:基于视觉角度计算的DPI,也不对应系统缩放MDT_EFFECTIVE_DPI:直接对应当前系统显示设置里的缩放比例,这才是你需要的参数
系统默认100%缩放对应96DPI,缩放比例计算公式为:缩放百分比 = (EffectiveDPI值 / 96) * 100%
比如120DPI对应125%,144DPI对应150%,完全匹配系统设置的数值。
具体实现代码
先定义必要的WinAPI P/Invoke声明:
using System; using System.Runtime.InteropServices; public static class DisplayScaleHelper { public enum MonitorDpiType : int { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2 } [DllImport("user32.dll")] public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumProc lpfnEnum, IntPtr dwData); public delegate bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData); [StructLayout(LayoutKind.Sequential)] public struct RECT { public int left; public int top; public int right; public int bottom; } [DllImport("shcore.dll")] public static extern int GetDpiForMonitor(IntPtr hmonitor, MonitorDpiType dpiType, out uint dpiX, out uint dpiY); }
再编写获取所有显示器缩放比例的方法:
public static void GetAllDisplayScales() { DisplayScaleHelper.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, delegate(IntPtr hMonitor, IntPtr hdcMonitor, ref DisplayScaleHelper.RECT lprcMonitor, IntPtr dwData) { if (DisplayScaleHelper.GetDpiForMonitor(hMonitor, DisplayScaleHelper.MonitorDpiType.MDT_EFFECTIVE_DPI, out uint dpiX, out uint dpiY) == 0) { // 多数情况下X/Y方向DPI一致,取任一计算即可 double scalePercent = Math.Round((dpiX / 96.0) * 100); Console.WriteLine($"显示器句柄:{hMonitor},系统缩放比例:{scalePercent:N0}%"); } return true; }, IntPtr.Zero); }
常见误区说明
- 不要依赖
dmPelsWidth:这个值是系统缩放后的逻辑分辨率,和物理分辨率的比值虽然能算出缩放,但受应用DPI感知设置影响,不如直接取Effective DPI准确。 - 必须指定
MDT_EFFECTIVE_DPI:另外两个DPI类型是硬件或视觉相关的,和系统显示设置里的100%/125%这类缩放值完全不对应。
窗口程序可选方案
如果你的应用是带窗口的程序,也可以通过窗口句柄直接获取对应显示器的缩放:
[DllImport("user32.dll")] public static extern uint GetDpiForWindow(IntPtr hwnd); // 使用示例 public static double GetCurrentWindowScale(IntPtr windowHandle) { uint dpi = GetDpiForWindow(windowHandle); return Math.Round((dpi / 96.0) * 100); }
内容的提问来源于stack exchange,提问作者cheesemp
相关产品推荐
相关产品推荐

