Windows Develop Bookmark and Share   
 index > Windows Forms General > Get real CloseReason in MDI Child FormClosing
 

Get real CloseReason in MDI Child FormClosing

I'm developing an MDI application with .NET Framework 3.5 and I want topromt the userfor saving changes from each MDI child form only when the user itself initiated closing and do nothing when the application is closing from Task Manager or because Windows is shutting down.
The problem i'm having is that only the MDI Parent knows the real closing reason whereas the MDI child forms get in FormClosing always MdiFormClosing instead of TaskManagerClosing or WindowsShutDown. The FormClosing event of the MDI parent is raised only at the end and I can check the real reason too late.
If the real reason would have been propagated to the MDI child form it would have been perfect, but this is not happening.
Does have somebody any idea how to do this ?

Gabriela_B  Wednesday, September 30, 2009 11:40 AM
Yes, clumsy. Paste this code in your MDI Parent form:

public static bool Shutdown;

protected override void WndProc(ref Message m) {
if (m.Msg == 0x11 || m.Msg == 0x16) Shutdown = true;
base.WndProc(ref m);
}

Check it in your child's OnFormClosing() method:

if (Form1.Shutdown) return;
// Prompt for save etc...


Hans Passant.
nobugz  Wednesday, September 30, 2009 5:30 PM

Well, I figured out that Task Manager is sending WM_CLOSE message. Here it is the complete working code in case someone else need the same:
In the MDI parent form:

 

public static CloseReason RealCloseReason = CloseReason.None;
public const int WM_SYSCOMMAND = 0x0112;
public const int WM_CLOSE = 0x0010;
public const int WM_QUERYENDSESSION = 0x0011;
public const int SC_CLOSE = 0xF060;
private const int WM_ENDSESSION = 0x0016;
private static bool UserClosed;

 

protected override void WndProc( ref Message m )
{
   if( m.Msg == WM_QUERYENDSESSION || m.Msg == WM_ENDSESSION )
   {
      // Shutdown, Logoff, Restart
      RealCloseReason = CloseReason.WindowsShutDown;
   } 
  else if( m.Msg == WM_SYSCOMMAND )
   {
      if( ( m.WParam.ToInt32() & SC_CLOSE ) == SC_CLOSE )
     {
         // The user clicked on the "X" button of the MDI Parent
         UserClosed = true;
      }
   } 
  else if( m.Msg == WM_CLOSE && UserClosed == false )
   { 
     // Task Manager
      RealCloseReason = CloseReason.TaskManagerClosing;
   }
   base.WndProc( ref m );
}

In the OnFormClosing of the MDI child form:
private void Form2_FormClosing( object sender, FormClosingEventArgs e )
{
   if( Form1.RealCloseReason == CloseReason.TaskManagerClosing || 
   Form1
.RealCloseReason == CloseReason.WindowsShutDown ) return;
   // Prompt for save
}

Thanks for the right direction.

  • Marked As Answer byGabriela_B Monday, October 05, 2009 8:11 AM
  •  
Gabriela_B  Monday, October 05, 2009 8:10 AM
Yes, clumsy. Paste this code in your MDI Parent form:

public static bool Shutdown;

protected override void WndProc(ref Message m) {
if (m.Msg == 0x11 || m.Msg == 0x16) Shutdown = true;
base.WndProc(ref m);
}

Check it in your child's OnFormClosing() method:

if (Form1.Shutdown) return;
// Prompt for save etc...


Hans Passant.
nobugz  Wednesday, September 30, 2009 5:30 PM

I've tried it andI have two problems:
1. I had to change in the MDI parent:
public static bool Shutdown;

protected override void WndProc(ref Message m) {
if (m.Msg == 11 || m.Msg == 16) Shutdown = true;
base.WndProc(ref m);
}

2. It is working now only when closing from Task Manager. But when Windows is shutting down, or by logoff or restart, it doesn't work.

I'veresearched on WndProc and these messages (WM_QUERYENDSESSION and WM_ENDSESSION) and lot of people are saying it should work, but it doesn't ?! Should I mention that I'm having XP Service Pack 3 ?

Gabriela_B  Thursday, October 01, 2009 1:53 PM
Not 11 and 16, 0x11 and 0x16. Copy and paste please.

Hans Passant.
nobugz  Thursday, October 01, 2009 5:05 PM

Well, I figured out that Task Manager is sending WM_CLOSE message. Here it is the complete working code in case someone else need the same:
In the MDI parent form:

 

public static CloseReason RealCloseReason = CloseReason.None;
public const int WM_SYSCOMMAND = 0x0112;
public const int WM_CLOSE = 0x0010;
public const int WM_QUERYENDSESSION = 0x0011;
public const int SC_CLOSE = 0xF060;
private const int WM_ENDSESSION = 0x0016;
private static bool UserClosed;

 

protected override void WndProc( ref Message m )
{
   if( m.Msg == WM_QUERYENDSESSION || m.Msg == WM_ENDSESSION )
   {
      // Shutdown, Logoff, Restart
      RealCloseReason = CloseReason.WindowsShutDown;
   } 
  else if( m.Msg == WM_SYSCOMMAND )
   {
      if( ( m.WParam.ToInt32() & SC_CLOSE ) == SC_CLOSE )
     {
         // The user clicked on the "X" button of the MDI Parent
         UserClosed = true;
      }
   } 
  else if( m.Msg == WM_CLOSE && UserClosed == false )
   { 
     // Task Manager
      RealCloseReason = CloseReason.TaskManagerClosing;
   }
   base.WndProc( ref m );
}

In the OnFormClosing of the MDI child form:
private void Form2_FormClosing( object sender, FormClosingEventArgs e )
{
   if( Form1.RealCloseReason == CloseReason.TaskManagerClosing || 
   Form1
.RealCloseReason == CloseReason.WindowsShutDown ) return;
   // Prompt for save
}

Thanks for the right direction.

  • Marked As Answer byGabriela_B Monday, October 05, 2009 8:11 AM
  •  
Gabriela_B  Monday, October 05, 2009 8:10 AM

You can use google to search for other answers

Custom Search

More Threads

• dataGridView Value
• What can I know what component is getting focus?
• XML Editor "Bug"
• how to bind the DataTable to the DAtaGridView control?
• Another ListView Question
• Get the file from URL path
• Fake key press
• Windows Forms
• C#: Can't Get a Form to Scale
• .net 1.1 - Apply Windows theme on all controls