Click here to Skip to main content
Email Password   helpLost your password?

Introduction

You can use this code to see why your application is closing (closed by user, by Windows, by code?). It can be very handy if you are using a NotifyIcon in your app. You can figure out if the user is closing your app or not, if so, then you can just minimize it to tray.

For those who have used Visual Basic before, you know that there was a QueryUnload method for your Forms and that you could find out the reason for the form's closing by examining the UnloadMode variable.

This code snippet shows you how to do this in .NET. The sample code is in VB.NET. The code is from GotDotNet message boards, written by "YeahIGotDotNet".

Private Sub Form1_Closing(ByVal sender As Object, _
  ByVal e As System.ComponentModel.CancelEventArgs) _
  Handles MyBase.Closing
    Dim O As System.Diagnostics.StackTrace = _
           New System.Diagnostics.StackTrace(True)
    Dim F As System.Diagnostics.StackFrame

    F = O.GetFrame(7)

    Select Case F.GetMethod.Name.ToString
        Case "SendMessage"
            MsgBox("Closing because of call in code.")
        Case "CallWindowProc"
            MsgBox("Closing because of system menu click.")
        Case "DispatchMessageW"
            MsgBox("Closing because of Task Manager.")
        Case Else
            MsgBox("Don't Know why I'm closing!!??")
    End Select
End Sub
You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralHandles Mybase.closing
atogwe
9:04 11 Jun '07  
I am trying to implement a handler for mybase.closing in VB.NET 2005. I am getting the blue underline error message saying "Event 'Closing' was not found". I know your article was done in 2002, and that the rtool is significantly different, but is there anything that I can do to resolve this issue???

Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing

T
GeneralUsing WM_QUERYENDSESSION to detect Windows shutdown
rodgerc
9:13 2 Oct '06  
Here is a good blog entry (C#) that describes how to use the WM_QUERYENDSESSION message to detect if the window is getting closed due to Windows Shutdown.

http://www.pixvillage.com/blogs/devblog/archive/2005/03/26.aspx[^]
GeneralOverriding WndProc changes the GetMethod.Name properties
HanreG
3:15 7 Nov '03  
Like the subject says, overriding WndProc on your form changes the GetMethod.Name properties, rendering this code pretty much useless. Closing with Task Manager even generates an error on GetFrame(14).

Me thinks it might even be easier to just check and handle the messages in WndProc anyway.

Still a very nice piece of code, though! Well done!

HanreG
GeneralCoversion of C++ method
BogBrush Zone
5:12 31 Aug '03  
I have recently converted an application that does this from VC++/MFC to C#.   The following is a conversion of the method I used in that application by overriding OnSysCommand and essentially handling the event when it is a button press on the Close button/menu item and before it is translated into a request to close the window.

private const int WM_SYSCOMMAND = 0x0112;     // From winuser.h
private const int SC_CLOSE = 0xF060;

protected override void WndProc(ref Message m)
{
     if (m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE)
     {
          // Perform actions
     }
     else
          base.WndProc (ref m);
}

N.B. I have also posted this to GotDotNet Wink

Gerard Krupa BSc AMBCS
GeneralMore complete implementation
EvilDoctorSmith
9:23 28 Oct '02  

I don't really have time to write an article on this, but here is a more complete implementation. I have tested on Windows 2000 only, so it may not work on 98/ME. Also, this has not been tested with MDI children or parents.

Most times, you need to know if you are closing because the user selects "Close" from the menu, or whether it is some sort of system thing. The previous implementation does not take into account shutting down the computer. In this instance, where I am cancelling and hiding if it is user input, this would abort the shutdown! You'd never be able to shutdown your computer normally as long as your .NET program is running.

private enum ClosingSource
{
Unknown = -1, //We've never seen this one before!!!
Code = 0, //Shutdown from a call to this.Close();
TaskManager = 1, //Shutdown from the task manager.
SystemShutdown = 2, //Windows is shutting down, or user logging out.
FormControlMenu = 3 //User selected by clicking "X" in form, or from
// the control menu.
}

private ClosingSource GetClosingSource(StackTrace stack)
{
StackFrame frame7 = stack.GetFrame(7);
if(frame7.GetMethod().Name == "SendMessage")
return ClosingSource.Code;
else if(frame7.GetMethod().Name == "DispatchMessageW")
return ClosingSource.TaskManager;
else if(frame7.GetMethod().Name == "CallWindowProc")
{
//At frame 7, a close due to system shutdown still looks
//like a user-selected shutdown, so we have to check the
//next change, which is at stack position 14.
StackFrame frame14 = stack.GetFrame(14);
if(frame14.GetMethod().Name == "WndProc")
return ClosingSource.SystemShutdown;
else if(frame14.GetMethod().Name == "WmSysCommand")
return ClosingSource.FormControlMenu;
}

return ClosingSource.Unknown;
}

private void EventLog_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
StackTrace stack = new StackTrace(true);

ClosingSource source = GetClosingSource(stack);

if(source == ClosingSource.FormControlMenu)
{
e.Cancel = true;
this.Hide();
}
}

