简体   繁体   English

区分用户关闭表单和用户关闭应用程序

[英]Distinguish between user closing form and user closing app

I am dealing with the following scenario: 我正在处理以下情况:

  • When user is trying to close one particular form in my application (via Ctrl + F4 or via dedicated button) I need him to log out when certain conditions are met, 当用户尝试在我的应用程序中关闭某个特定表单时(通过Ctrl + F4或通过专用按钮),我需要他在满足某些条件时注销,
  • Therefore I overrode OnFormClosed method, check the conditions, if they are met I display a message box and once user clicks OK, he is logged out of my application, 因此,我覆盖了OnFormClosed方法,检查条件,如果满足条件,我会显示一个消息框,并且一旦用户单击“确定”,他就退出了我的应用程序,
  • I am investigating FormClosedEventArgs.CloseReason and only apply this logic in situation of UserClosing , 我正在调查FormClosedEventArgs.CloseReason ,仅在UserClosing情况下应用此逻辑,
  • However, when user tries to close the entire application (via Alt + F4 or Close button in upper right corner), the CloseReason is still UserClosing , so instead of shutting down the application, he is presented the messagebox and logged out of application afterwards. 但是,当用户尝试关闭整个应用程序时(通过Alt + F4或右上角的“关闭”按钮), CloseReason仍然是UserClosing ,因此UserClosing关闭应用程序外,他还看到了消息框并随后退出了应用程序。 This is not desired because application shutdown is obviously stronger than log out. 这是不希望的,因为应用程序关闭显然比注销更强大。

So my question - is there a nice way to distiguish between user closing a form or user closing an entire application? 所以我的问题-在关闭用户表单或关闭整个应用程序之间是否有一种很好的区分方法? I could probably set some bool flags by overriding ProcessCmdKey to distinguish between Alt + F4 and Ctrl + F4 , but that is not very nice and also doesn't solve this issue when clicking the close button. 我可能可以通过覆盖ProcessCmdKey来设置一些bool标志,以区分Alt + F4Ctrl + F4 ,但这不是很好,并且在单击关闭按钮时也无法解决此问题。

There is no nice way, you have to detect the user closing your main window before the FormClosing events starts firing. 没有很好的方法,您必须检测到用户在FormClosing事件开始触发之前关闭了主窗口。 Not a capability that's exposed in Winforms, but you can easily add it by overriding the WndProc() method in your main window's Form class. 这不是Winforms中公开的功能,但是您可以通过覆盖主窗口的Form类中的WndProc()方法来轻松添加它。 You're interested in the WM_SYSCOMMAND message, SC_CLOSE command: 您对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);
    }

Now you can test that variable in your other classes: 现在,您可以在其他类中测试该变量:

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

You need to set MainWindowClosing back to false if you do anything to prevent the user from closing your app. 如果要执行任何防止用户关闭应用程序的操作,则需要将MainWindowClosing设置为false And I would remiss to not mention that adding a login procedure beyond the highly secure Windows login is a grave mistake that is likely to expose passwords. 而且,我不会忘记,除了高度安全的Windows登录之外,添加登录过程是一个严重的错误,很可能会泄露密码。

I don't think there's any built-in method to do what you want (other than preprocessing system keystrokes). 我认为没有任何内置方法可以完成您想要的事情(预处理系统按键除外)。 Any closing initiated by the user in the application (except for MDI forms) is going to be ÙserClosing . 用户在应用程序中发起的任何关闭(MDI表单除外)都将是ÙserClosing

One workaround could be having your form embedded in another form (with the Owner set to the outer form) and check if the inner form closing is with a FormOwnerClosing reason (that'd happen if you click the 'X' on the outer form), and check for UserClosing on the parent form, instead of the actual form (the inner one), but I'd say that's even less elegant and would split your code around two different forms. 一种解决方法是将您的表单嵌入另一种表单中(将Owner设置为外部表单),并检查内部表单关闭是否具有FormOwnerClosing原因(如果您在外部表单上单击“ X”,就会发生这种情况) ,然后检查父表单(而不是实际表单(内部表单))上的UserClosing ,但我想说这还不够优雅,并且会将您的代码分为两种不同的形式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM