开发者

Override standard close (X) button in a Windows Form

How do I go about changing what h开发者_Python百科appens when a user clicks the close (red X) button in a Windows Forms application (in C#)?


You can override OnFormClosing to do this. Just be careful you don't do anything too unexpected, as clicking the 'X' to close is a well understood behavior.

protected override void OnFormClosing(FormClosingEventArgs e)
{
    base.OnFormClosing(e);

    if (e.CloseReason == CloseReason.WindowsShutDown) return;

    // Confirm user wants to close
    switch (MessageBox.Show(this, "Are you sure you want to close?", "Closing", MessageBoxButtons.YesNo))
    {
    case DialogResult.No:
        e.Cancel = true;
        break;
    default:
        break;
    }        
}


Override the OnFormClosing method.

CAUTION: You need to check the CloseReason and only alter the behaviour if it is UserClosing. You should not put anything in here that would stall the Windows shutdown routine.

Application Shutdown Changes in Windows Vista

This is from the Windows 7 logo program requirements.


One thing these answers lack, and which newbies are probably looking for, is that while it's nice to have an event:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    // do something
}

It's not going to do anything at all unless you register the event. Put this in the class constructor:

this.FormClosing += Form1_FormClosing;


Either override the OnFormClosing or register for the event FormClosing.

This is an example of overriding the OnFormClosing function in the derived form:

protected override void OnFormClosing(FormClosingEventArgs e)
{
   e.Cancel = true;
}

This is an example of the handler of the event to stop the form from closing which can be in any class:

private void FormClosing(object sender,FormClosingEventArgs e)
{  
   e.Cancel = true;
}

To get more advanced, check the CloseReason property on the FormClosingEventArgs to ensure the appropriate action is performed. You might want to only do the alternative action if the user tries to close the form.


as Jon B said, but you'll also want to check for the ApplicationExitCall and TaskManagerClosing CloseReason:

protected override void OnFormClosing(FormClosingEventArgs e)
{
    if (  e.CloseReason == CloseReason.WindowsShutDown 
        ||e.CloseReason == CloseReason.ApplicationExitCall
        ||e.CloseReason == CloseReason.TaskManagerClosing) { 
       return; 
    }
    e.Cancel = true;
    //assuming you want the close-button to only hide the form, 
    //and are overriding the form's OnFormClosing method:
    this.Hide();
}


Override OnFormClosing?


One situation where it is quite useful to be able to handle the x-button click event is when you are using a Form that is an MDI container. The reason is that the closeing and closed events are raised first with children and lastly with the parent. So in one scenario a user clicks the x-button to close the application and the MDI parent asks for a confirmation to proceed. In case he decides to not close the application but carry on whatever he is doing the children will already have processed the closing event potentially lost information/work whatever. One solution is to intercept the WM_CLOSE message from the Windows message loop in your main application form (i.e. which closed, terminates the application) like so:

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x0010) // WM_CLOSE
        {
            // If we don't want to close this window 
            if (ShowConfirmation("Are you sure?") != DialogResult.Yes) return;
        }

        base.WndProc(ref m);
    }


This is a pretty commonly asked question. One good answer is here:

VB.NET overload default functionality when user clicks the X (Close Program)


If you don't feel comfortable putting your code in the Form_Closing event, the only other option I am aware of is a "hack" that I've used once or twice. It should not be necessary to resort to this hack, but here it is:


Don't use the normal close button. Instead, create your form so that it has no ControlBox. You can do this by setting ControlBox = false on the form, in which case, you will still have the normal bar across the top of the form, or you can set the form's FormBorderStyle to "None. If you go this second route, there will be no bar across the top, or any other visible border, so you'll have to simulate those either by drawing on the form, or by artistic use of Panel controls.

Then you can add a standard button and make it look like a close button, and put your clean-up code in there. At the end of the button event, just call this.Close() (C#) or Me.Close() (VB)


The accepted answer works quite well. An alternative method that I have used is to create a FormClosing method for the main Form. This is very similar to the override. My example is for an application that minimizes to the system tray when clicking the close button on the Form.

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (e.CloseReason == CloseReason.ApplicationExitCall)
        {
            return;
        }
        else
        {
            e.Cancel = true;
            WindowState = FormWindowState.Minimized;
        }            
    }

This will allow ALT+F4 or anything in the Application calling Application.Exit(); to act as normal while clicking the (X) will minimize the Application.


protected override bool ProcessCmdKey(ref Message msg, Keys dataKey)
    {
        if (dataKey == Keys.Escape)
        {
            this.Close();
            //this.Visible = false;
            //Plus clear values from form, if Visible false.
        }
        return base.ProcessCmdKey(ref msg, dataKey);
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