When you close a form in a Windows Form application, the following events expire in the order in which they appear in the following list:
- Closing
- FormClosing
- Closed
- FormClosed
However, when you close a hidden multiple document interface (MDI) child form, these events do not expire in the correct order.
Additionally, if the hidden MDI child form contains an ActiveX control, the MDI child form is destroyed in memory during the lifetime of the ActiveX control instance. Therefore, the MDI child form is closed but the control is not closed.
For MDI child forms, the application destroys the handler when the MDI form is hidden. This operation differs from the operation of a non-MDI child form. For non-MDI child forms, the application preserves the handler until the form is disposed. Therefore, the events of a non-MDI child form are raised even when the form is hidden.
To work around this problem, follow these steps:
- Detach the hidden MDI child form from the application.
- Perform the operations in the detached hidden MDI child form.
- Reattach the hidden MDI child form to the application.
Steps to reproduce the problem
- Start Microsoft Visual Studio 2005.
- Create a Microsoft Visual C# project. Name the project "CloseEventTest."
- Create four button controls. Each button control is used to perform one of the following tasks:
- Create a modeless form
- Create an MDI child form
- Close the MDI child form
- Show the MDI child form again
-
Run the following code:
Form2 f = null;
private void button1_Click(object sender, EventArgs e) {
if (f != null) {
MessageBox.Show("Form already created");
return;
}
f = new Form2();
f.Show();
}
private void button2_Click(object sender, EventArgs e) {
if (f != null) {
f.Close();
f = null;
}
}
private void button3_Click(object sender, EventArgs e) {
if (f != null) {
MessageBox.Show("Form already created");
return;
}
f = new Form2();
f.MdiParent = this;
f.Show();
}
private void button4_Click(object sender, EventArgs e) {
if (f != null)
f.Show();
} - Create a new form. Name the form "form2."
- Add trace code in the following events:
- Closing
- FormClosing
- Closed
- FormClosed
- Use the following code to hide the MDI child form:
private void HideButton_Click(object sender, EventArgs e) {
this.Hide();
}
protected override void OnHandleDestroyed(EventArgs e) {
MessageBox.Show("OnHandleDestroyed");
base.OnHandleDestroyed(e);
}
protected override void OnClosed(EventArgs e) {
MessageBox.Show ("OnClosed");
base.OnClosed(e);
}
protected override void OnClosing(CancelEventArgs e) {
MessageBox.Show ("OnClosing");
base.OnClosing(e);
}
protected override void OnFormClosed(FormClosedEventArgs e) {
MessageBox.Show ("OnFormClosed");
base.OnFormClosed(e);
}
protected override void OnFormClosing(FormClosingEventArgs e) {
MessageBox.Show ("OnFormClosing");
base.OnFormClosing(e);
}
- Close the hidden MDI child form.
Notice that the events do not expire as expected.