WinForms 中的 Per-Monitor V2 DPI 感知不会使用非环境字体重新缩放控件

问题描述

我的任务是为面向 .NET 4.7.2 的旧版 WinForms 应用程序添加对 Per-Monitor V2 DPI 感知的支持。我知道这是一个复杂的问题,我已经在 StackOverflow 和 MSDN 上阅读了很多关于这个主题文章。使用测试项目,我已经掌握了基础知识。测试应用程序会随着 DPI 的变化而重新调整。

这是我的问题:旧版软件在每个表单上都包含大量自定义字体(不同的样式和大小),当 DPI 在运行时发生变化时,我无法重新调整这些字体。似乎我可以在 Form 上设置我喜欢的任何字体,如果我在 Form 上使用 AutoScaleMode.Dpi,它会正确地重新缩放。但是,一旦我在子控件上设置了自定义字体,就不会对该控件应用重新缩放。随着 DPI 的变化,大小保持不变。如果 DPI 不变,这不是问题。只有在具有不同 DPI 设置的显示器之间移动或在运行时更改显示器的 DPI 设置时才会出现此问题。 (注意:所有字体更改都发生在设计器中)

这是一个例子:

显示器 1 - 96 DPI

Monitor 1 - 96 DPI

显示器 2 - 144 DPI

Monitor 2 - 144 DPI

您可以看到 checkBox3 为粗体,并在 96 DPI 下正确缩放。但是,当我将应用程序拖动到监视器 2 时,checkBox3 保持未缩放,因此现在它比其他文本小。

重新缩放的损失对我来说确实有意义,因为在子控件上设置自定义字体会破坏环境字体关系。根据我的测试,当 DPI 发生变化时,表单实际上会获得具有新 DPI 缩放点大小的新字体。不更新不使用该字体的控件是有道理的。但是没有办法要求所有控件重新缩放吗?

我一直试图在上述测试项目 (C# .NET 4.7.2) 中解决这个问题。我发现使自定义字体重新缩放的唯一方法是在 DPI 更改时使用 DPI 更改事件手动重新创建自定义字体。

private void CheckBox3_DpiChangedAfterParent(object sender,EventArgs e)
{
    checkBox3.Font = new Font(Font.FontFamily,checkBox3.Font.SizeInPoints * _dpiScaleFactor,checkBox3.Font.Style);
}

private void Form1_DpiChanged(object sender,DpiChangedEventArgs e)
{
   _dpiScaleFactor = (float)e.DeviceDpiNew / e.DeviceDpiOld;
}

显示器 2 - 144 DPI(手动调整字体大小)

Monitor 2 - 144 DPI (with manually font resizing)

所以这似乎确实有效。当然还有更好的方法。我在这里错过了什么?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)