Reactivation of a closed MDI child

  • Thread starter Thread starter zobie
  • Start date Start date
Z

zobie

In the parent of my MDI application I declare a child form

private frmChild = null;

which is to be activated on a menu click. In the click event I am using the
following code:

if (frmChild == null || !frmChild .IsHandleCreated)
{
frmChild = new frmChild ();
frmChild .MdiParent = this;
frmChild .Show ();
}
else
frmChild .Activate();

This does not have the desired effect however; I am trying to avoid having
to go through initialization each time the form is re-opened. I also need
to make sure that only one instance of this form is opened at a time.

Can anyone offer help?

Thanks,
Nate
 
zobie said:
In the parent of my MDI application I declare a child form
This does not have the desired effect however; I am trying to avoid having
to go through initialization each time the form is re-opened. I also need
to make sure that only one instance of this form is opened at a time.

I ran into your problem yesterday and came up with half of the solution: I
never close MDI children - just hide and unhide them (similar to [1]). The
problem was trying to close the entire app - which I just found the solution
in [2].

[1] http://tinyurl.com/mt46
[2] http://tinyurl.com/mt4t

To summarize here in the three steps (this isn't polished code, but should
give you the idea);

=============================
1. Add a closing event for the mdi child forms that cancels the close
(unless it's closing because of the parent closing), and instead just hides
the mdi child like this (you might want to use the sender object instead of
"this" depending upon where you put this event handler).

private void EntryForm_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{
MainForm parentFrm = (MainForm)this.MdiParent;
if (parentFrm.ClosingEventFromParent == false)
{
this.Visible = false;
e.Cancel = true;
}
}


=============================
2. Then to "activate" the mdi child, call this method from your menu buttons
like this:
BringToFront (mdiForm1Instance);
(You should probably use singleton pattern in your mdi children to really
prevent multiple instances)

void BringToFront (Form form)
{
if (form == null)
{
throw new ArgumentNullException ("form", "Can't bring a null form to
the front");
}
else
{
if (!form.Visible)
{
form.Show();
}

//form.WindowState = FormWindowState.Maximized;
form.BringToFront();
}
}


=============================
3. The important step is the closing method for the parent form. You can't
simply override onClosing or use the closing event, for reasons outlined in
[1] above. Instead add this to parent form:

const int WM_SYSCOMMAND = 0x0112;
const int SC_CLOSE = 0xF060;

public bool ClosingEventFromParent = false;
protected override void WndProc(ref Message m)
{
if ( m.Msg == WM_SYSCOMMAND && m.WParam == (IntPtr)SC_CLOSE )
{
ClosingEventFromParent = true;
}
base.WndProc(ref m);
}
 
Thanks! This is exactly what I was looking for.

Nate


Michael Mayer said:
zobie said:
In the parent of my MDI application I declare a child form
This does not have the desired effect however; I am trying to avoid having
to go through initialization each time the form is re-opened. I also need
to make sure that only one instance of this form is opened at a time.

I ran into your problem yesterday and came up with half of the solution: I
never close MDI children - just hide and unhide them (similar to [1]). The
problem was trying to close the entire app - which I just found the solution
in [2].

[1] http://tinyurl.com/mt46
[2] http://tinyurl.com/mt4t

To summarize here in the three steps (this isn't polished code, but should
give you the idea);

=============================
1. Add a closing event for the mdi child forms that cancels the close
(unless it's closing because of the parent closing), and instead just hides
the mdi child like this (you might want to use the sender object instead of
"this" depending upon where you put this event handler).

private void EntryForm_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{
MainForm parentFrm = (MainForm)this.MdiParent;
if (parentFrm.ClosingEventFromParent == false)
{
this.Visible = false;
e.Cancel = true;
}
}


=============================
2. Then to "activate" the mdi child, call this method from your menu buttons
like this:
BringToFront (mdiForm1Instance);
(You should probably use singleton pattern in your mdi children to really
prevent multiple instances)

void BringToFront (Form form)
{
if (form == null)
{
throw new ArgumentNullException ("form", "Can't bring a null form to
the front");
}
else
{
if (!form.Visible)
{
form.Show();
}

//form.WindowState = FormWindowState.Maximized;
form.BringToFront();
}
}


=============================
3. The important step is the closing method for the parent form. You can't
simply override onClosing or use the closing event, for reasons outlined in
[1] above. Instead add this to parent form:

const int WM_SYSCOMMAND = 0x0112;
const int SC_CLOSE = 0xF060;

public bool ClosingEventFromParent = false;
protected override void WndProc(ref Message m)
{
if ( m.Msg == WM_SYSCOMMAND && m.WParam == (IntPtr)SC_CLOSE )
{
ClosingEventFromParent = true;
}
base.WndProc(ref m);
}
 
Back
Top