区分用户关闭窗体和用户关闭应用

本文关键字:用户 应用 窗体 | 更新日期: 2023-09-27 18:36:45

我正在处理以下情况:

  • 当用户尝试关闭我的应用程序中的一个特定表单(通过 Ctrl + F4 或通过专用按钮)时,我需要他在满足某些条件时注销,
  • 因此,我覆盖了OnFormClosed方法,检查条件,如果满足条件,我会显示一个消息框,一旦用户单击"确定",他就会退出我的应用程序,
  • 我正在调查FormClosedEventArgs.CloseReason,并且仅在UserClosing的情况下应用此逻辑,
  • 但是,当用户尝试关闭整个应用程序(通过 Alt + F4 或右上角的"关闭"按钮)时,CloseReason仍然UserClosing,因此他不会关闭应用程序,而是显示消息框并在之后注销应用程序。这不是必需的,因为应用程序关闭显然比注销更强。

所以我的问题 - 有没有一种很好的方法来区分用户关闭表单或用户关闭整个应用程序?我可能可以通过覆盖ProcessCmdKey来设置一些布尔标志来区分 Alt + F4 和 Ctrl + F4,但这不是很好,并且在单击关闭按钮时也无法解决此问题。

区分用户关闭窗体和用户关闭应用

没有好的方法,您必须在 FormClosing 事件开始触发之前检测用户关闭主窗口。 不是 WinForms 中公开的功能,但您可以通过重写主窗口的 Form 类中的 WndProc() 方法轻松添加它。 您对WM_SYSCOMMAND消息感兴趣,SC_CLOSE命令:

    public static bool MainWindowClosing;
    protected override void WndProc(ref Message m) {
        if (m.Msg == 0x112 && (m.WParam.ToInt32() & 0xfff0) == 0xf060) {
            MainWindowClosing = true;
        }
        base.WndProc(ref m);
    }

现在,您可以在其他类中测试该变量:

    protected override void OnFormClosing(FormClosingEventArgs e) {
        if (!Form1.MainWindowClosing && e.CloseReason == CloseReason.UserClosing) {
            // Display your dialog
            //...
        }
        base.OnFormClosing(e);
    }

您需要将 MainWindowClosing 设置回 false,如果您执行任何操作来阻止用户关闭您的应用。 而且我不能不提到在高度安全的Windows登录之外添加登录过程是一个严重的错误,可能会暴露密码。

我认为没有任何内置方法可以做您想要的操作(除了预处理系统击键)。用户在应用程序中启动的任何关闭(MDI 表单除外)都将ÙserClosing

一种解决方法可能是将您的表单嵌入到另一个表单中(Owner设置为外部表单)并检查内部表单关闭是否有FormOwnerClosing原因(如果您单击外部表单上的"X",就会发生这种情况),并检查父表单上的UserClosing,而不是实际表单(内部表单), 但我想说这更不优雅,并且会将您的代码拆分为两种不同的形式。