Closing MDI Child Form Won't Reopen? Help!

S

Siv

Hi,
I have an MDI application with child forms. I want to close a child form
and then reopen a new instance of it, but for some reason I can't reopen it
after initially opening an instance and then closing that instance. I use
the close method and then dispose of the instance variable, but it behaves
as if the dispose hasn't completed. My code is as follows:

In my module I have:

Friend F2 as frmSearch

Initially open form by assigning it to a variable F2

F2 = New frmSearch
F2.MdiParent = F0 'F0 is the MDI parent form.
F2.Show()

This works and I get the form showing.

Somewhere later I decide to close the form using:

F2.close()
F2.Dispose()

If I then reopen the form using the opening code above, I get no errors, but
the form won't appear?

Can anyone help??

Siv
 
S

Supra

try this...

F2.MdiParent = ME
regards

removed this...

F2.close()
F2.Dispose()
and c what happened.
regards,
supra
 
S

Siv

Thanks,
I'll give it a go. The initial thought is that I may not be in the MDI
parent when I do this (most likely in my module) is this what you intended?
Siv
 
H

Herfried K. Wagner [MVP]

* "Siv said:
I have an MDI application with child forms. I want to close a child form
and then reopen a new instance of it, but for some reason I can't reopen it
after initially opening an instance and then closing that instance. I use
the close method and then dispose of the instance variable, but it behaves
as if the dispose hasn't completed. My code is as follows:

In my module I have:

Friend F2 as frmSearch

Initially open form by assigning it to a variable F2

F2 = New frmSearch
F2.MdiParent = F0 'F0 is the MDI parent form.
F2.Show()

This works and I get the form showing.

Somewhere later I decide to close the form using:

F2.close()
F2.Dispose()

If I then reopen the form using the opening code above, I get no errors, but
the form won't appear?

Your code should work. Check the value of 'F0', that's the only place
in your code where the problem can be caused.
 
S

Siv

Herfried,

I declare F0 the same way as I declare the other forms, it is initially asigned to frmMain in the Sub Main as follows:

Public Sub Main()

F0 = New frmMain
Application.Run(F0) ' The main sub will halt execution here until F0 is closed.

call EndApplication 'This routine closes some global stuff and generally tidies up.

End Sub

In the Form_Load of the frmMain (now referred to as F0) I open my start child form:

Dim Resp As Boolean

'Stuff that happens only when the form first loads.
Try
Resp = ShowPage(Common.AppScreens.StartScreen)

'Get User Settings from Registry
If Not GetUserSettings(0) Then
ShowPage(Common.AppScreens.Options)
End If


Catch ex As Exception

Call ProgErrorHandler("frmMain_Load", "frmMain", ex.Message, False)

End Try

My routine "ShowPage" is a module level function that opens the forms. "AppScreens" is an enum for each form, I originally used an array var F() to hold the references to the forms, but found that I couldn't expose the controls as I wanted to without individually declaring each var as a type of the actual form rather than just using the Form object itself. The original code was along the lines of:

Dim F(20) as form

Then in the ShowPage routine below it did a:

F(2) = new frmSearch
F(2).MdiParent = F(0)
F(2).show

