C# WinForms固定对话框高DPI缩放时被裁剪的适配方法咨询
问题描述
我有一个固定尺寸的对话框,特定情况下右侧会被隐藏,我在_Load事件中处理其尺寸:
_Mru = Crud.MruTableMethods.GetMruTables(); if (_Mru == null) { this.Size = new Size(275, 261); } else { this.Size = new Size(512, 261); }
若在设计器中定义尺寸则显示正常,但Windows 11用户将「缩放与布局」设置为100%以上时,对话框会被相应比例裁剪;切换回100%缩放则显示正常。
请问是否有方法可让对话框尺寸动态适配系统缩放比例?
环境说明:.NET Framework 4.8,未启用Autosize(固定对话框),暂未了解DPI Awareness,将进一步查看。
解决方案
1. 启用DPI感知(DPI Awareness)
.NET Framework 4.8原生支持DPI感知,先让应用正确识别系统缩放比例,避免Windows自动拉伸导致的裁剪问题。
方式一:通过应用程序清单配置
打开项目的app.manifest文件,找到并取消注释以下代码段,修改为支持每显示器DPI感知:
<application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings> <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware> </windowsSettings> </application>
true/PM表示支持每显示器DPI感知,能适配不同屏幕的缩放比例;若仅需适配系统级缩放,可改为true。
方式二:通过代码设置(适合无法修改清单的场景)
在应用启动入口(如Program.cs的Main方法)添加以下代码:
using System.Windows.Forms; using System.Runtime.InteropServices; [DllImport("user32.dll", SetLastError = true)] private static extern bool SetProcessDpiAwarenessContext(int dpiFlag); private const int DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = 3; static void Main() { // 启用Per-Monitor V2 DPI感知 SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new YourDialogForm()); }
2. 基于DPI缩放计算对话框尺寸
启用DPI感知后,需根据当前屏幕的DPI比例动态计算尺寸,替代固定像素值:
private void YourDialog_Load(object sender, EventArgs e) { // 获取当前窗体的DPI缩放比例(96为100%缩放的基准DPI) float dpiScale = this.DeviceDpi / 96f; _Mru = Crud.MruTableMethods.GetMruTables(); if (_Mru == null) { int scaledWidth = (int)(275 * dpiScale); int scaledHeight = (int)(261 * dpiScale); this.Size = new Size(scaledWidth, scaledHeight); } else { int scaledWidth = (int)(512 * dpiScale); int scaledHeight = (int)(261 * dpiScale); this.Size = new Size(scaledWidth, scaledHeight); } }
3. 处理运行时DPI变化(可选)
若需支持用户在程序运行时调整缩放比例,可订阅窗体的DpiChanged事件,实时重新计算尺寸:
private void YourDialog_DpiChanged(object sender, DpiChangedEventArgs e) { float newDpiScale = e.DeviceDpiNew / 96f; if (_Mru == null) { this.Size = new Size((int)(275 * newDpiScale), (int)(261 * newDpiScale)); } else { this.Size = new Size((int)(512 * newDpiScale), (int)(261 * newDpiScale)); } }
注意:启用Per-Monitor DPI感知后,所有固定尺寸的控件都需要同步按比例调整,确保整体布局适配缩放。
内容的提问来源于stack exchange,提问作者Hambone
相关产品推荐
相关产品推荐

