锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / C#开源 / C#界面控件 / 实时修改MinimumSize控制窗体最小大小失败讨论
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发

锐英源精品原创,禁止全文或局部转载,禁止任何形式的非法使用,侵权必究。点名“简易百科”和闲暇巴盗用锐英源原创内容。

实时修改MinimumSize控制窗体最小大小失败讨论


背景

给上市公司开发一个软件,有复杂UI,里面有窗体最小大小控制,很麻烦,在处理过程中找了些外文资料,翻译下巩固下知识点,也分享给大家。总结意思就是不要用复杂的机制,尽量简单化处理,有些属性会影响Windows消息队列处理。

下面是翻译正文:

 

Winforms >> 在调整大小时更新 MinimumSize 不起作用?

您好, 我遇到了一个问题, 在托管世界中我没有看到任何解决方案。这是重现它的最简单方法:
- 创建一个将 MinimumSize 设置为 100 x 100 的表单。
- 当 ResizeBegin 事件被触发时,将 MinimumSize 更改为 50 x 50。
只要我开始拖动表单的右侧,我希望 新的 MinimumSize 能够激活,但 Windows 会以某种方式跟踪原始的 MinimumSize:我无法将窗口的大小减小到 100 x 100 以下。

使用 SPY++ 检查,我看到表单正确报告了当 WM_GETMINMAXINFO 事件被触发时更新了 MinimumSize :
- WM_MOUSEMOVE
- WM_SIZING
- WM_WINDOWPOSCHANGING
- WM_GETMINMAXINFO
- WM_NCCALCSIZE
- WM_NCPAINT
...
- WM_WINDOWPOSCHANGED
- WM_SIZE
...

然而,只要我移到最左边(宽度将变得小于100 像素宽),我只得到一个紧密的循环:
- WM_MOUSEMOVE
- WM_SIZING
和 WM_SIZING 不再改变。
这是设计使然吗?
我希望能够即时更改最小尺寸在我的实际应用程序中,我需要根据新的窗口大小,随着窗口内容的重新排列,最小值会变得比我最初假设的要小)。
有什么办法可以让我的场景工作吗?即使是肮脏的 WndProc 技巧也可以,只要我能让 Windows 忘记对WM_GETMINMAXINFO 的初始回复!

 

 

 

我根据您的描述进行了测试。我设置了一个 WinForms应用程序,将表单的 MinimumSize 设置为 400 x 400,将表单的 Size 设置为 500 x 500。我处理表单的 ResizeBegin 事件。下面是表单的 ResizeBegin 事件处理程序的代码。
使用 System.Diagnostics;
公共类 Form1 : Form
{
private void Form1_ResizeBegin(object sender, EventArgs e)
{
this.MinimumSize = new Size(100, 100);
// 当程序在调试和以下代码运行时执行后,信息将写入输出窗口。
Debug.WriteLine("resize begin:" +
this.MinimumSize.Width.ToString());
}
}
构建项目并按 F5 运行程序。我发现事实如下。
1.第一次开始调整表格大小的时候,看到Output窗口写着信息:resize begin:100,但是窗体只能最小化到400 x 400。当我开始调整窗体大小的时候第二次,我可以将窗体最小化为 100 x 100。
2. 如果我在调整表单大小之前移动表单,“resize begin:100”信息也会写入输出窗口。然后,如果我调整表格大小,我可以此时将表格最小化为 100 x 100。
到现在为止,我们可以看到即使
修改了表单的MinimumSize属性的值,也会在下一次生效。因此,我建议您在表单的 ResizeBegin、Resize 和 ResizeEnd 事件处理程序之外更改MinimumSize 属性的值。您应该放置此代码的详细位置取决于您的实际需求。

 

 

 

