Use FormClosing on the dialog. Modal dialogs are hidden, not closed.
No, they are not. From MSDN: "When a form is displayed as a modal dialog
box, clicking the Close button (the button with an X at the upper-right
corner of the form) causes the form to be hidden and the DialogResult
property to be set to DialogResult.Cancel."
http://msdn2.microsoft.com/en-us/library/system.windows.forms.form.formclosing.aspx
I am confused. It continues to say: "When the Close method is called
on a Form displayed as a modeless window, you cannot call the Show
method to make the form visible, because the form's resources have
already been released."
But, what's the difference? Both modal and modeless can exist always
and just be hidden away when not in use. The only real difference is
that one steals focus and doesn't let it go, where as the other
doesn't. So, what does that have to do with the way they are handled
when you call Close()?
But how do you display it? Modally or modeless? Do you keep the
reference to the form?
1. My main form has a reference to a second form for the entire time.
When I call Close() on this second form, it just goes hidden (calls
FormClosing), but it remains. I can make it come back with Show().
2. I have an About form that only has a reference inside of an event
handler for the 'about' button. When I call Close() on it, it calls
FormClosing then FormClosed.
They are both modeless (they don't steal focus and keep it). So, it
must be the reference to the 'second form' that keeps it from call
FormClosed. Since, for the about form, its reference goes away when
the 'about' button' event handler returns.
It also happens when the modeless dialog is "closed" (but not actually
closed).
Yes.
Because that's where the dialog result is set. See link above.
http://msdn2.microsoft.com/en-us/library/system.windows.forms.form.dialogresult.aspx
"The dialog result of a form is the value that is returned from the
form when it is displayed as a modal dialog box."
Ok, that makes sense, it's like the result you get from calling
MessageBox.Show(). That's a modal dialog.
In both of my cases, the dialogs are modeless (although the about box
really should be modal).
Because FormClosing has already been run.
(To be sure we're on the same page, I'm talking about my modeless
dialogs, here, which may or may not be different from modal.) I have
a Debug.WriteLine for both FormClosing and FormClosing, and I would
see if either is run at all, ever, and neither is run. In this case,
I make the dialog appear, and close the whole app:
DialogForm constructing. <-- it only constructs
MainForm constructing.
MainForm closing.
MainForm closed.
But, it is run, if I click 'x' to close it, or my Hide button that
calls Hide(). In this case, I repeatedly make it appear, and close
it:
DialogForm constructing.
MainForm constructing.
DialogForm closing. <-- me clicking 'x'
DialogForm closing. <-- me calling Hide(), after making it appear
again
DialogForm closing. <-- and so on.
MainForm closing.
MainForm closed.
So, FormClosing is only for, for my modeless dialog, when I call
Hide() or press 'x'. It has a reference to it in the MainForm (as you
can see, since even it is constructed before the MainForm is!)
It should run any time the modal dialog is dismissed (whether by Hide() or
clicking the close button or whatever).
Yes, it is.
If your application terminates normally, which means it waits until all
forms are closed, then you should get the FormClosed event for all the
forms.
Pressing 'x' on the main form terminates the app, and for all modeless
dialogs that are open, they do not get FormClosing or FormClosed. I
can verify this by calling MessageBox.Show or Debug.WriteLine in these
events. So, is pressing 'x' a 'normal termination'? Or should I
'catch' this, and instruct all forms to close?
If your application does not terminate normally, then lots of
things are prevented from executing, and I'm not surprised the FormClosed
event is one of those things.
Please define "not terminating normally". Maybe this is my issue.
If it's not working like that, then I have no explanation. I'm not an
expert in how the underlying forms stuff works. I just know what I've
done and what the docs say.
I think maybe you're dealing with modal dialogs, where I am dealing
with modeless. BUT, for modal dialogs, you can't click 'x' to shut
down the app, since you can't get focus to it to do so. So, in that
case, like for MessageBox.Show(), there is no issue, as the dialog
must close before you continue.
So, the only real issue is for modeless dialogs, and perhaps you have
not dealt with these (in the manner we've be speaking about), and this
is the source of confusion? modal != modeless?
I don't mean modeless dialog. A modeless dialog (or form) is just a form
that has been shown using Show rather than ShowDialog.
Ah, so that's how you make them different. I'll try testing the
differences between modal and modeless now. Although, hm, it doesn't
matter, modal keeps the focus, and by definition, there's no issue,
you can't close the app if a dialog has focus and won't let it go. So
it really doesn't matter what would happen if the app closed with a
modal open, since it just shouldn't happen under normal circumstances.
Yes, with both modal and modeless dialogs (forms) the resources are
disposed of when the form is closed. The difference is that with a modal
dialog (form), the form is not actually closed at the point in time that
it visually appears to be closed. The actual closing doesn't happen until
later.
Ok, I am having a serious issue with this. A modal dialog, one that
keeps focus until it is closed, is not actually closed when it
visually disappears. But, I have a modeless dialog doing the same
thing (displaying data in it that remains, as proof). So, neither
actually closes when it visually disappears. So, what happens when I
click 'x' on a message box, from MessageBox()? It must actually close
sometime, since I'll never reference it again. They must close when
the reference goes out of scope? That would explain the difference in
FormClosed being called for one of my modeless and not the other,
since the scope of one is the lifetime of the main form, and the scope
of the other is just a button handler.
Thanks for your help, Pete
Zytan