以上都没有真正禁用 WPF 中的 dpi 缩放。
这是 WPF 在 .net 4.6 中计算 dpi 缩放的方式:1) HwndTarget,它是所有视觉对象使用的 CompositionTarget。2) UIElement 是视觉效果的基类,也是存储dpi缩放计算结果的地方。
WPF 确保在准备第一个视觉对象时计算一次全局缩放。这由 HwndTarget {private static bool _setDpi = true} 上的布尔值控制。计算 dpi 后,_setDpi 字段设置为 false,并且 dpi 感知方法是使用像这样的代码的快捷方式 {if (!HwndTarget._setDpi) return;}
每个 UIElement 都会发生类似的事情,它具有相同的模式,使用 {private static bool _setDpi = true} 允许第一次计算。
下一个检查来自 ProcessDpiAwareness,它可以是 None、Process 或 Monitor。为了阻止 WPF 考虑单个监视器,您需要将 ProcessDpiAwareness 设置为 Process (int 1)。
最后,当计算 dpi 时,结果存储在 UIElement 上称为 DpiScaleXValues 和 DpiScaleYValues 的 2 个列表中。因此,您需要将这些初始化为正确的值。
这是我自己使用的示例代码(仅适用于 .net 4.6):
var setDpiHwnd = typeof(HwndTarget).GetField("_setDpi", BindingFlags.Static | BindingFlags.NonPublic);
setDpiHwnd?.SetValue(null, false);
var setProcessDpiAwareness = typeof(HwndTarget).GetProperty("ProcessDpiAwareness", BindingFlags.Static | BindingFlags.NonPublic);
setProcessDpiAwareness?.SetValue(null, 1, null);
var setDpi = typeof(UIElement).GetField("_setDpi", BindingFlags.Static | BindingFlags.NonPublic);
setDpi?.SetValue(null, false);
var setDpiXValues = (List<double>)typeof(UIElement).GetField("DpiScaleXValues", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null);
setDpiXValues?.Insert(0, 1);
var setDpiYValues = (List<double>)typeof(UIElement).GetField("DpiScaleYValues", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null);
setDpiYValues?.Insert(0, 1);