Reactivation of a closed MDI child

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
 
M

Michael Mayer

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);
}
 
Z

zobie

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);
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top