我很高兴你能够重现这个问题。但是,您的解决方案对我不起作用。我真的需要能够在用户拖动窗口的右侧边框时即时更新 MinimumSize。
我现在看到的唯一解决方案是将 MinimumSize 设置为 {0;0},然后以某种方式处理 WM_SIZING 事件,以避免用户使窗口变窄。
但是,如果您能解释一下为什么 Windows 会这样,我会很高兴。我在文档中看不到在调整大小时发送的 WM_* 消息,这表明初始 WM_GETMINMAXINFO 大小应优先于下一个值。
我担心我偶然发现了与此行为有关的 .NET/WinForms 错误。

 

 

WM_GETMINMAXINFO 两次发送:在进入大小/移动模式循环之前和退出前一次。看起来使用了从消息返回的最小轨道大小值。另一方面, OnResizeBegin 被触发以响应WM_ENTERSIZEMOVE 并且显然在此处设置 MinimumSize 为时已晚 - 需要在收到 WM_GETMINMAXINFO 时设置新大小。不幸的是,控件没有相应的事件WM_GETMINMAXINFO,因此需要在 WndProc 覆盖中处理。
这是一个如何做到这一点的例子。
const int WM_GETMINMAXINFO = 0x0024;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_GETMINMAXINFO)
{
this.MinimumSize = new Size(100, 100);
}
base.WndProc(ref m);
我 不知道操作系统的行为是这样还是 Form类中的错误。在类上看,虽然我看不出这样做的原因,如果Windows 操作系统会考虑第二个WM_GETMINMAXINFO 消息返回的最小跟踪大小值。不幸的是,目前我没有时间深入研究这个。

 

 

 

Winforms >> 在调整大小时更新 MinimumSize 不起作用?可能值得尝试使用 WinAPI 重现这一点,但 IMO 并不令人惊讶,并且可能在操作系统级别。 调整大小开始时,IMO 会采用最小大小并“缓存” 。 否则,Windows 将不得不重复阅读此信息,以防调整大小过程改变它(并且会遇到更多有争议
的问题,例如如果新的最小尺寸大于当前 尺寸等...)加上它会产生更多消息,当调整大小不是一项廉价的操作时,这些消息可能更倾向于避免。

 

 

Winforms >> 在调整大小时更新 MinimumSize 不起作用?我的实验表明,当用户调整窗口大小时,第一个 WM_GETMINMAXINFO 消息返回的信息
确实被 Windows 缓存了。随后的 WM_GETMINMAXINFO 不能增加最小大小。 唯一的解决方案是在初始 WM_GETMINMAXINFO 中返回 [1;1] 的最小尺寸,然后处理 WM_SIZING消息,以便根据我自己的最小尺寸信息限制窗口矩形的移动。 因此,这与 WinForms 无关,而与 Windows“优化”消息处理的方式有关。我很想在 MSDN Library 上找到更好的文档。

 

 

Winforms >> 在调整大小时更新 MinimumSize 不起作用?皮埃尔,
看起来你在这里遇到了操作系统限制。Apperanly 您不能为此使用MinimumSize,您应该尝试使用与控件调整大小相关的其余事件。

 

 

Winforms >> 在调整大小时更新 MinimumSize 不起作用?我尝试在 WndProc 中覆盖 WM_GETMINMAXINFO,但没有帮助,因为 Windows 似乎正在缓存此消息返回的第一个大小。 但没关系,正如我在这个现在很深的线程中的其他地方所说,我已经通过将最小大小设置为 1;1 然后
处理 WM_SIZING 消息来解决我的问题,这使我可以非常精确地控制窗口的大小. 我的调整大小逻辑有点奇怪,因为您通常希望窗口的内容具有可预测的最小大小。就我而言,事实并非如此。每当我更改窗口大小时, 窗口可以重新排列以更好地使用可用大小(例如,使用更短的标签、更小的按钮等),这会产生
最初预期的更小的最小尺寸。因此,当用户拖动窗口框架以调整窗体大小时,我会经历一个完整的布局阶段,该阶段可能会更新控件,然后我确定当前的最小尺寸。
当我的问题得到解决时,您可能会认为该线程已关闭。 非常感谢提出建议的各位。 并为我的延迟回复感到抱歉。我的第一个孩子是周一出生的,所以我没有花太多时间上网。


友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内劳动服务器公司办公楼一层