调用SaveFileDialog.ShowDialog()时MDI窗体DPI上下文变更,如何阻止?
解决Windows 11下ShowDialog调用后字体尺寸无法恢复的问题
问题原因
Windows 11对DPI上下文的管理逻辑与Windows 10不同,调用ShowDialog时会切换到对话框的DPI上下文,若主窗口与对话框的DPI感知模式不一致,关闭对话框后主窗口无法自动恢复原始DPI上下文,导致字体等UI元素尺寸缩小。
解决方案
统一窗口DPI感知模式
确保主窗口和对话框使用相同的DPI感知级别,推荐使用PerMonitorV2模式。在应用清单文件中添加以下配置:<application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings> <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">PerMonitorV2, true</dpiAware> <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness> </windowsSettings> </application>显式同步对话框与主窗口的DPI上下文
在对话框初始化时,强制继承主窗口的DPI上下文,避免上下文切换异常。以WinForms为例:[DllImport("user32.dll")] private static extern IntPtr GetWindowDpiAwarenessContext(IntPtr hWnd); [DllImport("user32.dll")] private static extern bool SetWindowDpiAwarenessContext(IntPtr hWnd, IntPtr dpiContext); public YourDialogForm(IntPtr mainWindowHandle) { InitializeComponent(); var mainDpiContext = GetWindowDpiAwarenessContext(mainWindowHandle); SetWindowDpiAwarenessContext(this.Handle, mainDpiContext); }关闭对话框后手动刷新主窗口
在对话框关闭事件中,触发主窗口的UI重绘,强制恢复原始尺寸:private void YourDialogForm_FormClosed(object sender, FormClosedEventArgs e) { MainForm.Instance.Invalidate(); MainForm.Instance.Update(); }
注意事项
- 不要混合使用不同的DPI感知模式(如系统级和每窗口级),否则会导致上下文冲突
- 若使用WPF,可通过
VisualTreeHelper.GetDpi获取主窗口DPI,同步到对话框后调用InvalidateVisual()刷新主窗口
内容的提问来源于stack exchange,提问作者Maris Mols
相关产品推荐
相关产品推荐

