0

I have a winforms C# application with multiple MDI child windows, each of which can contain changed user data.

When a child window is closed individually, the user is warned about the changed data, which works fine.

However, if the user attempts to close the application, I only want to warn once for all child windows if any have changed data (the data is not that critical).

So the idea is to hook into the main window's OnClosing event, look for changed user data in any of the child windows, display a warning just once if I find any changed data, and set a boolean to prevent each child window from bothering the user multiple times.

The problem I'm seeing is, the OnClosing event for the main window is triggered AFTER the OnClosing events for each child window are triggered, so I can't set my boolean soon enough.

Is there an event for application closing that I can hook into that arrives sooner than OnClosing, or is there maybe a Windows message I can trap?

Surfbutler
  • 1,529
  • 2
  • 17
  • 38
  • I can't test it right now, but try the answer in here: http://stackoverflow.com/questions/5142517/e-cancel-in-formclosing-event You can cancel form closing (and set it up to close at your convenience). – Zero Mar 17 '16 at 11:06
  • Thanks, but the problem was that I was getting the child window close events are triggered BEFORE I was getting the main form closing event. See my answer for the workaround. – Surfbutler Mar 17 '16 at 11:17

3 Answers3

2

Solved it, I just needed to hook into the WM_CLOSE Windows message:

protected override void WndProc(ref Message m)
{
    // Crucially, this message arrives before my child windows get the OnClosing event.
    if (m.Msg == WM_CLOSE)
    {
         // So I set my boolean here and everything works great.
    }

    base.WndProc(ref m);
}
Surfbutler
  • 1,529
  • 2
  • 17
  • 38
  • Though this works, I've accepted Ivan's answer instead, as it's far neater, and doesn't involve message loops and flags! – Surfbutler Mar 17 '16 at 11:28
2

Instead of hooking into MDI parent form close messages and setting flags, you can make your child forms subscribe to FormClosing event and skip the processing if FormClosingEventArgs.CloseReason is MdiFormClosing:

private void ChildForm_FormClosing(object sender, FormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.MdiFormClosing) return; // Do nothing
    // ...
}
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • Perfect - this is far better than my WndProc override, and as you say I won't need to pass down a flag. Going to accept your answer - might also be worth mentioning the different close reason when the child form is closed individually - CloseReason.UserClosing. – Surfbutler Mar 17 '16 at 11:25
  • You are right, probably the condition `e.CloseReason != CloseReson.UserClosing` is more appropriate in that case. – Ivan Stoev Mar 17 '16 at 12:01
0

I would create a boolean in each of your sub-windows that dictates whether or not to open the prompt.

public bool Prompt = true;

private void Form_Closing(object sender, EventArgs e)
{
    if (Prompt)
    {
        MessageBox.Show("Data thingy...whatever");
    }
}

And then in your main form you can set this boolean to false.

private void MainForm_Closing(object sender, EventArgs e)
{
    form1.Prompt = false;
    form1.Close();
    form2.Prompt = false;
    form2.Close();
    //etc
}
Sophie Coyne
  • 1,018
  • 7
  • 16
  • Thanks but that's similar to what I initially tried - unfortunately the main window closing event is triggered AFTER each child window closing event. See my answer which does work correctly. – Surfbutler Mar 17 '16 at 11:13
  • Yeah, I'm still somewhat intermediate so that would've never occured to me. – Sophie Coyne Mar 17 '16 at 12:48