hello,

which event is fired when i close form with X button ? i want event that fired only with X button pressed, i know that there is a FormClosing event, but the problem is that it fires each time when form is closed... also with frm.close()

and i don't want that happen

tanx

Dani AI

Generated

Short answer for : FormClosing (and FormClosed) always fire for any close. The event gives a CloseReason, but calling this.Close() sets the internal close reason to UserClosing before sending the close message, so e.CloseReason == CloseReason.UserClosing is true for both a user pressing X (or Alt+F4) and a programmatic Close() call. See the WinForms source and the FormClosing docs. (Form.Close source, FormClosingEventArgs.CloseReason).

Most reliable, simple pattern (least brittle)

  • Expose one method for programmatic closes (or set a private flag) and check that flag inside FormClosing. This is the approach suggested in prose and it avoids fragile message hacks.
private bool _programmaticClose;

public void CloseFromCode()
{
    _programmaticClose = true;
    Close();
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.UserClosing && !_programmaticClose)
    {
        // treat this as a user-initiated close (X / Alt+F4 / system menu)
    }
    // reset
    _programmaticClose = false;
}

If you need to detect the title-bar X (mouse click) more strictly

  • Override WndProc and watch for WM_SYSCOMMAND + SC_CLOSE. Inspect lParam: -1 means an accelerator (Alt+F4), 0 a mnemonic; a nonzero coord typically means a mouse click. This is what hinted at but using WM_SYSCOMMAND/SC_CLOSE is more precise than listening for WM_CLOSE. Example: check m.Msg == WM_SYSCOMMAND && (wParam & 0xFFF0) == SC_CLOSE, then test m.LParam. See the Win32 doc for WM_SYSCOMMAND. Note: this method is more brittle (custom chrome, MDI/maximized children, third-party toolbars can alter messages), so use it only if you really must. (WM_SYSCOMMAND doc, caveats: Syncfusion note).

Summary: for most apps the flag + FormClosing check is simplest and robust; use WndProc (SC_CLOSE + lParam) only if you must distinguish an actual mouse click on the X and accept the edge cases. This ties back to 's FormClosing/FormClosed point and to /'s flag/WndProc ideas — choose the tradeoff that fits your app.

Recommended Answers

All 6 Replies

You mean you don't want the user to be able to click on it?
A FormClosing event happens before a Form is closed, a FormClosed event happens after a Form is closed. You don't need to implement these if you don't want to.

commented: Thats how I would do it +14

no,
what i meant to is that i want to catch some event which is fired when i press X button on the form and only then,
and if i have line like " frm.close()" in my code, the event wont be fired...

You could also set the ControlBox property of the Form to false.

As far as I know the "X" just sends the form close message to your form and you cannot distinguish the caller. This will work though:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace daniweb
{
  public partial class frmImage : Form
  {
    private bool allowFormClose = false;

    public frmImage()
    {
      InitializeComponent();
    }

    protected override void WndProc(ref Message m)
    {
      if (!allowFormClose && (m.Msg == 0x0010)) //form "X"
      {
        System.Diagnostics.Debugger.Break();
        //Do something
      }
      else
        base.WndProc(ref m);
    }

    private void button2_Click(object sender, EventArgs e)
    {
      allowFormClose = true;
      this.Close();
    }
  }
}

[edit]
This is the functionally identical to just canceling the form close in the "FormClosing" event that ddanbe pointed out, with a lot less of a headache.
[/edit]

Wait -- You can do it!:icon_cheesygrin:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace daniweb
{
  public partial class frmImage : Form
  {
    private bool allowFormClose = false;

    public frmImage()
    {
      InitializeComponent();
    }

    protected override void WndProc(ref Message m)
    {
      if (!allowFormClose && (m.Msg == 0x0010)) //form "X"
      {
        //System.Diagnostics.Debugger.Break();
        //Do something
      }
      else
        base.WndProc(ref m);
    }

    new void Close()
    {
      allowFormClose = true;
      base.Close();
    }

    private void button2_Click(object sender, EventArgs e)
    {
      this.Close(); //will work
    }

    private void button3_Click(object sender, EventArgs e)
    {
      (this as Form).Close(); //will not work
    }
  }
}

But this method doesn't work very well with inheritance and will probably break things down the road. You're still better off listening to Danny.

That's interesting sknake, I never would have thought of catching the close method like that.

But as far as all these answers go, the Simple response is the X button does only call the form to close. and however you catch that close call, either by wndproc or by a simple form closing event, the trick is to set a flag, just a simple Boolean variable, if its true, cancel the closing and handle your business, if its false, do nothing and allow the form to close.

when you need to call this.Close(); first change your variable. else you can create a public method for your form called DoClose() or something and change the flag there and call close, its up to you.

commented: Simple things are often the best! +12
commented: Thats what I would do +14
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.