Joh*_*hnC 5 c# scaling highdpi winforms
在 Winforms 应用程序中,我遵循了如何编写自动缩放到系统字体和 dpi 设置的 winforms 代码以及.Net Framework 高 dpi 支持中的一般指南来启用 PerMonitorV2 DPI 缩放。我在 Windows 10 周年更新 (1607) 后的系统上使用 .NET Framework 4.8,以利用最新的高 DPI 支持功能。
如果应用程序在主监视器或与主监视器具有相同缩放比例的任何监视器上启动,则 DPI 缩放看起来很棒,但如果任何表单(应用程序的主表单或辅助顶级表单)首先启动,则缩放完全错误显示在 DPI 与主显示器不同的显示器上。例如,如果应用程序在 4k/250% 缩放笔记本电脑屏幕上启动(其他四台显示器的缩放比例为 1920x1080/100%),则表单会在 4k 屏幕上以 1:1 缩放比例显示,并显示为一个小 1该屏幕上的平方英寸(仅标题和菜单栏正确缩放):图像显示错误缩放。
该问题似乎是由于在这些情况下未正确设置表单的 CurrentAutoScaleDimensions 而引起的。它们似乎设置为主屏幕的当前“尺寸” ,而不是显示表单的屏幕。但是,如果表单首先显示在主屏幕上,然后移动到具有不同 DPI 的屏幕,则 CurrentAutoScaleDimensions会正确更新以反映目标屏幕的实际 DPI,并且表单会正确缩放。因此,例如,如果我将主屏幕设置为 4k/250% 屏幕,然后在 1920x1080/100% 屏幕上启动应用程序,则 CurrentAutoScaleDimensions(错误)将设置为 4k/250% 屏幕和结果表格的尺寸被极度放大。但是,如果我在主 4k/250% 屏幕上启动该应用程序,它在首次显示时会正确缩放,然后在拖动到其他显示器(或返回)时也会正确缩放。总之,当第一次显示表单时,CurrentAutoScaleDimensions似乎总是设置为主显示器尺寸,而不是显示表单的屏幕尺寸。
有谁知道这种情况的补救措施?
我能想到的最佳解决方案是强制应用程序始终在主屏幕上启动,无论它是从哪个屏幕启动的。这似乎解决了主窗体初始缩放的所有问题,以及在监视器之间拖动时的所有后续缩放似乎都很好:
public Form1()
{
this.Font = SystemFonts.IconTitleFont;
// Force the main Form of the app to always open on the primary screen
// to get scaling to work.
this.Location = Screen.PrimaryScreen.WorkingArea.Location;
this.StartPosition = FormStartPosition.Manual;
InitializeComponent();
...
Run Code Online (Sandbox Code Playgroud)
对于应用程序生成的辅助表单,我发现如果我首先在主屏幕上显示它们,然后在包含应用程序主表单的屏幕上隐藏并重新显示它们(我希望它们显示在其中),它们就会正确缩放。在某些情况下,我发现仅调用f.PerformLayout()就足够了,而不是在主屏幕上实际显示表单,但这并非在所有情况下都有效。
private void secondFormToolStripMenuItem_Click(object sender, EventArgs e)
{
FormExtra f = new FormExtra(this);
// First display the Form on the primary screen to make scaling correct
f.StartPosition = FormStartPosition.Manual;
f.Location = Screen.PrimaryScreen.WorkingArea.Location;
f.Show();
// Then hide it and move it where we really want it
f.Hide();
f.StartPosition = FormStartPosition.CenterParent;
f.ShowDialog();
}
Run Code Online (Sandbox Code Playgroud)
该解决方案并不理想,因为表单会在另一个屏幕上短暂闪烁,这看起来相当笨拙。但是,此解决方案似乎确实可以正确缩放应用程序中的所有表单,无论应用程序在哪个监视器上启动。到目前为止,我已经在两种不同的多显示器配置上对其进行了测试。