I don't like the stack-based solution for "QueryUnload" --> "Closing" much. It depends on a lot of underlying code that I don't have any control over not changing over time. However, I have yet to find a better method, or even another method that works. One of the few instances where .NET functionality is not a superset of VB6.


GeneralClosing a User Control
Peter S
7:06 16 Oct '02  
This is fine if I have a WinForm app. If I have a User Control housed within IE or a Win Exe, how do I determine (from within my User Control) that they've closed the app hosting my User Control?
GeneralRe: Closing a User Control
David Stone
15:55 16 Oct '02  
You can't. Because it's really IE getting closed and not your User Control. What would you need this functionality for though?

Norm Almond: I seen some GUI's in my life but WTF is this mess Wink
Leppie: I made an app for my sister and she wouldnt use it till it was colorful enoughSmile
Norm:good point leppie, from that statement I can only deduce that this GUI must be aimed at childrenLaugh
Leppie:My sister is 25Eek!
-Norm on the MailMagic GUI

GeneralRe: Closing a User Control
BarryJ
21:09 16 Oct '02  
That they HAVE closed it, or HOW it was closed?
GeneralRepost
Richard_D
0:05 14 Oct '02  
This code appears to have been "borrowed" from a post by "YeahIGotDotNet" on the GotDotNet[^] message boards. Unless you are the original poster of this code, either remove it or include the appropriate credits. Mad
GeneralRe: Repost
Anonymous
15:13 14 Oct '02  
Maybe he is the original poster. It could happen.
GeneralRe: Repost
Richard_D
23:40 14 Oct '02  
Not in this case. The original poster has been notified.
GeneralRe: Repost
Anonymous
19:36 14 Oct '02  
It says right in the article:
"The code if from GotDotNet message boards"
GeneralRe: Repost
Richard_D
23:47 14 Oct '02  
It doesn't even mention the name of the person who was stupid kind enough to post the code to the messageboards in the first place. Mad Mad Mad
GeneralRe: Repost
Kourosh
13:22 16 Oct '02  
AHEM!!!
I didnt mean to steal any thing!
I was just so desperate in finding a code like this, so I decided to post it here so that other people can use it...
and the reason that I didnt post the person's name was that because I couldn't go to GotDotNet.com (site upgrade I guess).

The original poster is YeahIGotDotNet.
GeneralRe: Repost
Richard_D
0:02 17 Oct '02  
The name and email address of the poster are included in the notification email. Since you appear to be the person who originaly asked the question, you would have a copy of that message. If not, you would have seen the name when you copied the code from the forum.

Whilst I can appreciate your desire to share this code with other people, it would have been better to contact YeahIGotDotNet and ask him to post the code as an article here. Only if he had ignored the request for a long time, or told you that he was too busy to post an article, should you have posted the code here with his name and a link to the original thread.

Posting his code verbatim as an article, without including the credits, asking for permission, or even notifying him, is totally unacceptable. This kind of behaviour will discourage anyone from providing sample code in forum posts to help answer questions.


Last Updated 16 Oct 2002 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010