如何阻止C# WinForms子窗体在Win11平板模式下最大化打开?
Windows 11平板上WinForms自定义对话框自动最大化的解决方法
问题描述
我有一个Windows Forms应用程序,通过调用Form.ShowDialog()打开子窗体。当该应用在搭载Windows 11的平板设备上运行时,子窗体总是以最大化模式打开,不符合预期。
测试代码如下:
namespace DialogSizeTest { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { // 即使在搭载Windows 11的松下平板上,此对话框也以“正常”大小显示。 var dlg = new OpenFileDialog(); dlg.ShowDialog(this); } private void button2_Click(object sender, EventArgs e) { // 在搭载Windows 11的松下平板上,此对话框会最大化显示。为什么? var dlg = new MyOwnDialog(); dlg.ShowDialog(this); } } }
其中MyOwnDialog()是仅包含一个标签的简单Windows窗体。
测试环境及结果
| 测试编号 | 硬件 | Windows版本 | 主窗体大小 | 打开文件对话框大小 | 自定义对话框大小 |
|---|---|---|---|---|---|
| 1 | 笔记本电脑 | 11 | 正常 | 正常 | 正常 |
| 2 | 平板设备 | 10(平板模式开启) | 最大化 | 正常 | 正常 |
| 3 | 平板设备 | 10(平板模式关闭) | 正常 | 正常 | 正常 |
| 4 | 平板设备 | 11 | 最大化 | 正常 | 最大化 |
测试1、2、3结果符合预期,但测试4中自定义对话框意外最大化。
解决方法
1. 显式设置窗体状态与大小
在显示自定义对话框前,强制指定窗口状态为正常,并设置固定尺寸:
var dlg = new MyOwnDialog(); dlg.WindowState = FormWindowState.Normal; // 根据需求设置目标大小 dlg.Size = new Size(400, 300); dlg.ShowDialog(this);
也可以在MyOwnDialog的构造函数中预先配置:
public MyOwnDialog() { InitializeComponent(); this.WindowState = FormWindowState.Normal; this.MaximizeBox = false; // 可选,直接禁用最大化按钮 }
2. 修改应用清单禁用平板优化
Windows 11针对平板模式下的WinForms应用有自动最大化的优化逻辑,可通过app.manifest禁用:
打开项目中的app.manifest(若无则右键项目添加「应用程序清单文件」),添加以下配置:
<application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings> <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware> <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness> <tabletMode xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">false</tabletMode> </windowsSettings> </application>
3. 重写WndProc限制窗口最大尺寸
通过处理WM_GETMINMAXINFO消息,强制限制窗口的最大尺寸,避免系统自动最大化:
protected override void WndProc(ref Message m) { const int WM_GETMINMAXINFO = 0x0024; if (m.Msg == WM_GETMINMAXINFO) { MINMAXINFO minMaxInfo = (MINMAXINFO)Marshal.PtrToStructure(m.LParam, typeof(MINMAXINFO)); // 将最大尺寸设为窗体初始大小 minMaxInfo.ptMaxSize.X = this.Size.Width; minMaxInfo.ptMaxSize.Y = this.Size.Height; minMaxInfo.ptMaxTrackSize.X = this.Size.Width; minMaxInfo.ptMaxTrackSize.Y = this.Size.Height; Marshal.StructureToPtr(minMaxInfo, m.LParam, true); } base.WndProc(ref m); } // 定义所需的结构体 [StructLayout(LayoutKind.Sequential)] private struct POINT { public int X; public int Y; public POINT(int x, int y) { X = x; Y = y; } } [StructLayout(LayoutKind.Sequential)] private struct MINMAXINFO { public POINT ptReserved; public POINT ptMaxSize; public POINT ptMaxPosition; public POINT ptMinTrackSize; public POINT ptMaxTrackSize; }
内容的提问来源于stack exchange,提问作者arnadan
相关产品推荐
相关产品推荐

