如何避免调整 MDIParent 表单的大小

How do I avoid MDIParent form from resizing

我正在设计一个 Windows 表单应用程序。我有一个以最大化状态加载的 MDIParent 窗体,并以最大化状态加载其子窗体。但是,当我打开 OpenFileDialog 或任何数据读取器对象时,MDIParent 及其所有窗体和控件都缩小到更小的尺寸。

这个解决方案 Opening child form is causing mdiform to change size and shrink 在我的情况下 apply/work 没有。

这个解决方案 https://support.microsoft.com/en-nz/help/967173/restoring-a-maximized-or-minimized-mdi-parent-form-causes-its-height-t 对我也不起作用。

一些背景:我几乎在我所有的 WinForm 应用程序中都看到过这种行为,但我从来没有热衷于解决它。当我开始调查时,我能够缩小到上面突出显示的原因。有些帖子将其描述为 windows 错误,但只要屏幕分辨率开始超过 1024 (VS 2010) 就我的情况而言,它就一直存在。我希望这不仅仅是一个 windows 错误...

I hoped it is not just a windows bug...

Feature,不是bug,但也不是Winforms程序员很喜欢的。值得注意的是,在过去的几个月里,有几个关于神秘化 window 收缩的问题。我认为它与 Win10 Fall Creators 版本的发布有关。它对遗留的 Win32 api 层进行了深刻的更改,并且引起了很多动荡。

在您的特定情况下,"feature" 由 shell 扩展启用。当您使用 OpenFileDialog 时,它们会被注入到您的进程中。这样做的人非常非常邪恶,并且做了 shell 扩展绝不能做的事情。它调用 SetProcessDPIAware()。值得注意的是,它可能是用 WPF 编写的,它有一个非常狡猾的后门来声明自己是 dpiAware。只需加载 PresentationCore 程序集就足够了。但不限于 WPF 代码,任何代码都可以做到这一点,并且可能已经很长时间未被发现。

追踪这个恶意扩展的一种方法是使用 SysInternals 的 AutoRuns 实用程序。它允许您有选择地禁用扩展。不过也有程序员的办法,你可以在VS中调试这个。

使用项目 > 属性 > 调试选项卡 > 勾选 "Enable native code debugging" 复选框。顺便说一下,在旧的 VS 版本中命名略有不同。然后调试 > 新断点 > 函数断点。函数名称 = user32!SetProcessDPIAware,语言 = C。您可以在 do-nothing WPF 应用程序中进行练习,以确保一切设置正确。为了完整起见,您还可以为新风格的 SetProcessDPIAwareness 添加断点。

按 F5 开始调试并触发 OpenFileDialog.ShowDialog() 调用。现在应该命中断点,使用 Debug > Windows > Call Stack 查看堆栈跟踪。您通常不会在您的案例中看到任何非常可识别的东西,因为恶意代码存在于您没有 PDB 的 DLL 中。但是 DLL 名称和位置(在 Debug > Windows > Modules 中可见)应该有助于识别您需要向其提交错误的人。如果你离不开它,请卸载它。

最后但并非最不重要的一点是,开始创建 dpiAware 的 Winforms 应用程序变得非常重要,这样这样的错误就永远不会出现。您通过 declaring your app to be dpiAware 启动它,因此 DPI 虚拟化被禁用。加上您需要在代码中执行的任何操作,以确保 UI 设计正确缩放。