27

How can I detect how a windows form is being closed? For example, how do I find out whether the user has clicked on a button which closes the form or if the user clicks on the "X" in the upper-right? Thank you.

Update:

Forgot to mention that the button calls the Application.Exit() method.

Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
user
  • 16,429
  • 28
  • 80
  • 97
  • 1
    [Detect if the Form has closed using X button/Alt+F4/System menu or using Close method](https://stackoverflow.com/a/58790227/3110834) – Reza Aghaei Nov 26 '19 at 04:20

3 Answers3

36

As bashmohandes and Dmitriy Matveev already mentioned the solution should be the FormClosingEventArgs. But as Dmitriy also said, this wouldn't make any difference between your button and the X in the right upper corner.

To distinguish between these two options, you can add a boolean property ExitButtonClicked to your form and set it to true in the button Click-Event right before you call Application.Exit().

Now you can ask this property within the FormClosing event and distinguish between those two options within the case UserClosing.

Example:

    public bool UserClosing { get; set; }

    public FormMain()
    {
        InitializeComponent();

        UserClosing = false;
        this.buttonExit.Click += new EventHandler(buttonExit_Click);
        this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
    }

    void buttonExit_Click(object sender, EventArgs e)
    {
        UserClosing = true;
        this.Close();
    }

    void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        switch (e.CloseReason)
        {
            case CloseReason.ApplicationExitCall:
                break;
            case CloseReason.FormOwnerClosing:
                break;
            case CloseReason.MdiFormClosing:
                break;
            case CloseReason.None:
                break;
            case CloseReason.TaskManagerClosing:
                break;
            case CloseReason.UserClosing:
                if (UserClosing)
                {
                    //what should happen if the user hitted the button?
                }
                else
                {
                    //what should happen if the user hitted the x in the upper right corner?
                }
                break;
            case CloseReason.WindowsShutDown:
                break;
            default:
                break;
        }

        // Set it back to false, just for the case e.Cancel was set to true
        // and the closing was aborted.
        UserClosing = false;
    }
Oliver
  • 43,366
  • 8
  • 94
  • 151
  • 2
    Oliver, you have serious mistake now. If you call Application.Exit from click handler when close reason will be CloseReason.ApplicationExitCall and if(UserClosing) condition will be useless. You should call this.Close() method in click handler to match UserClosing switch case or you need to move if statement to the outside of switch statement. – okutane Oct 26 '09 at 10:46
  • If the form is ever not closed once you're in Form1_FormClosing -- perhaps there's a "did you mean to exit?" question -- something needs to set the UserClosing flag variable to false or the next time it might falsely be true. – J.Merrill Aug 07 '12 at 16:00
  • Easiest way is to set the DialogResult property to something other than None for your 'normal' close button. In Form_Closing you can check for these results and assume DialogResult.None is the 'X' button in the form control box. Kind of a stupid implementation on Microsoft's part to not have a specific handling for the 'X' button built-in. – B H Sep 26 '18 at 00:32
5

You can check CloseReason property of FormClosingEventArgs in FormClosing event handler to check some of the possible cases. However, cases described by you will be indistinguishable if you will only use this property. You will need to write some additional code in click event handler of your "close" button to store some information which will be checked in the FormClosing event handler to distinguish between these cases.

okutane
  • 13,754
  • 10
  • 59
  • 67
1

You need to add a listener to the Even FormClosing, which sends in the event args a property of type CloseReason which is one of these values

    // Summary:
//     Specifies the reason that a form was closed.
public enum CloseReason
{
    // Summary:
    //     The cause of the closure was not defined or could not be determined.
    None = 0,
    //
    // Summary:
    //     The operating system is closing all applications before shutting down.
    WindowsShutDown = 1,
    //
    // Summary:
    //     The parent form of this multiple document interface (MDI) form is closing.
    MdiFormClosing = 2,
    //
    // Summary:
    //     The user is closing the form through the user interface (UI), for example
    //     by clicking the Close button on the form window, selecting Close from the
    //     window's control menu, or pressing ALT+F4.
    UserClosing = 3,
    //
    // Summary:
    //     The Microsoft Windows Task Manager is closing the application.
    TaskManagerClosing = 4,
    //
    // Summary:
    //     The owner form is closing.
    FormOwnerClosing = 5,
    //
    // Summary:
    //     The System.Windows.Forms.Application.Exit() method of the System.Windows.Forms.Application
    //     class was invoked.
    ApplicationExitCall = 6,
}
bashmohandes
  • 2,356
  • 1
  • 16
  • 23
  • 2
    Both cases described by Nate will be CloseReason.UserClosing, so how usage of this property can help him? – okutane Oct 26 '09 at 09:14