Windows监视系统的缩放
using System.Runtime.InteropServices;
using System.Text;
internal static class Program
{
private static void Main()
{
Console.OutputEncoding = Encoding.UTF8;
SetProcessDpiAwareness(2); // PROCESS_PER_MONITOR_DPI_AWARE
Dictionary<string, uint> previous = ReadScales();
foreach ((string name, uint dpi) in previous)
Console.WriteLine($"{name}:{ToPercent(dpi):F0}%");
using var changed = new AutoResetEvent(false);
Marshal.ThrowExceptionForHR(RegisterScaleChangeEvent(
changed.SafeWaitHandle.DangerousGetHandle(), out _));
while (changed.WaitOne())
{
//Thread.Sleep(200);
Dictionary<string, uint> current = ReadScales();
foreach ((string name, uint dpi) in current)
{
if (previous.TryGetValue(name, out uint oldDpi) && oldDpi != dpi)
Console.WriteLine(
$"[{DateTime.Now:HH:mm:ss.fff}] {name}:"
+ $"{ToPercent(oldDpi):F0}% -> {ToPercent(dpi):F0}%");
}
previous = current;
}
}
private static Dictionary<string, uint> ReadScales()
{
var result = new Dictionary<string, uint>(StringComparer.OrdinalIgnoreCase);
EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, (monitor, _, _, _) =>
{
var info = new MonitorInfo { Size = (uint)Marshal.SizeOf<MonitorInfo>() };
GetMonitorInfo(monitor, ref info);
Marshal.ThrowExceptionForHR(GetDpiForMonitor(monitor, 0, out uint dpi, out _));
result[info.DeviceName] = dpi;
return true;
}, IntPtr.Zero);
return result;
}
private static double ToPercent(uint dpi) => dpi * 100.0 / 96;
[StructLayout(LayoutKind.Sequential)]
private struct Rect { public int Left, Top, Right, Bottom; }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct MonitorInfo
{
public uint Size;
public Rect Monitor, WorkArea;
public uint Flags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DeviceName;
}
private delegate bool MonitorCallback(IntPtr monitor, IntPtr dc, IntPtr rect, IntPtr data);
[DllImport("user32.dll")]
private static extern bool EnumDisplayMonitors(
IntPtr dc, IntPtr clip, MonitorCallback callback, IntPtr data);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern bool GetMonitorInfo(IntPtr monitor, ref MonitorInfo info);
[DllImport("shcore.dll")]
private static extern int SetProcessDpiAwareness(int awareness);
[DllImport("shcore.dll")]
private static extern int GetDpiForMonitor(
IntPtr monitor, int type, out uint dpiX, out uint dpiY);
[DllImport("shcore.dll")]
private static extern int RegisterScaleChangeEvent(
IntPtr eventHandle, out nuint registrationCookie);
}
h2
注意如果是WPF程序需要增加app.manifest
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
</assembly>
注意

浙公网安备 33010602011771号