在窗体的"已激活"事件中将其他窗体置于前面时出现问题



我希望 MainForm 在它本身被带到前面时将另外两个单独的表单带到前面。我正在使用 MainForm 的 Activated 事件处理程序来执行此操作,但是将其他两个窗体放在前面并将焦点返回到 MainForm 会导致问题:

private void MainForm_Activated(object sender, EventArgs e)
{
tilemapForm.BringToFront();
tilesetForm.BringToFront();
this.BringToFront();
this.Focus();
}

每当触发此事件时,所有三个窗体的标题栏文本都会消失,并且窗体会疯狂闪烁几秒钟,然后完成。

删除它。Focus() 修复了它,但随后禁用了 MainForm 的控制框,以便通过控制框最小化或关闭它变得不可能。有解决这个难题的方法吗?

Windows 窗口管理器内置了特定的对策来阻止程序崩溃。 没有它们,您的代码注定会随着这个网站的名称而崩溃。 由于您正在编写导致再次引发 Activate 事件的代码,因此递归将吹毁堆栈并使用 StackOverflowException 使您的应用程序崩溃。

它所做的一件事是在触发WM_ACTIVATE消息时完全忽略将另一个窗口移动到前台的任何尝试。 您自己发现了这一点,因此您决定使用 Focus() 方法来强制激活窗口。

不能轻易击败Windows,它也有对策。 它最多会尝试 32 次来满足您的请求。 这就是你所看到的,窗口疯狂地来回交换,直到Windows在决定你的程序陷入无限循环时停止它。 这些是常见的编程错误,结果非常不愉快,堆栈溢出很难诊断。

解决方法非常简单,您需要一个拥有的窗口。 拥有的窗口始终显示在其所有者的顶部,并与所有者一起最小化。 在工具窗口和对话框中很常见。

使用 Show(所有者)重载显示这些工具窗口并删除 Activated 事件处理程序。

发布评论作为答案。

这是什么类型的应用程序?
您如何创建/显示您的两个附加表单?

当您使用Show(IWin32Window)方法显示主窗体时,请尝试将 Main 窗体添加为所属窗体,就像在tilemapForm.Show(this)中一样,如果要在 Main 窗体中创建它们。通过这样做,它将设置表单的Owner属性(您也可以稍后通过直接在表单上设置属性来执行此操作),通过第二个链接中的引用,将为您提供所需的结果:

当一个表单由另一个表单拥有时,它将与所有者表单一起关闭或隐藏。例如,考虑一个名为 Form2 的窗体,该窗体由名为 Form1 的窗体拥有。如果 Form1 已关闭或最小化,则 Form2 也会关闭或隐藏。拥有的表单也永远不会显示在其所有者表单后面。您可以对窗口(如查找和替换窗口)使用拥有的窗体,选择所有者窗体时,这些窗体不应消失。若要确定父窗体拥有的窗体,请使用 OwnedForms 属性。

最新更新