Visible = False on Form_Closing...

  • Thread starter Thread starter DraguVaso
  • Start date Start date
D

DraguVaso

Hi,

I have a MDIForm with some MDIChilds. When the user clicks on the "x" in the
upper right corner, I don't want the MDIChild to be closed, but the property
Visible = False.

So far no problem: I do this useing the Form_Closing-event in which I typed:
e.Cancel = True
Me.Visibible = False

But: When I Close the MDIParent, it wont shut down the whole application
because of the fact that those MDIChilds cancel the closing!

I tryed to put work with a boolean which is set to true when MDIParent is
closed, and first evaluated in the MIDChild_Closing-event, but that doesn't
work either, because of the fact that the Closing-event of the MDIChilds are
fired before the Closing Event of the Parent...

Anybody got any idea how to do this? Maybe with the Closed-event? This event
comes after the Closing-event, but I can't find someting in ot to Cancel the
closing of the form.

I guess there must be a 'nicer' way to do this: Maybe by handling the click
on the "x", and when it is clicked not to close etc etc...

Hoping for your help and thanks a lot in advance,

Pieter
 
You can set closeing flag in the main form (MDI parent).

in the Main form (MDI parent) class:

public class frmMain:Form
{
private bool mClosing=false;
public frmMain()
{
}

internal bool MainFormClosing
{
get { return mClosing; }
}
.....
......
private void frmMain_Closing(...)
{
mClosing=true;
}
}

in the MDI child form class

public frmChild:Form
{
....
....
private frmChild_Closing(....)
{
//If the closing is caused by MDI parent, no CANCELLING
frmMain f=(frmMain)this.Parent;
if (f.MainFormClosing) return;

//Cancel closing
e.Cancel=true
this.Visible=false;
}
}

The code is in C#, and very little differentce from VB.NET code and you
should be able to read it.

HTH
 
Unfortunately this doesn't work... I tryed it myself alreaddy before.
This code does the following: It first hides one MDIChild, and when you
click a second time on the "x" of the Parent, then it closes the whole
application.

The reason for that is simple: When you close your application, the
MIDChild_Closing-event is fired before the Parent_Closing-event: so you
aren't able to change the boolean-value before closing the MDIChilds. The
second time you click the boolean value is alreaddy changed (from the first
time), and than the application is properly shutted down.

The order of events is this:
Child_Closing
Parent_Closing
Child_Closed
Parent_Closed

So what I could do is: change the boolean in the Parent_Closing, and
evaluate it in the Child_Closed. Unfortunately: I can't find a way to cancel
the closing in the Closed-event...

Anybody any idea? I'm really stuck with this problem :-(

Pieter
 
Pieter,

this could be a slight suggestion: when the main form is beeing closed,
you can catch the message that orders it to close, set the value of some
public flag and then, in the closing event of the child you could check if
it is the main form beeing closed or just the mdi child beeing closed.

details:

put followind code in the main form:

public bool bClosingEventFromParent = false;
protected override void WndProc( ref Message m )
{
if ( m.Msg == (int)0x0112 ) // WM_SYSCOMMAND
if ( m.WParam == (IntPtr)0xF060 ) // SC_CLOSE
bClosingEventFromParent = true;
base.WndProc( ref m );
}

because the SC_CLOSE message is processed immediatelly after you press 'x'
in the main form, the flag will properly indicate the mdi child if it is the
main form beeing closed. and then you can react properly in the closing
event of the mdi child.

I hope this will help you,
Wiktor Zychla
 
Great! This worked fine!
But how did you come up with something like that? These are thing I even
didn't know they existed, hehe :-)

For others thare are interested in the VB.NET version:

Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = Convert.ToInt32("0x0112", 16) Then
If IntPtr.op_Equality(m.WParam,
IntPtr.op_Explicit(Convert.ToInt32("0xF060", 16))) Then
blnMainClosing = True
End If
End If
MyBase.WndProc(m)
End Sub
 
Great! This worked fine!
But how did you come up with something like that? These are thing I even
didn't know they existed, hehe :-)

Windows GUI works by exchanging messages between visual objects. they are
triggered by various events (for example: user activity). there are however
much more win32 messages than .NET events. in such cases you just have to
know what message corresponds to the activity you would like to intercept
(or invoke).

Regards, Wiktor
 
Back
Top