Advertisement
Advertisement


How to know user has clicked "X" or the "Close" button?


Question

In MSDN I found CloseReason.UserClosing to know that the user had decided to close the form but I guess it is the same for both clicking the X button or clicking the close button. So how can I differentiate between these two in my code?

Thanks all.

2014/05/02
1
94
5/2/2014 5:46:04 PM

Accepted Answer

Assuming you're asking for WinForms, you may use the FormClosing() event. The event FormClosing() is triggered any time a form is to get closed.

To detect if the user clicked either X or your CloseButton, you may get it through the sender object. Try to cast sender as a Button control, and verify perhaps for its name "CloseButton", for instance.

private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
    if (string.Equals((sender as Button).Name, @"CloseButton"))
        // Do something proper to CloseButton.
    else
        // Then assume that X has been clicked and act accordingly.
}

Otherwise, I have never ever needed to differentiate whether X or CloseButton was clicked, as I wanted to perform something specific on the FormClosing event, like closing all MdiChildren before closing the MDIContainerForm, or event checking for unsaved changes. Under these circumstances, we don't need, according to me, to differentiate from either buttons.

Closing by ALT+F4 will also trigger the FormClosing() event, as it sends a message to the Form that says to close. You may cancel the event by setting the

FormClosingEventArgs.Cancel = true. 

In our example, this would translate to be

e.Cancel = true.

Notice the difference between the FormClosing() and the FormClosed() events.

FormClosing occurs when the form received the message to be closed, and verify whether it has something to do before it is closed.

FormClosed occurs when the form is actually closed, so after it is closed.

Does this help?

2016/05/11
95
5/11/2016 10:26:53 AM


The "X" button registers as DialogResult.Cancel so another option is to evaluate the DialogResult.

If you have multiple buttons on your form, you're probably already associating different DialogResults to each and this will provide you with the means to tell the difference between each button.

(Example: btnSubmit.DialogResult = DialogResult.OK, btnClose.DialogResult = Dialogresult.Abort)

    public Form1()
    {
        InitializeComponent();

        this.FormClosing += Form1_FormClosing;
    }

    /// <summary>
    /// Override the Close Form event
    /// Do something
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
    {
        //In case windows is trying to shut down, don't hold the process up
        if (e.CloseReason == CloseReason.WindowsShutDown) return;

        if (this.DialogResult == DialogResult.Cancel)
        {
            // Assume that X has been clicked and act accordingly.
            // Confirm user wants to close
            switch (MessageBox.Show(this, "Are you sure?", "Do you still want ... ?", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
            {
                //Stay on this form
                case DialogResult.No:
                    e.Cancel = true;
                    break;
                default:
                    break;
            }
        }
    }
2011/12/01

How to detect if the form closed by click on X button or by calling Close() in code?

You cannot rely on close reason of the form closing event args, because if the user click X button on title bar or close the form using Alt + F4 or use system menu to close the form or the form get closed by calling Close() method, all all above cases, the close reason will be Closed by User which is not desired result.

To distinguish if the form closed by X button or by Close method, you can use either of the following options:

  • Handle WM_SYSCOMMAND and check for SC_CLOSE and set a flag.
  • Check the StackTrace to see if any of the frames contain Close method call.

Example 1 - Handle WM_SYSCOMMAND

public bool ClosedByXButtonOrAltF4 {get; private set;}
private const int SC_CLOSE = 0xF060;
private const int WM_SYSCOMMAND = 0x0112;
protected override void WndProc(ref Message msg)
{
    if (msg.Msg == WM_SYSCOMMAND && msg.WParam.ToInt32() == SC_CLOSE)
        ClosedByXButtonOrAltF4 = true;
    base.WndProc(ref msg);
}
protected override void OnShown(EventArgs e)
{
    ClosedByXButtonOrAltF4 = false;
}   
protected override void OnFormClosing(FormClosingEventArgs e)
{
    if (ClosedByXButtonOrAltF4)
        MessageBox.Show("Closed by X or Alt+F4");
    else
        MessageBox.Show("Closed by calling Close()");
}

Example 2 - Checking StackTrace

protected override void OnFormClosing(FormClosingEventArgs e)
{
    if (new StackTrace().GetFrames().Any(x => x.GetMethod().Name == "Close"))
        MessageBox.Show("Closed by calling Close()");
    else
        MessageBox.Show("Closed by X or Alt+F4");
}
2020/08/12

It determines when to close the application if a form is closed (if your application is not attached to a specific form).

    private void MyForm_FormClosed(object sender, FormClosedEventArgs e)
    {
        if (Application.OpenForms.Count == 0) Application.Exit();
    }
2012/10/19

I always use a Form Close method in my applications that catches alt + x from my exit Button, alt + f4 or another form closing event was initiated. All my classes have the class name defined as Private string mstrClsTitle = "grmRexcel" in this case, an Exit method that calls the Form Closing Method and a Form Closing Method. I also have a statement for the Form Closing Method - this.FormClosing = My Form Closing Form Closing method name.

The code for this:

namespace Rexcel_II
{
    public partial class frmRexcel : Form
    {
        private string mstrClsTitle = "frmRexcel";

        public frmRexcel()
        {
            InitializeComponent();

            this.FormClosing += frmRexcel_FormClosing;
        }

        /// <summary>
        /// Handles the Button Exit Event executed by the Exit Button Click
        /// or Alt + x
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnExit_Click(object sender, EventArgs e)
        {            
            this.Close();        
        }


        /// <summary>
        /// Handles the Form Closing event
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmRexcel_FormClosing(object sender, FormClosingEventArgs e)
        {

            // ---- If windows is shutting down, 
            // ---- I don't want to hold up the process
            if (e.CloseReason == CloseReason.WindowsShutDown) return;
            {

                // ---- Ok, Windows is not shutting down so
                // ---- either btnExit or Alt + x or Alt + f4 has been clicked or
                // ---- another form closing event was intiated
                //      *)  Confirm user wants to close the application
                switch (MessageBox.Show(this, 
                                    "Are you sure you want to close the Application?",
                                    mstrClsTitle + ".frmRexcel_FormClosing",
                                    MessageBoxButtons.YesNo, MessageBoxIcon.Question))
                {

                    // ---- *)  if No keep the application alive 
                    //----  *)  else close the application
                    case DialogResult.No:
                        e.Cancel = true;
                        break;
                    default:
                        break;
                }
            }
        }
    }
}
2018/05/14

You can try adding event handler from design like this: Open form in design view, open properties window or press F4, click event toolbar button to view events on Form object, find FormClosing event in Behavior group, and double click it. Reference: https://social.msdn.microsoft.com/Forums/vstudio/en-US/9bdee708-db4b-4e46-a99c-99726fa25cfb/how-do-i-add-formclosing-event?forum=csharpgeneral

2016/08/25

Source: https://stackoverflow.com/questions/2683679
Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]