Wednesday, April 13, 2005

Hiding your app when the close button is clicked!

Have you ever tried to hide your Windows Forms application when the close button is clicked? Well then you'd probably have encountered problems when shuttin down.
Actually if you try to hide your form in the Form_Closeing event Windows will not be able to close your application while shutting down. When you shut down windows, it will send WM_CLOSE message to each active window and closes them before shutting down. So if you avoid closing the application by adding some custom code, it will interrupt Windows being shut down.
So what exactly you have to do is, to check whether the form is being closed by the user or the system shut down op. Perhaps you must be wondering under which event of the Form class, you should do it. Well... the answer is there is no particuler event. As you may all know by now, neither Form_Closing nor Form_Closed event has a parameter to detect the source of the close command.
hmmm... now what?
Dont worry! Thanks to the .Net Fx we still have a method for that. Form class is the base class for all Windows Forms. It has a overideable method called WndProc(). This is the default window message handler. We can overide this to allert us when the WM_CLOSE message is sent by System shutdown op.
Following code snippet sets a public flag "on" if the WM_CLOSE is sent by shutdown op. If the flag is "on" then Form_Closing event will close form insead of hiding it.

private bool _isShuttingDown = false;
protected override void WndProc(ref Message m)
{
_isShuttingDown = (m.Msg == 0x11); // Detect if shutting down.
base.WndProc (ref m);
}
private void Form_Closing(object sender, CancelEventArgs e)
{
if(!_isShuttingDown) // Cancel closing if not shutting down.
{
e.Cancel = true;
this.Hide(); // Hide the form.
}
}

Hope this helps!

overriding WndProc will catch only messages for the form, not for contained controls. This will catch all messages for all forms and controls in your application:
partial class Form1 : Form, IMessageFilter
{
public Form1()
{ InitializeComponent(); }

private void Form1_Load(object sender, EventArgs e)
{
Application.AddMessageFilter(this);
}
public bool PreFilterMessage(ref Message m)
{
Control sender = Control.FromHandle(m.HWnd);
return false; // true to discard the message
}
}

0 Comments:

Post a Comment

<< Home