This worked fine until I tried to reference cotrols on F(0) the MDI Parent and kept getting errors like "sbp1 is not a member of System.Windows.Form" or something similar (sbp1 being a panel of the StatusBar that I wanted to write some text to). I eventually realised that assigning each form to an array of form was limiting me to only being able to access objects exposed by the form object, not a true instance of the actual frmSearch or any other forms in my app. (I am an old VB6'er and this strict typeing is hard to adjust to). When I twigged (with some help from this forum) why I couldn't modify controls on the F(0) (MDI Parent form) I changed it to the code below. At the declarations of the module I define each form variable as:

Friend F0 as frmMain
Friend F1 as frmStart
Friend F2 as frmSearch etc ..

Then when I want to open one of them I call the ShowPage routine, I first assume the form is already open and try to just open it. If this fails because the F2 F3 F4 etc var is not allocated, the Catch part then opens it.

Public Function ShowPage(ByVal pageToShow As AppScreens, Optional ByVal CreateNewCustomerRecord As Boolean = False) As Boolean

Try
'Try and show the page assumes it already exists
Select Case pageToShow

Case AppScreens.StartScreen
F1.Show()
F1.Activate()

Case AppScreens.SearchScreen
F2.Show()
F2.Activate()

End Select
'If not then create it after exception occurs

Catch ex As Exception
Select Case pageToShow

Case AppScreens.StartScreen
F1 = New frmStart
F1.MdiParent = F0
F1.Show()

Case AppScreens.SearchScreen
F2 = New frmSearch
F2.MdiParent = F0
F2.Show()

End Select

End Try
ShowPage = True
End Function

The problem is however that if the user clicks the inner close box and closes the child form or if I programmatically close it from a button press or whatever, the code is called to do the f2.close() and f2.dispose() but then when I want to open that form again in future the code to open in the "Try" part of the "ShowPsge" just passes through without raising an error, so the Catch never gets called to open it again??

It all seems a bit weird??

Siv
 
S

Siv

I have just run the app again and broken into after manually closing F10
using the child's close box. I then typed the following into the immediate
Window:

? F10.IsDisposed
True
? f10.Name
"frmCust"
? isnothing(f10)
False

This seems a bit strange, how can IsDisposed be true and IsNothing returns
"False"???

It's as if F10 is still lurking around, albeit without showing itself as a
child form and not appearing in the WindowList yet is classed as being
Disposed??

I'm confused??

Siv
 
H

Herfried K. Wagner [MVP]

* "Siv said:
I have just run the app again and broken into after manually closing F10
using the child's close box. I then typed the following into the immediate
Window:

? F10.IsDisposed
True
? f10.Name
"frmCust"
? isnothing(f10)
False

This seems a bit strange, how can IsDisposed be true and IsNothing returns
"False"???

As long as you are holding a reference to the instance of your form, it
cannot be cleaned up by the GC. Disposing a form will not cause the GC
to destroy the object. The object will be destroyed some time after the
last reference to it has been released. Notice that there is no
determined finalization in .NET.
 
S

Siv

Herfried,

Given what you say, how should I re-open an MDI Child form that the user has
closed using its close button. I found if I force the code to create a new
instance, the windows list shows a number of entries with no names which
increase every time I close and re-open the child form??

Is there a better process for doing this as I would rather change my code
and do it right!

Siv
 
S

Siv

Cor,
I did use your sample above and I now check that the form I wish to open
isn't already open but not topmost in the window order. If it isn't found
I just open a new instance and show it.

Thanks for that!

I am still interested to know why the GC process (or VB itself) doesn't get
rid of a form that I have explicitly closed and disposed. As a programmer
I need to know that the system is doing what I tell it. This sort of "I'll
get rid of it when I feel like it" sort of attitude makes me nervous,
particularly when nowadays we should be worried about hackers being able to
scan memory for information!!

I would be interested to know why MS couldn't give us a Dispose() that does
Dispose immediately!?
 
S

Siv

Cor,
Yes I have implemented your routine and the whole thing seems to be a lot
better in that previously it was possible to switch to the start form and
have multiple instances of the same child WIndow open. Your technique is
now at the top of my "ShowPage" function and asertains whether the form is
already open just not at the front and brings it to the front.

If after looking for the form name I don't find it then I open a new
instance using my original code.

So far it works well.

Thanks.

For interest I would be interested to know why the GC process or indeed
VB.NET doesn't remove all references to a disposed form immediately. I
still can't understand why that is desirable. Particularly as it can lead
to the kind of troubles I was having??

Siv
 
C

Cor Ligthert

I would be interested to know why MS couldn't give us a Dispose() that does
Dispose immediately!?
Great to hear that you solved it, however this GC behaviour is one of the
benefits of managed code. Your computer is now not busy any time with
rearrange memory, however does it when there is memory needed or at any time
that it cost no processing power.

Using the dispose in a class is by the way not neccassery when a class
implements Idisposable (what all designer generated forms do) which does the
job for you. Closing the form is more than enough in that case.

(The advised dispose explicitly are with:
bitmaps
connections when there are more than 100 connections possible in one time)
And I am in doubt about showdialog forms.

Cor
 
S

Siv

Thanks Cor,
That is useful to know, I'll just close forms not dispose them in future.
Siv
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top