Results 1 to 27 of 27

Thread: Unloading Forms

  1. #1

    Thread Starter
    Frenzied Member RudyL's Avatar
    Join Date
    Mar 2001
    Location
    Chicago
    Posts
    1,519

    Question 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".

  2. #2
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    404

    Re: Unloading Forms

    .Dispose


  3. #3
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    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."

  4. #4

    Thread Starter
    Frenzied Member RudyL's Avatar
    Join Date
    Mar 2001
    Location
    Chicago
    Posts
    1,519

    Re: Unloading Forms

    Thanks!
    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".

  5. #5

    Thread Starter
    Frenzied Member RudyL's Avatar
    Join Date
    Mar 2001
    Location
    Chicago
    Posts
    1,519

    Re: Unloading Forms

    Quote Originally Posted by SJWhiteley View Post
    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".

  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    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

  7. #7
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    404

    Re: Unloading Forms

    I think it's likely to be the default instances issue as I've had this issue before as well shaggy

  8. #8

    Thread Starter
    Frenzied Member RudyL's Avatar
    Join Date
    Mar 2001
    Location
    Chicago
    Posts
    1,519

    Re: Unloading Forms

    Quote Originally Posted by Shaggy Hiker View Post
    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".

  9. #9
    Still learning kebo's Avatar
    Join Date
    Apr 2004
    Location
    Gardnerville,nv
    Posts
    3,757

    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

    Quote 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....

    Quote 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

  10. #10

    Thread Starter
    Frenzied Member RudyL's Avatar
    Join Date
    Mar 2001
    Location
    Chicago
    Posts
    1,519

    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".

  11. #11
    Still learning kebo's Avatar
    Join Date
    Apr 2004
    Location
    Gardnerville,nv
    Posts
    3,757

    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

  12. #12
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    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

  13. #13
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    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."

  14. #14
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    Re: Unloading Forms

    Quote Originally Posted by SJWhiteley View Post
    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.

    Quote Originally Posted by kebo View Post
    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
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  15. #15

    Thread Starter
    Frenzied Member RudyL's Avatar
    Join Date
    Mar 2001
    Location
    Chicago
    Posts
    1,519

    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".

  16. #16
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Unloading Forms

    Quote Originally Posted by techgnome View Post
    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."

  17. #17
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Unloading Forms

    Quote Originally Posted by RudyL View Post
    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."

  18. #18

    Thread Starter
    Frenzied Member RudyL's Avatar
    Join Date
    Mar 2001
    Location
    Chicago
    Posts
    1,519

    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".

  19. #19
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    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
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  20. #20
    Still learning kebo's Avatar
    Join Date
    Apr 2004
    Location
    Gardnerville,nv
    Posts
    3,757

    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

  21. #21
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    404

    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/

  22. #22
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    404

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

  23. #23
    Still learning kebo's Avatar
    Join Date
    Apr 2004
    Location
    Gardnerville,nv
    Posts
    3,757

    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

  24. #24

    Thread Starter
    Frenzied Member RudyL's Avatar
    Join Date
    Mar 2001
    Location
    Chicago
    Posts
    1,519

    Re: Unloading Forms

    Quote Originally Posted by techgnome View Post
    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".

  25. #25
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    404

    Re: Unloading Forms

    Quote Originally Posted by kebo View Post
    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:
    1. /// <include file='doc\Form.uex' path='docs/doc[@for="Form.Dispose"]/*' />
    2.         /// <devdoc>
    3.         ///    <para>Releases all the system resources associated with the Form. If a subclass
    4.         ///       overrides this function, it must call the base implementation.</para>
    5.         /// </devdoc>
    6.         protected override void Dispose(bool disposing) {
    7.             if (disposing) {
    8.                 CalledOnLoad = false;
    9.                 CalledMakeVisible = false;
    10.                 CalledCreateControl = false;
    11.  
    12.                 if (Properties.ContainsObject(PropAcceptButton)) Properties.SetObject(PropAcceptButton, null);
    13.                 if (Properties.ContainsObject(PropCancelButton)) Properties.SetObject(PropCancelButton, null);
    14.                 if (Properties.ContainsObject(PropDefaultButton)) Properties.SetObject(PropDefaultButton, null);
    15.                 if (Properties.ContainsObject(PropActiveMdiChild)) Properties.SetObject(PropActiveMdiChild, null);
    16.  
    17.                 if (MdiWindowListStrip != null){
    18.                     MdiWindowListStrip.Dispose();
    19.                     MdiWindowListStrip = null;
    20.                 }
    21.  
    22.                 if (MdiControlStrip != null){
    23.                     MdiControlStrip.Dispose();
    24.                     MdiControlStrip = null;
    25.                 }
    26.  
    27.                 if (MainMenuStrip != null) {
    28.                     // should NOT call dispose on MainMenuStrip - it's likely NOT to be in the form's control collection.
    29.                     MainMenuStrip = null;
    30.                 }
    31.              
    32.                 Form owner = (Form)Properties.GetObject(PropOwner);
    33.                 if (owner != null) {
    34.                     owner.RemoveOwnedForm(this);
    35.                     Properties.SetObject(PropOwner, null);
    36.                 }
    37.  
    38.                 Form[] ownedForms = (Form[])Properties.GetObject(PropOwnedForms);
    39.                 int ownedFormsCount = Properties.GetInteger(PropOwnedFormsCount);
    40.  
    41.                 for (int i = ownedFormsCount-1 ; i >= 0; i--) {
    42.                     if (ownedForms[i] != null) {
    43.                         // it calls remove and removes itself.
    44.                         ownedForms[i].Dispose();
    45.                     }
    46.                 }
    47.  
    48.                 if (smallIcon != null) {
    49.                     smallIcon.Dispose();
    50.                     smallIcon = null;
    51.                 }
    52.  
    53.                 ResetSecurityTip(false /* modalOnly */);
    54.  
    55.                 base.Dispose(disposing);
    56.                 ctlClient = null;
    57.  
    58.                 MainMenu mainMenu = Menu;
    59.  
    60.                 // VSWhidbey 93518, 93544, 93547, 93563, and 93568: We should only dispose this form's menus!
    61.                 if (mainMenu != null && mainMenu.ownerForm == this) {
    62.                     mainMenu.Dispose();
    63.                     Properties.SetObject(PropMainMenu, null);
    64.                 }
    65.  
    66.                 if (Properties.GetObject(PropCurMenu) != null) {
    67.                     Properties.SetObject(PropCurMenu, null);
    68.                 }
    69.  
    70.                 MenuChanged(Windows.Forms.Menu.CHANGE_ITEMS, null);
    71.  
    72.                 MainMenu dummyMenu = (MainMenu)Properties.GetObject(PropDummyMenu);
    73.  
    74.                 if (dummyMenu != null) {
    75.                     dummyMenu.Dispose();
    76.                     Properties.SetObject(PropDummyMenu, null);
    77.                 }
    78.  
    79.                 MainMenu mergedMenu = (MainMenu)Properties.GetObject(PropMergedMenu);
    80.  
    81.                 if (mergedMenu != null) {
    82.                     if (mergedMenu.ownerForm == this || mergedMenu.form == null) {
    83.                         mergedMenu.Dispose();
    84.                     }
    85.                     Properties.SetObject(PropMergedMenu, null);
    86.                 }
    87.             }
    88.             else {
    89.                 base.Dispose(disposing);
    90.             }
    91.         }

  26. #26
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    404

    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)

  27. #27
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Unloading Forms

    Quote Originally Posted by RudyL View Post
    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
  •  



Click Here to Expand Forum to Full Width