消失的FormClosing / FormClosed事件

时间:2012-10-15 08:41:36

标签: c# .net winforms winapi events

以下代码段可能看起来很奇怪,但它是一种非常简单的方法来重现与不同应用程序的复杂交互问题。

示例应用程序有两种形式,两种形式都注册FormClosing和FormClosed事件,只是在那里执行Debug.WriteLine。

主要功能:

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Form2 form2 = new Form2();
    form2.Show();
    Application.Run(new Form1());
}

当我关闭Form2时,我按预期收到事件。当我关闭Form1时,应用程序退出,Form2也关闭。但是:Form2的事件不会发生。

我覆盖了Form2的WndProc。当我关闭Form2时,我会收到

15.10.2012 10:25:04 WndProc - WM_CLOSE
15.10.2012 10:25:04 OnClosing
15.10.2012 10:25:04 Form2_FormClosing
15.10.2012 10:25:04 OnClosed
15.10.2012 10:25:04 Form2_FormClosed
...
15.10.2012 10:25:04 WndProc - WM_DESTROY
...
15.10.2012 10:25:04 WndProc - WM_NCDESTROY

当我关闭Form1时,Form2没有收到WM_CLOSE。但是收到WM_DESTROY和WM_NCDESTROY。

编辑: 获得这种奇怪行为的另一种方法如下: 该项目有三种形式,Form1和Form2各有一个用于打开下一个表单的按钮。在form2的按钮单击事件中,执行:

Form3 frm3 = new Form3();
frm3.Parent = null;
frm3.Show(null);

再次,如上所述注册事件处理程序。关闭form2时,应用程序保持运行(仍显示form1),但form3也会关闭,并且没有收到WM_CLOSE事件。请注意,我已将表单的Parent和Owner都设置为null。

这种奇怪行为的原因是什么?

1 个答案:

答案 0 :(得分:3)

发送

WM_CLOSE消息以选择取消关闭。请参阅此流程图:

enter image description here

因此,无论如何,当窗口即将被销毁时,此消息中没有必要。这是设计行为。当您关闭主要应用程序时,将调用Application.ThreadExit方法。它描述为:

  

退出当前线程上的消息循环并关闭所有窗口   线程。

如果您希望所有已打开的表单都收到WM_CLOSE消息,则需要使用Application.Exit代替:

  

通知所有消息泵必须终止,然后关闭   消息处理完毕后的所有应用程序窗口。

因此,只需订阅Form1_FormClosing事件并通知所有打开的窗口关闭:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    Application.Exit();
}