簡體   English   中英

WinForms:如何修復 Forms 在具有不同分辨率/縮放的高 DPI、多監視器環境 (PerMonitorV2) 中的不正確縮放

[英]WinForms: How to fix incorrect scaling of Forms in high-DPI, multi-monitor environments (PerMonitorV2) with different resolution/scaling

在 Winforms 應用程序中,我遵循了how-to-write-winforms-code-that-auto-scales-to-system-font-and-dpi-settings.Net Framework high-dpi support中的一般指導來啟用 PerMonitorV2 DPI 縮放。 我在 Windows 10 周年更新 (1607) 之后的系統上使用 .NET Framework 4.8 以利用最新的高 DPI 支持功能。

如果應用程序在主監視器或與主監視器具有相同縮放比例的任何監視器上啟動,DPI 縮放看起來很棒,但如果任何表單(應用程序的主表單或二級頂級表單)是第一個,則縮放完全錯誤顯示在與主顯示器具有不同 DPI 的顯示器上。 例如,如果應用程序在 4k/250% 縮放的筆記本電腦屏幕上啟動(其他四台顯示器的縮放比例為 1920x1080/100%),那么表單會在 4k 屏幕上以 1:1 的比例顯示並顯示為微小的 1該屏幕上的平方英寸(只有 Title 和 MenuBar 正確縮放): Image Showing Bad Scaling

該問題似乎是由於在這些情況下未正確設置 Form 的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();
    ...

對於應用程序生成的輔助 Forms,我發現如果我首先在主屏幕上顯示它們,然后在包含應用程序主窗體的屏幕上隱藏並重新顯示它們(我希望它們顯示),它們會正確縮放。 在某些情況下,我發現只調用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();
    }

這個解決方案並不理想,因為表單會在另一個看起來相當笨拙的屏幕上短暫閃爍。 但是,無論應用程序在哪個監視器上啟動,此解決方案似乎都可以正確縮放應用程序中的所有 Forms。 到目前為止,我已經在兩種不同的多顯示器配置上對其進行了測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM