-
May 20th, 2015, 01:54 PM
#1
Thread Starter
Frenzied Member
Unloading Forms
Something I noticed today... Form.Close() does NOT unload the form.. (as in old VB6 days). So when I Close the form the next time I load it (Form.ShowDialog) any residual data from the previous time it was displayed is still present. Oddly enough the Form_Load routine still fires off as if it were properly "unloaded"...
My question is (to avoid having to set all kinds of defaults at load), how do I "unload" a form when I want to close it so when it's re-opened there is no residual data from the previous time is was loaded?
And this all happens while running the app. If I close the app and relaunch it everything is fine (no surprises there)
Here's an example:
Form 1 has a button that calls Form2.ShowDialog
On form 2 there is a text box and a button to Exit.
Type some stuff in the test box and then click on button to exit. That button executes Me.Close()
The click on the button on form 1 and the data in the text box from form 2 is still there.
10 different ways to skin a cat and amazingly enough each and every one has the same result, the cat gets skinned! The same can be applied to code, so be nice and accept each others "preferences".
-
May 20th, 2015, 01:56 PM
#2
Hyperactive Member
Re: Unloading Forms
.Dispose
-
May 20th, 2015, 02:04 PM
#3
Re: Unloading Forms
You don't want to actually get rid of the form after closing when the form is displayed using ShowDialog(). How would you access the properties of the dialog shown if it's completely gone? You can use the Show() method, instead, if you don't want a dialog.
If you do need a dialog, create a new instance of the form, rather than using the default instance:
Code:
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim f As New Form2
f.ShowDialog()
End Sub
"Ok, my response to that is pending a Google search" - Bucky Katt.
"There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
"Before you can 'think outside the box' you need to understand where the box is."
-
May 20th, 2015, 02:09 PM
#4
Thread Starter
Frenzied Member
10 different ways to skin a cat and amazingly enough each and every one has the same result, the cat gets skinned! The same can be applied to code, so be nice and accept each others "preferences".
-
May 20th, 2015, 02:10 PM
#5
Thread Starter
Frenzied Member
Re: Unloading Forms
Originally Posted by SJWhiteley
You don't want to actually get rid of the form after closing when the form is displayed using ShowDialog(). How would you access the properties of the dialog shown if it's completely gone? You can use the Show() method, instead, if you don't want a dialog.
I'm using ShowDialog to ensure that the calling form is not accessible while the called form is in use. Basically, forcing the user to finish their task before doing something else.
10 different ways to skin a cat and amazingly enough each and every one has the same result, the cat gets skinned! The same can be applied to code, so be nice and accept each others "preferences".
-
May 20th, 2015, 03:41 PM
#6
Re: Unloading Forms
What you described shouldn't normally be happening. There isn't any such thing as residual data. Each instance of a form is unique. The controls in it are unique, the form itself is unique, and so forth. Forms are just classes. If you have a cat that loses a leg in an accident, you wouldn't expect other cats to suddenly be three-legged, as well.
So, though I can't say how it is happening, you aren't actually showing a new instance of a form if some of the old data is there. Whether this is some strange quirk of the default instances (which do have some strange quirks, though I have never heard of anything like this), or something that you managed to do without realizing it (that would be quite a trick, in this case), I can't say. It isn't normal, though.
Calling .Close does different things for modal and non-modal, but for modal forms, it will do exactly what you expect it to do...eventually. It doesn't get destroyed right away, but it will in time. However, you shouldn't be able to show it again. Perhaps the default instance doesn't work that way.
My usual boring signature: Nothing
-
May 20th, 2015, 03:43 PM
#7
Hyperactive Member
Re: Unloading Forms
I think it's likely to be the default instances issue as I've had this issue before as well shaggy
-
May 20th, 2015, 03:46 PM
#8
Thread Starter
Frenzied Member
Re: Unloading Forms
Originally Posted by Shaggy Hiker
What you described shouldn't normally be happening. There isn't any such thing as residual data. Each instance of a form is unique. The controls in it are unique, the form itself is unique, and so forth. Forms are just classes. If you have a cat that loses a leg in an accident, you wouldn't expect other cats to suddenly be three-legged, as well.
So, though I can't say how it is happening, you aren't actually showing a new instance of a form if some of the old data is there. Whether this is some strange quirk of the default instances (which do have some strange quirks, though I have never heard of anything like this), or something that you managed to do without realizing it (that would be quite a trick, in this case), I can't say. It isn't normal, though.
Calling .Close does different things for modal and non-modal, but for modal forms, it will do exactly what you expect it to do...eventually. It doesn't get destroyed right away, but it will in time. However, you shouldn't be able to show it again. Perhaps the default instance doesn't work that way.
I'm with you Shaggy... I did not expect for that data to be in there. Once of the things I had going on is I'm populating a Dropdown list box with 3 values at load... Each time I "showed" the form after closing it that items in the listbox grew by 3's every time... Very odd behavior IMO
10 different ways to skin a cat and amazingly enough each and every one has the same result, the cat gets skinned! The same can be applied to code, so be nice and accept each others "preferences".
-
May 20th, 2015, 05:14 PM
#9
Re: Unloading Forms
This seems to be more about variable scope than anything else. But there is something a bit fishy. According to the document for the Form Load Event
Originally Posted by msdn
Occurs before a form is displayed for the first time.
But try this on for size....
Code:
Public Class Form1
Dim f As New Form2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
f.ShowDialog()
End Sub
End Class
Public Class Form2
Public Sub New()
' This call is required by the designer.
InitializeComponent()
i = 0
End Sub
Dim i As Integer = 0
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
i += 1
Me.Text = i.ToString
End Sub
End Class
When you run it, each time the button in form 1 is clicked, form2 is displayed and the variable i is incremented. Since there is only 1 instance of form2 created, the form2 constructor only runs once as expected. HOWEVER, each time form2 is shown, the load event fires, as indicated by the incremented variable. This is contrary to the documentation for the load event.
Further, from the documentation for the ShowDialog method....
Originally Posted by 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. Unlike non-modal forms, the Close method is not called by the .NET Framework when the user clicks the close form button of a dialog box or sets the value of the DialogResult property. Instead the form is hidden and can be shown again without creating a new instance of the dialog box. Because a form displayed as a dialog box is hidden instead of closed, you must call the Dispose method of the form when the form is no longer needed by your application.
Edit,
Even if you are using the default form instance, rather than creating a new Form2 instance, the behavior mentioned above still exists. By disposing of Form2 directly after the ShowDialog call, the default instance gets released and a new default instance is created during the next button click. Without the dispose, the default Form2 instance is reused.
Last edited by kebo; May 20th, 2015 at 06:22 PM.
Process control doesn't give you good quality, it gives you consistent quality.
Good quality comes from consistently doing the right things.
Vague general questions have vague general answers. A $100 donation is required for me to help you if you PM me asking for help. Instructions for donating to one of our local charities will be provided.
______________________________ Last edited by kebo : Now. Reason: superfluous typo's
-
May 20th, 2015, 05:44 PM
#10
Thread Starter
Frenzied Member
Re: Unloading Forms
I think that nails down kebo - I'll try playing around with your other example tomorrow but I think the dispose is the fix here.
10 different ways to skin a cat and amazingly enough each and every one has the same result, the cat gets skinned! The same can be applied to code, so be nice and accept each others "preferences".
-
May 20th, 2015, 05:46 PM
#11
Re: Unloading Forms
I think that nails down kebo
O don't nail me down.... I'm free I say, free
GL with it.
Process control doesn't give you good quality, it gives you consistent quality.
Good quality comes from consistently doing the right things.
Vague general questions have vague general answers. A $100 donation is required for me to help you if you PM me asking for help. Instructions for donating to one of our local charities will be provided.
______________________________ Last edited by kebo : Now. Reason: superfluous typo's
-
May 20th, 2015, 06:00 PM
#12
Re: Unloading Forms
Very nice. I have never seen that behavior before, and I know why: I have never done anything like what you showed. Seems like there would be a use for it, I just have never encountered one in practice.
My usual boring signature: Nothing
-
May 21st, 2015, 07:38 AM
#13
Re: Unloading Forms
Again, don't use the default instances when creating forms. It'll result in less confusion, as you will know exactly what instance you are dealing with.
While the 'load' documentation seems a bit of a misdirection, this is correct behavior for a dialog box. With a Dialog, you would most likely want the Load event to fire when the dialog is shown, the alternative is to not run the form load: how would you then 'load' a reused dialog box?
In the method with the ShowDialog() method called, you are practically 'showing the dialog for the first time', even though the dialog may have previously been shown. The object still exists, and while it is technically hidden, for all practical purposes you are showing and closing the dialog.
To reiterate, most of this confusion can be avoided by not using the default instances, particularly in this case, but there may be rare situations where the default instance is more appropriate. If you 'initialize' your dialog when it is shown in the 'load' event, it won't actually matter if you use the default instance or not.
"Ok, my response to that is pending a Google search" - Bucky Katt.
"There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
"Before you can 'think outside the box' you need to understand where the box is."
-
May 21st, 2015, 09:02 AM
#14
Re: Unloading Forms
Originally Posted by SJWhiteley
Again, don't use the default instances when creating forms. It'll result in less confusion, as you will know exactly what instance you are dealing with.
While the 'load' documentation seems a bit of a misdirection, this is correct behavior for a dialog box. With a Dialog, you would most likely want the Load event to fire when the dialog is shown, the alternative is to not run the form load: how would you then 'load' a reused dialog box?
In the method with the ShowDialog() method called, you are practically 'showing the dialog for the first time', even though the dialog may have previously been shown. The object still exists, and while it is technically hidden, for all practical purposes you are showing and closing the dialog.
To reiterate, most of this confusion can be avoided by not using the default instances, particularly in this case, but there may be rare situations where the default instance is more appropriate. If you 'initialize' your dialog when it is shown in the 'load' event, it won't actually matter if you use the default instance or not.
but if you look at keebo's exqample... it isn't a default instance... it is an explicitly created form - created once, so it mimics the way default instances are.
Originally Posted by kebo
This seems to be more about variable scope than anything else. But there is something a bit fishy. According to the document for the Form Load Event
But try this on for size....
Code:
Public Class Form1
Dim f As New Form2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
f.ShowDialog()
End Sub
End Class
Public Class Form2
Public Sub New()
' This call is required by the designer.
InitializeComponent()
i = 0
End Sub
Dim i As Integer = 0
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
i += 1
Me.Text = i.ToString
End Sub
End Class
When you run it, each time the button in form 1 is clicked, form2 is displayed and the variable i is incremented. Since there is only 1 instance of form2 created, the form2 constructor only runs once as expected. HOWEVER, each time form2 is shown, the load event fires, as indicated by the incremented variable. This is contrary to the documentation for the load event.
Further, from the documentation for the ShowDialog method....
Edit,
Even if you are using the default form instance, rather than creating a new Form2 instance, the behavior mentioned above still exists. By disposing of Form2 directly after the ShowDialog call, the default instance gets released and a new default instance is created during the next button click. Without the dispose, the default Form2 instance is reused.
I wonder if what's happening is that there is an unlaod happening as a result of using DialogResult... but it isn't disposed... hmmm...
warrants further testing.
-tg
-
May 21st, 2015, 09:08 AM
#15
Thread Starter
Frenzied Member
Re: Unloading Forms
It's interesting in that MS dropped the "Unload" event from the VB6 days and seems to have replaced it with a "Close" event. However, to properly unload - or close - a form you also have to Dispose of it. Makes sense to me (kinda) but I think MS has made a simple process more difficult - not unexpected when comparing VB6 days to now.. IMO
I'm leaning towards this is intended behavior based on how they have implemented the Dispose methodology throughout.
10 different ways to skin a cat and amazingly enough each and every one has the same result, the cat gets skinned! The same can be applied to code, so be nice and accept each others "preferences".
-
May 21st, 2015, 09:27 AM
#16
Re: Unloading Forms
Originally Posted by techgnome
but if you look at keebo's exqample... it isn't a default instance... it is an explicitly created form - created once, so it mimics the way default instances are.
...
Yes you are correct on both counts: it mimics the default instance so acts exactly the same way, so we may as well treat it as a default instance.
"Ok, my response to that is pending a Google search" - Bucky Katt.
"There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
"Before you can 'think outside the box' you need to understand where the box is."
-
May 21st, 2015, 09:30 AM
#17
Re: Unloading Forms
Originally Posted by RudyL
It's interesting in that MS dropped the "Unload" event from the VB6 days and seems to have replaced it with a "Close" event. However, to properly unload - or close - a form you also have to Dispose of it. Makes sense to me (kinda) but I think MS has made a simple process more difficult - not unexpected when comparing VB6 days to now.. IMO
I'm leaning towards this is intended behavior based on how they have implemented the Dispose methodology throughout.
Yes, it is more difficult: the reason being is that they wanted (were required to) mimic VB6 behavior, but also expose the nuts and bolts of windows framework, like almost every other windows programming language. The whole point of VB6s simplicity was to hide that. And it was, indeed, much easier to work with. So, we have two conflicting objectives built into the language, adding what is really only a small amount of complexity to an otherwise simple operation.
"Ok, my response to that is pending a Google search" - Bucky Katt.
"There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
"Before you can 'think outside the box' you need to understand where the box is."
-
May 21st, 2015, 09:32 AM
#18
Thread Starter
Frenzied Member
Re: Unloading Forms
I believe MS calls that "Progress"
10 different ways to skin a cat and amazingly enough each and every one has the same result, the cat gets skinned! The same can be applied to code, so be nice and accept each others "preferences".
-
May 21st, 2015, 09:42 AM
#19
Re: Unloading Forms
It seems the way .Show and .ShowDialog work are different... I know that goes w/o saying but here's what I tried:
using Keebo's example code, I expanded it to use two instances of Form2 ... one that is shown using ShowDialog and the other using Show ... if i click the button that uses Showdialog, the form will appear each time, with the number incremented, no errors. With the .Show method though, the form was only available once. If I tried to click it a second time, I'd get the "cannot accessed a disposed object" exception.
This leads me to believe that Showdialog closes/unloads the form, but doesn't dispose it - this is by design so that you can access it afterwards. However, when you close a form that's using .Show ... it is disposed automatically when it is closed.
Now that I think about it, i've run into this before, i just never gave it too much thought. Anything I want to run once and only once when the form is created I'll put into the constructor, or add checks/flags to the Load event to ensure that somethings happen only once.
-tg
-
May 21st, 2015, 10:03 AM
#20
Re: Unloading Forms
However, when you close a form that's using .Show ... it is disposed automatically when it is closed.
Yea, that's exactly right. The close documentation states the only time a form is not disposed of when it's closed is when it's an MDI child and when it's displayed using showDialog. Since you can't show an MDI child with showDialog anyway, there is really only one condition the form is not disposed after closing it.
Regarding the default instances, the only difference I have seen between the default instance and an explicit instance is how and when the constructor is called. For the explicit instance, you obviously call the constructor, but with the default instance, the constructor will run we you first reference the form. After that, the default instance seems to behave identically to an explicit instance.
Process control doesn't give you good quality, it gives you consistent quality.
Good quality comes from consistently doing the right things.
Vague general questions have vague general answers. A $100 donation is required for me to help you if you PM me asking for help. Instructions for donating to one of our local charities will be provided.
______________________________ Last edited by kebo : Now. Reason: superfluous typo's
-
May 21st, 2015, 10:06 AM
#21
Hyperactive Member
Re: Unloading Forms
Code:
/// <include file='doc\Form.uex' path='docs/doc[@for="Form.ShowDialog"]/*' />
/// <devdoc>
/// <para>Displays this form as a modal dialog box with no owner window.</para>
/// </devdoc>
public DialogResult ShowDialog() {
return ShowDialog(null);
}
/// <include file='doc\Form.uex' path='docs/doc[@for="Form.ShowDialog1"]/*' />
/// <devdoc>
/// <para>Shows this form as a modal dialog with the specified owner.</para>
/// </devdoc>
public DialogResult ShowDialog(IWin32Window owner) {
if (owner == this) {
throw new ArgumentException(SR.GetString(SR.OwnsSelfOrOwner,
"showDialog"), "owner");
}
else if (Visible) {
throw new InvalidOperationException(SR.GetString(SR.ShowDialogOnVisible,
"showDialog"));
}
else if (!Enabled) {
throw new InvalidOperationException(SR.GetString(SR.ShowDialogOnDisabled,
"showDialog"));
}
else if (!TopLevel) {
throw new InvalidOperationException(SR.GetString(SR.ShowDialogOnNonTopLevel,
"showDialog"));
}
else if (Modal) {
throw new InvalidOperationException(SR.GetString(SR.ShowDialogOnModal,
"showDialog"));
}
else if (!SystemInformation.UserInteractive) {
throw new InvalidOperationException(SR.GetString(SR.CantShowModalOnNonInteractive));
}
else if ( (owner != null) && ((int)UnsafeNativeMethods.GetWindowLong(new HandleRef(owner, Control.GetSafeHandle(owner)), NativeMethods.GWL_EXSTYLE)
& NativeMethods.WS_EX_TOPMOST) == 0 ) { // It's not the top-most window
if (owner is Control) {
owner = ((Control)owner).TopLevelControlInternal;
}
}
this.CalledOnLoad = false;
this.CalledMakeVisible = false;
// for modal dialogs make sure we reset close reason.
this.CloseReason = CloseReason.None;
IntPtr hWndCapture = UnsafeNativeMethods.GetCapture();
if (hWndCapture != IntPtr.Zero) {
UnsafeNativeMethods.SendMessage(new HandleRef(null, hWndCapture), NativeMethods.WM_CANCELMODE, IntPtr.Zero, IntPtr.Zero);
SafeNativeMethods.ReleaseCapture();
}
IntPtr hWndActive = UnsafeNativeMethods.GetActiveWindow();
IntPtr hWndOwner = owner == null ? hWndActive : Control.GetSafeHandle(owner);
IntPtr hWndOldOwner = IntPtr.Zero;
Properties.SetObject(PropDialogOwner, owner);
Form oldOwner = OwnerInternal;
if (owner is Form && owner != oldOwner) {
Owner = (Form)owner;
}
try {
SetState(STATE_MODAL, true);
// ASURT 102728
// It's possible that while in the process of creating the control,
// (i.e. inside the CreateControl() call) the dialog can be closed.
// e.g. A user might call Close() inside the OnLoad() event.
// Calling Close() will set the DialogResult to some value, so that
// we'll know to terminate the RunDialog loop immediately.
// Thus we must initialize the DialogResult *before* the call
// to CreateControl().
//
dialogResult = DialogResult.None;
// V#36617 - if "this" is an MDI parent then the window gets activated,
// causing GetActiveWindow to return "this.handle"... to prevent setting
// the owner of this to this, we must create the control AFTER calling
// GetActiveWindow.
//
CreateControl();
if (hWndOwner != IntPtr.Zero && hWndOwner != Handle) {
// Catch the case of a window trying to own its owner
if (UnsafeNativeMethods.GetWindowLong(new HandleRef(owner, hWndOwner), NativeMethods.GWL_HWNDPARENT) == Handle) {
throw new ArgumentException(SR.GetString(SR.OwnsSelfOrOwner,
"showDialog"), "owner");
}
// Set the new owner.
hWndOldOwner = UnsafeNativeMethods.GetWindowLong(new HandleRef(this, Handle), NativeMethods.GWL_HWNDPARENT);
UnsafeNativeMethods.SetWindowLong(new HandleRef(this, Handle), NativeMethods.GWL_HWNDPARENT, new HandleRef(owner, hWndOwner));
}
try {
// If the DialogResult was already set, then there's
// no need to actually display the dialog.
//
if (dialogResult == DialogResult.None)
{
// Application.RunDialog sets this dialog to be visible.
Application.RunDialog(this);
}
}
finally {
// Call SetActiveWindow before setting Visible = false.
//
if (!UnsafeNativeMethods.IsWindow(new HandleRef(null, hWndActive))) hWndActive = hWndOwner;
if (UnsafeNativeMethods.IsWindow(new HandleRef(null, hWndActive)) && SafeNativeMethods.IsWindowVisible(new HandleRef(null, hWndActive))) {
UnsafeNativeMethods.SetActiveWindow(new HandleRef(null, hWndActive));
}
else if (UnsafeNativeMethods.IsWindow(new HandleRef(null, hWndOwner)) && SafeNativeMethods.IsWindowVisible(new HandleRef(null, hWndOwner))){
UnsafeNativeMethods.SetActiveWindow(new HandleRef(null, hWndOwner));
}
SetVisibleCore(false);
if (IsHandleCreated) {
// VSWhidbey 94917: If this is a dialog opened from an MDI Container, then invalidate
// so that child windows will be properly updated.
if (this.OwnerInternal != null &&
this.OwnerInternal.IsMdiContainer) {
this.OwnerInternal.Invalidate(true);
this.OwnerInternal.Update();
}
// VSWhidbey 430476 - Everett/RTM used to wrap this in an assert for AWP.
DestroyHandle();
}
SetState(STATE_MODAL, false);
}
}
finally {
Owner = oldOwner;
Properties.SetObject(PropDialogOwner, null);
}
return DialogResult;
}
Code:
/// <include file='doc\Form.uex' path='docs/doc[@for="Form.Show"]/*' />
/// <devdoc>
/// Makes the control display by setting the visible property to true
/// </devdoc>
public void Show(IWin32Window owner) {
if (owner == this) {
throw new InvalidOperationException(SR.GetString(SR.OwnsSelfOrOwner,
"Show"));
}
else if (Visible) {
throw new InvalidOperationException(SR.GetString(SR.ShowDialogOnVisible,
"Show"));
}
else if (!Enabled) {
throw new InvalidOperationException(SR.GetString(SR.ShowDialogOnDisabled,
"Show"));
}
else if (!TopLevel) {
throw new InvalidOperationException(SR.GetString(SR.ShowDialogOnNonTopLevel,
"Show"));
}
else if (!SystemInformation.UserInteractive) {
throw new InvalidOperationException(SR.GetString(SR.CantShowModalOnNonInteractive));
}
else if ( (owner != null) && ((int)UnsafeNativeMethods.GetWindowLong(new HandleRef(owner, Control.GetSafeHandle(owner)), NativeMethods.GWL_EXSTYLE)
& NativeMethods.WS_EX_TOPMOST) == 0 ) { // It's not the top-most window
if (owner is Control) {
owner = ((Control)owner).TopLevelControlInternal;
}
}
IntPtr hWndActive = UnsafeNativeMethods.GetActiveWindow();
IntPtr hWndOwner = owner == null ? hWndActive : Control.GetSafeHandle(owner);
IntPtr hWndOldOwner = IntPtr.Zero;
Properties.SetObject(PropDialogOwner, owner);
Form oldOwner = OwnerInternal;
if (owner is Form && owner != oldOwner) {
Owner = (Form)owner;
}
if (hWndOwner != IntPtr.Zero && hWndOwner != Handle) {
// Catch the case of a window trying to own its owner
if (UnsafeNativeMethods.GetWindowLong(new HandleRef(owner, hWndOwner), NativeMethods.GWL_HWNDPARENT) == Handle) {
throw new ArgumentException(SR.GetString(SR.OwnsSelfOrOwner,
"show"), "owner");
}
// Set the new owner.
hWndOldOwner = UnsafeNativeMethods.GetWindowLong(new HandleRef(this, Handle), NativeMethods.GWL_HWNDPARENT);
UnsafeNativeMethods.SetWindowLong(new HandleRef(this, Handle), NativeMethods.GWL_HWNDPARENT, new HandleRef(owner, hWndOwner));
}
Visible = true;
}
Here is the code from MS, in c#.
i carnt see what within this causes the effect maybe one of you can/
-
May 21st, 2015, 12:44 PM
#22
Hyperactive Member
Re: Unloading Forms
however the close event suggests that all forms being closed modal/nonmodal dialog/non dialog are all disposed of upon the close event being called
Code:
/// <include file='doc\Form.uex' path='docs/doc[@for="Form.Close"]/*' />
/// <devdoc>
/// <para>Closes the form.</para>
/// </devdoc>
public void Close() {
if (GetState(STATE_CREATINGHANDLE))
throw new InvalidOperationException(SR.GetString(SR.ClosingWhileCreatingHandle, "Close"));
if (IsHandleCreated) {
closeReason = CloseReason.UserClosing;
SendMessage(NativeMethods.WM_CLOSE, 0, 0);
}
else{
// MSDN: When a form is closed, all resources created within the object are closed and the form is disposed.
// For MDI child: MdiChildren collection gets updated (VSWhidbey# 368642 & 93550)
Dispose();
}
}
-
May 21st, 2015, 12:51 PM
#23
Re: Unloading Forms
however the close event suggests that all forms being closed modal/nonmodal dialog/non dialog are all disposed of upon the close event being called
That's not the case. At least not in vb.net. I'm not a c#'er so maybe it's different.
edit that,
It does appear that way from the code you posted, but the form behavior would suggest differently.
Code:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim f As New Form2
f.ShowDialog()
MessageBox.Show(f.IsDisposed.ToString)
f.Dispose()
MessageBox.Show(f.IsDisposed.ToString)
End Sub
End Class
Process control doesn't give you good quality, it gives you consistent quality.
Good quality comes from consistently doing the right things.
Vague general questions have vague general answers. A $100 donation is required for me to help you if you PM me asking for help. Instructions for donating to one of our local charities will be provided.
______________________________ Last edited by kebo : Now. Reason: superfluous typo's
-
May 21st, 2015, 01:01 PM
#24
Thread Starter
Frenzied Member
Re: Unloading Forms
Originally Posted by techgnome
It seems the way .Show and .ShowDialog work are different... I know that goes w/o saying but here's what I tried:
using Keebo's example code, I expanded it to use two instances of Form2 ... one that is shown using ShowDialog and the other using Show ... if i click the button that uses Showdialog, the form will appear each time, with the number incremented, no errors. With the .Show method though, the form was only available once. If I tried to click it a second time, I'd get the "cannot accessed a disposed object" exception.
This leads me to believe that Showdialog closes/unloads the form, but doesn't dispose it - this is by design so that you can access it afterwards. However, when you close a form that's using .Show ... it is disposed automatically when it is closed.
Now that I think about it, i've run into this before, i just never gave it too much thought. Anything I want to run once and only once when the form is created I'll put into the constructor, or add checks/flags to the Load event to ensure that somethings happen only once.
-tg
Thinking about this more, it leads me to believe this is done so you have a more defined / direct method to create custom message box / input box type forms.
10 different ways to skin a cat and amazingly enough each and every one has the same result, the cat gets skinned! The same can be applied to code, so be nice and accept each others "preferences".
-
May 21st, 2015, 01:15 PM
#25
Hyperactive Member
Re: Unloading Forms
Originally Posted by kebo
That's not the case. At least not in vb.net. I'm not a c#'er so maybe it's different.
edit that,
It does appear that way from the code you posted, but the form behavior would suggest differently.
Code:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim f As New Form2
f.ShowDialog()
MessageBox.Show(f.IsDisposed.ToString)
f.Dispose()
MessageBox.Show(f.IsDisposed.ToString)
End Sub
End Class
looking into this the dispose event acts differently depending on being modal/not modal but this is only a small difference on line 53
c# Code:
/// <include file='doc\Form.uex' path='docs/doc[@for="Form.Dispose"]/*' /> /// <devdoc> /// <para>Releases all the system resources associated with the Form. If a subclass /// overrides this function, it must call the base implementation.</para> /// </devdoc> protected override void Dispose(bool disposing) { if (disposing) { CalledOnLoad = false; CalledMakeVisible = false; CalledCreateControl = false; if (Properties.ContainsObject(PropAcceptButton)) Properties.SetObject(PropAcceptButton, null); if (Properties.ContainsObject(PropCancelButton)) Properties.SetObject(PropCancelButton, null); if (Properties.ContainsObject(PropDefaultButton)) Properties.SetObject(PropDefaultButton, null); if (Properties.ContainsObject(PropActiveMdiChild)) Properties.SetObject(PropActiveMdiChild, null); if (MdiWindowListStrip != null){ MdiWindowListStrip.Dispose(); MdiWindowListStrip = null; } if (MdiControlStrip != null){ MdiControlStrip.Dispose(); MdiControlStrip = null; } if (MainMenuStrip != null) { // should NOT call dispose on MainMenuStrip - it's likely NOT to be in the form's control collection. MainMenuStrip = null; } Form owner = (Form)Properties.GetObject(PropOwner); if (owner != null) { owner.RemoveOwnedForm(this); Properties.SetObject(PropOwner, null); } Form[] ownedForms = (Form[])Properties.GetObject(PropOwnedForms); int ownedFormsCount = Properties.GetInteger(PropOwnedFormsCount); for (int i = ownedFormsCount-1 ; i >= 0; i--) { if (ownedForms[i] != null) { // it calls remove and removes itself. ownedForms[i].Dispose(); } } if (smallIcon != null) { smallIcon.Dispose(); smallIcon = null; } ResetSecurityTip(false /* modalOnly */); base.Dispose(disposing); ctlClient = null; MainMenu mainMenu = Menu; // VSWhidbey 93518, 93544, 93547, 93563, and 93568: We should only dispose this form's menus! if (mainMenu != null && mainMenu.ownerForm == this) { mainMenu.Dispose(); Properties.SetObject(PropMainMenu, null); } if (Properties.GetObject(PropCurMenu) != null) { Properties.SetObject(PropCurMenu, null); } MenuChanged(Windows.Forms.Menu.CHANGE_ITEMS, null); MainMenu dummyMenu = (MainMenu)Properties.GetObject(PropDummyMenu); if (dummyMenu != null) { dummyMenu.Dispose(); Properties.SetObject(PropDummyMenu, null); } MainMenu mergedMenu = (MainMenu)Properties.GetObject(PropMergedMenu); if (mergedMenu != null) { if (mergedMenu.ownerForm == this || mergedMenu.form == null) { mergedMenu.Dispose(); } Properties.SetObject(PropMergedMenu, null); } } else { base.Dispose(disposing); } }
-
May 21st, 2015, 01:33 PM
#26
Hyperactive Member
Re: Unloading Forms
further to this run the below code and you will receive false true true, false true true
which shows that the close method always disposes of the form
Code:
f = New Form1
f.ShowDialog()
Debug.Print(f.IsDisposed.ToString)
f.Close()
Debug.Print(f.IsDisposed.ToString)
f.Dispose()
Debug.Print(f.IsDisposed.ToString)
f = New Form1
f.Show()
Debug.Print(f.IsDisposed.ToString)
f.Close()
Debug.Print(f.IsDisposed.ToString)
f.Dispose()
Debug.Print(f.IsDisposed.ToString)
-
May 21st, 2015, 02:36 PM
#27
Re: Unloading Forms
Originally Posted by RudyL
Thinking about this more, it leads me to believe this is done so you have a more defined / direct method to create custom message box / input box type forms.
Yep. As noted, already, it allows you to access the results of that dialog. It is by design.
"Ok, my response to that is pending a Google search" - Bucky Katt.
"There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
"Before you can 'think outside the box' you need to understand where the box is."
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|