Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Passing to and back from Dialog

0 views
Skip to first unread message

Webbiz

unread,
Nov 14, 2009, 1:45:27 AM11/14/09
to
When a user double-clicks a text box, a dialog box is to open and the
info from that text box sent over so that the dialog box would have
some initial data to display.

The user than can change that information from within the dialog box.

When the user clicks on the OK button, that information needs to be
returned to the same routine (the textbox doubleclick) that called the
dialog box.

To send data over, I thought to use the .Tag property of the dialog
box.

Dialog.Tag = dMyDateInfo
Dialog.Show 1, Me

The dialog's Activate method deals with the dMyDateInfo sent over.

However, when I wish to send the data back and close the dialog, so as
to test the validity of the info if the user entered a change, the
.Tag cannot be used. This is because the dialog is unloaded.

Now, I know I can create a Global variable and set it to the return
value. But I would like to find ways to minimize the number of Global
variables being added to the project. Once that data is sent back, I
have no other use for such a variable.

What is the suggested way to do this?


Thanks.

Webbiz


Eduardo

unread,
Nov 14, 2009, 2:10:21 AM11/14/09
to
Webbiz escribi�:

> When a user double-clicks a text box, a dialog box is to open and the
> info from that text box sent over so that the dialog box would have
> some initial data to display.
>
> The user than can change that information from within the dialog box.
>
> When the user clicks on the OK button, that information needs to be
> returned to the same routine (the textbox doubleclick) that called the
> dialog box.
>
> To send data over, I thought to use the .Tag property of the dialog
> box.
>
> Dialog.Tag = d
> Dialog.Show 1, Me
>
> The dialog's Activate method deals with the dMyDateInfo sent over.
>
> However, when I wish to send the data back and close the dialog, so as
> to test the validity of the info if the user entered a change, the
> .Tag cannot be used. This is because the dialog is unloaded.
>
> Now, I know I can create a Global variable and set it to the return
> value. But I would like to find ways to minimize the number of Global
> variables being added to the project. Once that data is sent back, I
> have no other use for such a variable.
>
> What is the suggested way to do this?

A Public variable in the Dialog form.

' In the form's code module:
Public pMyDateInfo

' In the calling form
Dialog.Show 1, Me
MyDateInfo = Dialog.pMyDateInfo

Nobody

unread,
Nov 14, 2009, 3:26:19 AM11/14/09
to
This is very common, and some call it "calling form with parameters". You
basically make a Public/Friend function in the form and call it with
parameters. The function shows the form modally, then return the result in
ByRef parameters, or return a UDF containing the result. Example:

' frmPassword

Option Explicit

Private m_sPassword As String

Public Function GetPassword() As String
Debug.Print "GetPassword called " & Time
m_sPassword = ""
Me.Show vbModal
Debug.Print "GetPassword: after calling Me.Show vbModal " & Time
GetPassword = m_sPassword
End Function

Private Sub btnOK_Click()
m_sPassword = txtPassword.Text
Unload Me
End Sub

Private Sub Form_Initialize()
Debug.Print "Form_Initialize " & Time
End Sub

Private Sub Form_Load()
Debug.Print "Form_Load " & Time
End Sub

Private Sub Form_Terminate()
Debug.Print "Form_Terminate " & Time
End Sub

Private Sub Form_Unload(Cancel As Integer)
Debug.Print "Form_Unload " & Time
Set frmPassword = Nothing ' Must be the last line in Form_Unload
End Sub

' How to use:
' ========

Dim sPassword As String

sPassword = frmPassword.GetPassword()
Debug.Print "Password is " & sPassword


Example output:
===========

Form_Initialize 3:19:14 AM
GetPassword called 3:19:14 AM
Form_Load 3:19:14 AM
Form_Unload 3:19:23 AM
GetPassword: after calling Me.Show vbModal 3:19:23 AM
Form_Terminate 3:19:23 AM
Password is abc

There is some debugging code above to show what sequence of events being
called. Note that I added "Set frmPassword = Nothing" at the end of
Form_Unload. This causes a reference to be released so Form_Terminate is
called. Without this line, Form_Terminate is not called and form level
variables will keep their old values, so the next time you load the form,
you will find that form level variables are not initialized to zero and
blank "" as expected. You could initialize them in Form_Initialize or
Form_Load, but this is cumbersome. Another way to ensure that Form_Terminate
is called is using the following:

Dim sPassword As String
Dim f As frmPassword

Set f = New frmPassword
sPassword = f.GetPassword()
Set f = Nothing
Debug.Print "Password is " & sPassword

In this case, you don't need "Set frmPassword = Nothing" line.

Also, make sure that you don't access any of the form's controls or its
properties and methods after the call to "Me.Show vbModal", otherwise the
form is reloaded. You have to store whatever you need in form level
variables, then check them afterward.

Another example:

Public Function ShowMe(ByVal param1 As Long, ByVal param2 As Long, ByRef
Result1 As Long, ByRef Result2 As Long) As Long
Text1.Text = CStr(param1)
Text2.Text = CStr(param2)
Me.Show vbModal
Result1 = m_Result1
Result2 = m_Result2
ShowMe = m_lErrorCode
End Sub

Usage:

Dim ret As Long, Result1 As Long, Result2 As Long

ret = frmDialog.ShowMe(1, 2, Result1, Result2)
Debug.Print "ShowMe returned " & ret
Debug.Print Result1, Result2


Nobody

unread,
Nov 14, 2009, 3:34:08 AM11/14/09
to
"Nobody" <nob...@nobody.com> wrote in message
news:%23emCrQQ...@TK2MSFTNGP05.phx.gbl...
> or return a UDF

Typo, make that UDT.


Larry Serflaten

unread,
Nov 14, 2009, 3:15:31 AM11/14/09
to

"Webbiz" <nos...@forme.thanks.com> wrote

> When a user double-clicks a text box, a dialog box is to open and the
> info from that text box sent over so that the dialog box would have
> some initial data to display.
< ... >

> Now, I know I can create a Global variable and set it to the return
> value. But I would like to find ways to minimize the number of Global
> variables being added to the project. Once that data is sent back, I
> have no other use for such a variable.
>
> What is the suggested way to do this?

To keep things encapsulated you wouldn't want to expose temporary variables
to the outside. One way to get data back from a dialog form is to add a
public function to the form and call that from your main form. You can assign
the return value right where it needs to go, without any intermediary storage,
much like:

Text1.Text = Dialog.TextInput(Text1.Text)

The TextInput function in the dialog form accepts the passed in string
and puts that in the textbox the user will use to edit the text. When it closes
the function returns the value the user edited which goes right into the
textbox on the main form. (vbModal waits for the form to close)

For a demo try out the code below. You would want to use a separate
form for the dialog, whereas I re-used the same Form1 just to give you
the look and feel. On a new form add 2 textboxes and 2 command
buttons and paste in the code below. Try it out, and use as you see fit!

LFS

Option Explicit
Private Enum FormType
Main = 1
Dialog = 2
End Enum

Private Code As FormType
Private Reply As String

Public Function TextInput(Caption As String, Text As String) As String
' Save text for return value
Reply = Text
' Store in edit box
Text1.Text = Text
Text1.SelStart = 0
Text1.SelLength = Len(Text)
PSet (120, 45), Point(120, 15)
Print "Enter " & Caption
' Show form, return reply
Me.Show vbModal
TextInput = Reply
End Function

Private Sub Command1_Click()
Dim Dia As New Form1
Select Case Code
Case Main
' Main form calls the dialog's function
Text1.Text = Dia.TextInput("First Name", Text1.Text)
Case Dialog
' Dialog OK button
Reply = Text1.Text
Unload Me
End Select
End Sub

Private Sub Command2_Click()
Dim Dia As New Form1
Select Case Code
Case Main
' Main form calls the dialog's function
Text2.Text = Dia.TextInput("Last Name", Text2.Text)
Case Dialog
' Dialog Cancel button
Unload Me
End Select
End Sub

Private Sub Form_Activate()
Text1.SetFocus
End Sub

Private Sub Form_Load()
Code = Forms.Count
AutoRedraw = True
Select Case Code
Case Main
Caption = "MAIN"
Move Left, Top, 5000, 2000
Text1.Move 90, 270, 4200, 240
Text2.Move 90, 810, 4200, 240
Text1.Text = ""
Text2.Text = ""
Command1.Move 4325, 270, 300, 240
Command1.Caption = "..."
Command2.Move 4325, 810, 300, 240
Command2.Caption = "..."
PSet (120, 45), Point(120, 15)
Print "First Name"
PSet (120, 600), Point(120, 715)
Print "Last Name"
Case Dialog
Caption = "DIALOG"
Move (Screen.Width - 3000) * 0.5, (Screen.Height - 1500) * 0.4, 3000, 1500
Text1.Move 90, 270, 2700, 240
Text2.Visible = False
Command1.Move 450, 690, 690, 300
Command2.Move 1800, 690, 690, 300
Command1.Caption = "OK"
Command2.Caption = "Cancel"
End Select
End Sub

Private Sub Text1_DblClick()
If Code = Main Then
Dim Dia As New Form1
Text1.Text = Dia.TextInput("First Name", Text1.Text)
End If
End Sub

Private Sub Text2_DblClick()
If Code = Main Then
Dim Dia As New Form1
Text2.Text = Dia.TextInput("Last Name", Text2.Text)
End If
End Sub

Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer)
' Return on Enter keypress
If Code = Dialog Then
If KeyCode = vbKeyReturn Then
Reply = Text1.Text
KeyCode = 0
Unload Me
End If
End If
End Sub


Eduardo

unread,
Nov 14, 2009, 8:56:17 AM11/14/09
to
Eduardo escribi�:

Another option is to Hide the Dialog form instead of unloading it.

'In the Dialog's form Unload event:

Private Sub Form_Unload(Cancel As Integer)

Cancel = 1
Me.Hide
End Sub

' In the calling form:

Dialog.Tag = dMyDateInfo
Dialog.Show 1, Me
MyDateInfo = Dialog.Tag
Unload Dialog
Set Dialog = Nothing ' recommended, to clear variables

Eduardo

unread,
Nov 14, 2009, 9:12:57 AM11/14/09
to
PS: you don't need to use the form's Tag property as intermediary stage
to set the default value, you can directly use the controls properties.

Suppose you use that in a textbox named txtDateInfo:

Dialog.txtDateInfo.Text = dMyDateInfo
Dialog.Show 1, Me
MyDateInfo = CDate(Dialog.txtDateInfo.Text)


Unload Dialog
Set Dialog = Nothing ' recommended, to clear variables

(Add validation and formatting as required.)

MikeD

unread,
Nov 14, 2009, 9:44:10 PM11/14/09
to

"Webbiz" <nos...@forme.thanks.com> wrote in message
news:c3ksf51ni74289qii...@4ax.com...

There really should be no need for a global variable at all.

I'd say the dialog box form should validate the data prior to unloading.
That way, you don't even unload it until the data's been validated.

But there are other ways to approach this. For example, instead of
unloading the dialog box, hide it. That way you can make it visible again if
the calling procedure (the proc that shows the dialog) has to do the
validation and the validation check fails. Unload the form AFTER the
validation check succeeds.

Another option would be to create a Public property in the dialog box form.
You can unload the form and still access that property without causing the
form to reload. Only a form's intrinsic properties cause the form to reload
when referenced. Properties you add don't cause the form to reload. They
are cleared by setting the form's object variable to Nothing (or writing a
method to clear or explicitly setting the property to a default value).

A tip. Don't use "magic numbers". In your code in which you show the
dialog, instead of using

Dialog.Show 1, Me

you should have:

Dialog.Show vbModal, Me

Use the intrinsic constants that VB provides. It makes your code MUCH more
concise and therefore easier to read and understand and maintain.

--
Mike

deactivated

unread,
Nov 15, 2009, 3:25:47 PM11/15/09
to
On Sat, 14 Nov 2009 00:45:27 -0600, Webbiz <nos...@forme.thanks.com>
wrote:

>When a user double-clicks a text box, a dialog box is to open and the
>info from that text box sent over so that the dialog box would have
>some initial data to display.

>What is the suggested way to do this?
>
>
>Thanks.
>
>Webbiz
I use the following structure in my dialog calls and it always works.

The called dialog form has a public flag "Cancelled" that is set to
True when clicking the Cancel button or the X control box, and set to
False if the OK button is clicked.

It also has an Init public function (help checking error in set up
with retunr error code...) through which default values are passed.

In the calling form, I put the following code ( in some button_click
event, for example)

Load frmDialog
frmDialog.Init "Default string"
frmDialog.Show vbModal ' this is important
' then wait for user to finish wiht it.
If not frmDialog.Cancelled then
' get the data and place it where it should be
txtTextBox.Text = frmDialog.getNewValue
End If
' finally...
Unload frmDialog
Set frmDailog = Nothing ' this prevent "resources leak"

Webbiz

unread,
Nov 17, 2009, 6:02:23 PM11/17/09
to


Eduardo-

Thanks. But sending the data isn't the problem.

The problem is getting data back without resorting to creating a
global variable.

When the dialog box has received the info and displays, the user than
can make changes to it. These changes then need to be returned to the
routine that called the dialog box to begin with.

Unfortunately, if you had that info stored in a variable that it's
scope is the dialog box itself, it goes away when the dialog box
closes.

I know I can create a Global variable outside the scope of the dialog
box to receive the data back. Thing is, I was curious as if there was
as way to 'pass it back', much like a function would pass back, when
the dialog box was being closed.

The next line in the routine that calls the dialog box will not run
until the dialog is closed, because of how I'm showing the dialog box
via Dialog.Show 1, Me. So I won't be able to just grab that info from
the Dialog box from the calling routine while it is still open.

:)

Webbiz


Webbiz

unread,
Nov 17, 2009, 6:27:30 PM11/17/09
to


Sweet.

Thanks Larry.

:-)
Webbiz

Webbiz

unread,
Nov 17, 2009, 6:36:24 PM11/17/09
to
On Sat, 14 Nov 2009 03:34:08 -0500, "Nobody" <nob...@nobody.com>
wrote:

Hello Nobody (this sounds like someone talking to themselves :)

Thanks for your explanation and example code. Learned a bunch.

Especially this...

"Without this line, Form_Terminate is not called and form level

variables will keep their old values.."

I thought that once the form was unloaded, all variables within would
be lost. This is interesting.

Thanks again.

Webbiz

Webbiz

unread,
Nov 17, 2009, 6:49:10 PM11/17/09
to
Hi MikeD

Comments strewn within.


On Sat, 14 Nov 2009 21:44:10 -0500, "MikeD" <nob...@nowhere.edu>
wrote:

>
>

>There really should be no need for a global variable at all.
>
>I'd say the dialog box form should validate the data prior to unloading.
>That way, you don't even unload it until the data's been validated.

Can certainly do this. Send the data back while still loaded.

>
>But there are other ways to approach this. For example, instead of
>unloading the dialog box, hide it. That way you can make it visible again if
>the calling procedure (the proc that shows the dialog) has to do the
>validation and the validation check fails. Unload the form AFTER the
>validation check succeeds.

If the dialog is vbModal, the calling proc won't be doing anything
until the dialog is unloaded, right?

>
>Another option would be to create a Public property in the dialog box form.
>You can unload the form and still access that property without causing the
>form to reload.

Now this was the part I did not think about until Nobody mentioned it.
In my mind, I'm looking at the Dialog (Form) like a procedure, that
once it is exited all the variables within its scope go bye bye.

However, in reality, now that I think of it, a Dialog or Form is much
like a Module, except it has a visual side to it. So if the Form has a
Global variable, it should be seen by all procedures in the app much
like a Global variable in a Module or Class.

>Only a form's intrinsic properties cause the form to reload
>when referenced. Properties you add don't cause the form to reload. They
>are cleared by setting the form's object variable to Nothing (or writing a
>method to clear or explicitly setting the property to a default value).
>
>A tip. Don't use "magic numbers". In your code in which you show the
>dialog, instead of using
>
>Dialog.Show 1, Me
>
>you should have:
>
>Dialog.Show vbModal, Me
>
>Use the intrinsic constants that VB provides. It makes your code MUCH more
>concise and therefore easier to read and understand and maintain.

Thanks for the tip. I've still to get familiarized with all the
available constants.

Thanks.

Webbiz

Webbiz

unread,
Nov 17, 2009, 6:51:09 PM11/17/09
to
Thanks. Nice suggestion. :)

Webbiz

Eduardo

unread,
Nov 17, 2009, 7:12:07 PM11/17/09
to
Webbiz escribi�:

> Eduardo-
>
> Thanks. But sending the data isn't the problem.
>
> The problem is getting data back without resorting to creating a
> global variable.
>
> When the dialog box has received the info and displays, the user than
> can make changes to it. These changes then need to be returned to the
> routine that called the dialog box to begin with.
>
> Unfortunately, if you had that info stored in a variable that it's
> scope is the dialog box itself, it goes away when the dialog box
> closes.
>
> I know I can create a Global variable outside the scope of the dialog
> box to receive the data back. Thing is, I was curious as if there was
> as way to 'pass it back', much like a function would pass back, when
> the dialog box was being closed.
>
> The next line in the routine that calls the dialog box will not run
> until the dialog is closed, because of how I'm showing the dialog box
> via Dialog.Show 1, Me. So I won't be able to just grab that info from
> the Dialog box from the calling routine while it is still open.

OK, that's why I suggested this (to Hide the Dialog instead of unloading
it):

'In the Dialog's form Unload event:

Private Sub Form_Unload(Cancel As Integer)
Cancel = 1
Me.Hide
End Sub


' And in the calling form:

deactivated

unread,
Nov 17, 2009, 9:19:48 PM11/17/09
to
On Tue, 17 Nov 2009 17:51:09 -0600, Webbiz <nos...@forme.thanks.com>
wrote:

Forgot this detail:

The called dialog must be hidden when either OK or Cancel / X box is
clicked.

Webbiz

unread,
Nov 17, 2009, 9:48:28 PM11/17/09
to

What is happening here? Isn't the Form_Unload event triggered by the
Form 'unloading'? Yet, it actually does not unload afterall?

Is this because of Me.Hide? Since this is one of those built-in procs,
it reloads it perhaps? And if so, it reloads it without the vbModal
setting, allowing the calling proc to continue?

Webbiz

Eduardo

unread,
Nov 17, 2009, 10:16:16 PM11/17/09
to
>> 'In the Dialog's form Unload event:
>>
>> Private Sub Form_Unload(Cancel As Integer)
>> Cancel = 1
>> Me.Hide
>> End Sub
>>
>>
>> ' And in the calling form:
>>
>> Dialog.txtDateInfo.Text = dMyDateInfo
>> Dialog.Show 1, Me
>> MyDateInfo = CDate(Dialog.txtDateInfo.Text)
>> Unload Dialog
>> Set Dialog = Nothing ' recommended, to clear variables
>
>
>
> What is happening here? Isn't the Form_Unload event triggered by the
> Form 'unloading'? Yet, it actually does not unload afterall?
>
> Is this because of Me.Hide? Since this is one of those built-in procs,
> it reloads it perhaps? And if so, it reloads it without the vbModal
> setting, allowing the calling proc to continue?
>
> Webbiz

No, The event fires before unloading, so at that time you have the
chance to cancel the unloading.

The 'Cancel = 1' is what cancels the unload.
The 'Me.Hide' is there to hide to form, otherwise nothing would happen
and the form would remain shown.

Larry Serflaten

unread,
Nov 18, 2009, 8:13:36 AM11/18/09
to

"Webbiz" <nos...@forme.thanks.com> wrote


> >Private Sub Form_Unload(Cancel As Integer)
> > Cancel = 1
> > Me.Hide
> >End Sub
>
>

> What is happening here? Isn't the Form_Unload event triggered by the
> Form 'unloading'? Yet, it actually does not unload afterall?
>
> Is this because of Me.Hide? Since this is one of those built-in procs,
> it reloads it perhaps? And if so, it reloads it without the vbModal
> setting, allowing the calling proc to continue?

Yes. When you close the dialog form, it doesn't unload, it will instead
cancel the unload process and simply hide, actually remaining in memory.

When you then go to close the main form, (close the app) the Dialog
form's Unload event will be triggered again, and be again canceled.

That will in effect cancel the unload process for the main form, so you
would never be able to close the application!!!

Sneaky!
LFS

Eduardo

unread,
Nov 18, 2009, 10:57:44 AM11/18/09
to
Eduardo escribi�:

Reading Larry's comment I realize that I forgot something:

Put a flag to allow the unload at the line 'Unload Dialog'.

I usually use a Public variable at form's module level, but you could
also use the Tag property.

For example:

'In the Dialog's form Unload event:

Private Sub Form_Unload(Cancel As Integer)

If Me.Tag <> "1" Then
Cancel = 1
Me.Hide
End If
End Sub

' And in the calling form:

Dialog.txtDateInfo.Text = dMyDateInfo
Dialog.Show 1, Me
MyDateInfo = CDate(Dialog.txtDateInfo.Text)

Dialog.Tag = "1"


Unload Dialog
Set Dialog = Nothing ' recommended, to clear variables

Or

'In the Dialog's form Unload event:

Public pAllowUnload as Boolean

Private Sub Form_Unload(Cancel As Integer)

If Not pAllowUnload Then
Cancel = 1
Me.Hide
End If
End Sub

' And in the calling form:

Dialog.txtDateInfo.Text = dMyDateInfo
Dialog.Show 1, Me
MyDateInfo = CDate(Dialog.txtDateInfo.Text)

Dialog.pAllowUnload = True
Unload Dialog
Set Dialog = Nothing ' required now, or set Dialog.pAllowUnload
' to False before showing the dialog

Eduardo

unread,
Nov 18, 2009, 11:11:34 AM11/18/09
to
Or just use the Query_Unload instead of the Unload event and check the
UnloadMode parameter to see if the user closed the form or it's being
unloaded from code.

There are lot of ways of doing this. Some more sophisticated, some simpler.

Some suggestions other made here are somehow more proffesional but
require a couple more lines of code.
Do what you prefer.

In cases likes this, I sometimes wrote functions (as other suggested)
and sometimes I did something like I said here.

Ralph

unread,
Nov 18, 2009, 11:51:01 AM11/18/09
to

"Webbiz" <nos...@forme.thanks.com> wrote in message
news:c3ksf51ni74289qii...@4ax.com...
> When a user double-clicks a text box, a dialog box is to open and the
> info from that text box sent over so that the dialog box would have
> some initial data to display.
>
> The user than can change that information from within the dialog box.
>
> When the user clicks on the OK button, that information needs to be
> returned to the same routine (the textbox doubleclick) that called the
> dialog box.
>
> To send data over, I thought to use the .Tag property of the dialog
> box.
>
> Dialog.Tag = dMyDateInfo
> Dialog.Show 1, Me
>
> The dialog's Activate method deals with the dMyDateInfo sent over.
>
> However, when I wish to send the data back and close the dialog, so as
> to test the validity of the info if the user entered a change, the
> .Tag cannot be used. This is because the dialog is unloaded.
>

Just to add to the pile (or to the confusion): since you used the phrase
"test the validity of the info", you might consider moving your business
rules to an object, and let that object manage the rules and any other data
collection mechanism (eg, a dialog) that might be necessary. The object
could communicate with any Form using Events. (as well as the dialog with
its business wrapper.)

-ralph


Henning

unread,
Nov 18, 2009, 12:24:07 PM11/18/09
to

"Webbiz" <nos...@forme.thanks.com> skrev i meddelandet
news:c3ksf51ni74289qii...@4ax.com...

All ways of returning a value, to me seems a lot of overhead to avoid a
global variable ;)

I, for one, even use global variables, or global UDT's, to reduce the need
to pass multiple values to/from routines.

/Henning


Webbiz

unread,
Nov 18, 2009, 5:08:06 PM11/18/09
to


Several of my projects go back many years, as I was writting them at
the same time learning the A B C's of VB (as I continue to do).

What I find in these, as I continue to play around with them, is that
they are filled to the hilt with Global/Public (module level)
variables. I used them for anything and everything!

After awhile, I may delete code that contained them and not realize I
need to clean up the unused variables.

It just seems cleaner to me to use as many variables that go out of
scope when done with the routine than to have a bunch of them that
never go out of scope.

This is why my questions lean toward these types of solutions, so that
it sort of, to a point, cleans up after itself.

But I hear ya. :)

Webbiz

Dave O.

unread,
Nov 19, 2009, 5:06:21 AM11/19/09
to

"Eduardo" <m...@mm.com> wrote in message news:he15hr$1s3$1...@aioe.org...

> Put a flag to allow the unload at the line 'Unload Dialog'.
>
> I usually use a Public variable at form's module level, but you could also
> use the Tag property.

So what you are saying is for him to avoid using a public variable to return
data from the dialog, he should have a different public variable to control
unloading the same dialog.

Hmm, there seems to be logical inconsistency here. If he is going to have a
public or global variable he might just as well skip all the clever stuff
and use it to return data from the dialog. Equally well he could (rather
tackily) use some otherwise unused tag.

I've never understood the hatred towards judicious use of global/public
variables after all there are stacks of hidden ones in every program such as
every property of every control.

Regards
Dave O.


Dee Earley

unread,
Nov 19, 2009, 8:40:30 AM11/19/09
to
On 18/11/2009 00:12, Eduardo wrote:
>> The next line in the routine that calls the dialog box will not run
>> until the dialog is closed, because of how I'm showing the dialog box
>> via Dialog.Show 1, Me. So I won't be able to just grab that info from
>> the Dialog box from the calling routine while it is still open.
>
> OK, that's why I suggested this (to Hide the Dialog instead of unloading
> it):

You can still access form variable data after it is unloaded.
It will only be "cleared" when you set the reference to nothing.

Think of forms as extended classes and the form can be instantiated but
not loaded. Even after unloading, the class still exists until you
release/terminate it.

The only exception is that accessing form properties that access the UI
causes it to be loaded, after which, you have to unload it before you
can release it again.

--
Dee Earley (dee.e...@icode.co.uk)
i-Catcher Development Team

iCode Systems

Eduardo

unread,
Nov 19, 2009, 8:50:56 AM11/19/09
to
Dave O. escribi�:

> "Eduardo" <m...@mm.com> wrote in message news:he15hr$1s3$1...@aioe.org...
>
>> Put a flag to allow the unload at the line 'Unload Dialog'.
>>
>> I usually use a Public variable at form's module level, but you could also
>> use the Tag property.
>
> So what you are saying is for him to avoid using a public variable to return
> data from the dialog,

No, I didn't say that.
In fact, that was my first suggestion in the thread.

> he should have a different public variable to control
> unloading the same dialog.

They are two ways of doing the same thing (two ways with public module
variables).

>
> Hmm, there seems to be logical inconsistency here. If he is going to have a
> public or global variable he might just as well skip all the clever stuff
> and use it to return data from the dialog. Equally well he could (rather
> tackily) use some otherwise unused tag.

There are perhaps thousands of ways of doing this.

>
> I've never understood the hatred towards judicious use of global/public
> variables after all there are stacks of hidden ones in every program such as
> every property of every control.

They are also in the options pool. But it's what he didn't want.
They are not my choice on cases like this either.

The problem could be if you reuse them, you have to remember that they
could have and old value already, or clear them after use.

>
> Regards
> Dave O.

Regards.

Eduardo

unread,
Nov 19, 2009, 8:53:25 AM11/19/09
to
Dee Earley escribi�:

> On 18/11/2009 00:12, Eduardo wrote:
>>> The next line in the routine that calls the dialog box will not run
>>> until the dialog is closed, because of how I'm showing the dialog box
>>> via Dialog.Show 1, Me. So I won't be able to just grab that info from
>>> the Dialog box from the calling routine while it is still open.
>>
>> OK, that's why I suggested this (to Hide the Dialog instead of unloading
>> it):
>
> You can still access form variable data after it is unloaded.
> It will only be "cleared" when you set the reference to nothing.
>
> Think of forms as extended classes and the form can be instantiated but
> not loaded. Even after unloading, the class still exists until you
> release/terminate it.

Yes, I know.

>
> The only exception is that accessing form properties that access the UI
> causes it to be loaded, after which, you have to unload it before you
> can release it again.
>

I suggested to hide the form instead of unload so he could use controls
properties to get the values. It was just an alternative.

Dave O.

unread,
Nov 19, 2009, 9:24:14 AM11/19/09
to

"Eduardo" <m...@mm.com> wrote in message news:he3ig9$orc$1...@aioe.org...

>> I've never understood the hatred towards judicious use of global/public
>> variables after all there are stacks of hidden ones in every program such
>> as every property of every control.
>
> They are also in the options pool. But it's what he didn't want.
> They are not my choice on cases like this either.
>
> The problem could be if you reuse them, you have to remember that they
> could have and old value already, or clear them after use.

Aha, the objection isn't to public variables per se, but the combination of
public variables and sloppy programming. That seems reasonable.
If used carefully a public variable that is reset immediately after and/or
before use and is only used to span a few lines between forms can simplify
this sort of messaging greatly.

Regards
Dave O.


Ralph

unread,
Nov 19, 2009, 11:01:19 AM11/19/09
to

"Dave O." <nob...@nowhere.com> wrote in message
news:upnM5PS...@TK2MSFTNGP04.phx.gbl...

As well as the reasons Eduardo gave, consider that the simple expedient of
using a Global may work well in one scenario, but becomes awkward in
another. For example, communicating with one object instance compared to a
future need to communicate to multiple instances.

The value of avoiding globals is never appreciated until one has to go back
and modify or expand a program that has made extensive or even casual use of
them. This is only a personal observation, so take with a grain of salt, but
over the years I've never applied a solution dependent on Globals that
didn't come back to bite me.

There are some items in any application which are naturally 'global', eg ...
gbVerboseLoggingOn
gbLogPath
gbWarningLevel
etc. But even then, I find placing them in Objects or at the very least as
Properties greatly simplifies the initialization and tracking of this
information.

-ralph


Dave O.

unread,
Nov 19, 2009, 11:13:53 AM11/19/09
to

"Ralph" <nt_cons...@yahoo.com> wrote in message
news:%23Nw6QHT...@TK2MSFTNGP05.phx.gbl...

All very reasonable, that's why I said if one does use them the scope should
be limited to no more than a few lines, otherwise you're correct to say it
may well bite you on the bum should you need to revisit the code a few years
down the line.

Dave O.


Webbiz

unread,
Nov 19, 2009, 3:55:35 PM11/19/09
to
Well, I'm glad I asked this question. All the responses have been
great.

What I really gained from this is the fact that while the form may be
unloaded, it's variables that are Public/Global are still accessible
to the rest of the application. This was something I didn't think
about.

So as long as I load those variables with the data I wish to retrieve
later by the calling routine (or any others), and have not cleared out
those variables, then that is one way to pass info back.

There was also the technique of simply creating a Function within the
called form that also returns information, and allowing that function
to put the form into vbModal mode. Thus, the value will not return
UNTIL the form has served its purposes and is unloaded. That turned
out to be the way I went with this particular task I was trying to
solve.

There is, however, one thing not quite clear in my head. It has been
mentioned that the Public/Global variables will continue to hold the
values stored there after the form has been unloaded, UNLESS the form
is set = Nothing. If the Global/Public variables of a form is much
like those in a Module or Class, why are they cleared when the 'form'
itself is set = Nothing? If this is the case, then it suggests to me
that you have to have an instance of a form object before you can use
the variables, but this is not the case with a module itself. Here I'm
a bit confused.

Webbiz

Ralph

unread,
Nov 19, 2009, 4:15:33 PM11/19/09
to

"Webbiz" <nos...@forme.thanks.com> wrote in message
news:7jbbg55did9omdden...@4ax.com...

>
> There is, however, one thing not quite clear in my head. It has been
> mentioned that the Public/Global variables will continue to hold the
> values stored there after the form has been unloaded, UNLESS the form
> is set = Nothing. If the Global/Public variables of a form is much
> like those in a Module or Class, why are they cleared when the 'form'
> itself is set = Nothing? If this is the case, then it suggests to me
> that you have to have an instance of a form object before you can use
> the variables, but this is not the case with a module itself. Here I'm
> a bit confused.
>

Because Forms are kinda like Classes, but ain't the same thing.

"Life Cycle of Visual Basic Forms"
http://msdn.microsoft.com/en-us/library/aa242139(VS.60).aspx

-ralph


Ralph

unread,
Nov 19, 2009, 4:44:34 PM11/19/09
to

"Webbiz" <nos...@forme.thanks.com> wrote in message
news:7jbbg55did9omdden...@4ax.com...
> If the Global/Public variables of a form is
much
> like those in a Module or Class, why are they cleared when the 'form'
> itself is set = Nothing? If this is the case, then it suggests to me
> that you have to have an instance of a form object before you can use
> the variables, but this is not the case with a module itself. Here I'm
> a bit confused.
>

Perhaps didn't answer question completely. As I'm not sure what you mean by
"module" - Class or Basic?

You always have to have an instance of a Form or Class before you can use
its Global or Private variables. All variables (and function/subs) in .BAS
modules are "pre-instanced" or available since they are loaded into memory
at the start of a program. (The 'Private' attribute for .BAS modules is only
honored at 'Parse/Compile" time.)

Members of a Form or Class can not be accessed unless the Form or Class is
instanced. In fact all "Global/Public" variables in Forms or Classes are
converted to Properties, with a hidden private store, and become a part of
the Form or Class's Public or Default Interface.

So given that - what is confusing about "a module itself"?

-ralph

Larry Serflaten

unread,
Nov 19, 2009, 5:00:15 PM11/19/09
to

"Webbiz" <nos...@forme.thanks.com> wrote

> There is, however, one thing not quite clear in my head. It has been
> mentioned that the Public/Global variables will continue to hold the
> values stored there after the form has been unloaded, UNLESS the form
> is set = Nothing. If the Global/Public variables of a form is much
> like those in a Module or Class, why are they cleared when the 'form'
> itself is set = Nothing? If this is the case, then it suggests to me
> that you have to have an instance of a form object before you can use
> the variables, but this is not the case with a module itself. Here I'm
> a bit confused.


Its all about the 'lifetime' of a form. You have 3 different types of
modules, the standard module, the class module, and the form module.
The class and form are objects and must be created, the standard module
is not.

When you first call something contained in a standard module (a method,
a public variable, etc) the module is loaded into memory and stays loaded
until the app ends (for all practical purposes).

When you create an instance of a class, its module is loaded into memory
and stays in memory all while the reference to the class remains in scope.
You get two events that give you an opportunity to act on these transitions.
Initialize fires when the class is being loaded into memory, and Terminate
fires when the class is being unloaded from memory. Between these two
events, the public variables and methods you add to the code module of
the class are available for use.

When you create an instance of a form, its module is loaded into memory
and stays in memory all while the reference to the form remains in scope.
You get two events that give you an opportunity to act on these transitions.
Initialize fires when the form is being loaded into memory, and Terminate
fires when the form is being unloaded from memory. Between these two
events, the public variables and methods you add to the code module of
the form are available for use.

Note that with respect to memory, a form is exactly like a class.

But a form also has a visual component. When you cause a form to be
visible, its visual component is loaded into memory and stays in memory
until it is unloaded. You get two events that give you an opportunity to act
on these transitions. Load fires when the visual component is being loaded
into memory and Unload fires when the visual component is being
unloaded from memory. There is also the state where the visual component
is loaded, but hidden from view (Hide was called).

If you put debug statements into the different events, you'll find a form
goes through the transitions in this order:

Form_Initialize
Form_Load
Form_QueryUnload
Form_Unload
Form_Terminate

Between Load and Unload, all the controls and properties of the form are
available. Between Initialize and Terminate, all the public variables and
methods you add to the code module are available.

Code executing between Initialize and Load, or between Unload and
Terminate that references a control or property of the form will cause
the visual component to load so that the control or property can be
accessed.

That means care has to be taken to avoid undesired effects. Example:

Unload Me
Me.Caption = "Unloading"

Here, the Unload event fires, but the very next statement accesses a
property of the form, causing the visual component to be reloaded into
memory. In that case the form's code module would also remain in
memory.

Perhaps now you can see why your form's public variables retain their
values after the visual component has been unloaded. That is because
the form's code module is still in memory waiting for the reference to
fall out of scope (eg: Set to Nothing).

Thus, if you want to track when a form is being loaded and unloaded
from memory, put debug statements in its Initialize and Terminate events.
If you want to track when a form's visual component is being loaded
and unloaded from memory, put debug statements in its Load and
Unload events.

HTH
LFS

Eduardo

unread,
Nov 19, 2009, 6:48:30 PM11/19/09
to
Webbiz escribi�:

> There is, however, one thing not quite clear in my head. It has been
> mentioned that the Public/Global variables will continue to hold the
> values stored there after the form has been unloaded, UNLESS the form
> is set = Nothing. If the Global/Public variables of a form is much
> like those in a Module or Class, why are they cleared when the 'form'
> itself is set = Nothing? If this is the case, then it suggests to me
> that you have to have an instance of a form object before you can use
> the variables, but this is not the case with a module itself. Here I'm
> a bit confused.

You always need an instance of something to hold its variables.
The standard modules are loaded (just one instance that doesn't need to
be referenced) when you first access something of the module.

This is how I understand it, perhaps someone else can explain it further.

Eduardo

unread,
Nov 19, 2009, 6:50:44 PM11/19/09
to
Eduardo escribi�:

> This is how I understand it, perhaps someone else can explain it further.

Emmm, I haven't scrolled the window, and I see now that the question had
many responses

Webbiz

unread,
Nov 20, 2009, 12:22:13 AM11/20/09
to


This is a comment found on the above linked page:

---------------------------------------------
Dim frm As New Form1
frm.ANewMethod
Set frm = Nothing ' Form is destroyed.

A form used in this fashion is no better than a class module, so the
vast majority of forms pass on to the next state.
---------------------------------------------

Here it states that a form that has been set to "Nothing" is no better
than a class module. With a class module, the module level variables
that are Public are always available, right?

The section that deals with setting the form to Nothing states that it
completely reclaims the memory and resources (releases it). But would
that mean ridding the module level Global variables it contains, since
you don't have to reference the form (or any module) when using Global
variables, right?

Looking up everything that "Nothing" is suppose to do, it seems to be
all about removing the 'reference' to something. Global variables do
not need object referencing to begin with, no?

The writeup was illuminating though. Thanks.

Webbiz

Webbiz

unread,
Nov 20, 2009, 12:25:09 AM11/20/09
to
On Thu, 19 Nov 2009 15:44:34 -0600, "Ralph"
<nt_cons...@yahoo.com> wrote:


>Perhaps didn't answer question completely. As I'm not sure what you mean by
>"module" - Class or Basic?
>
>You always have to have an instance of a Form or Class before you can use
>its Global or Private variables. All variables (and function/subs) in .BAS
>modules are "pre-instanced" or available since they are loaded into memory
>at the start of a program. (The 'Private' attribute for .BAS modules is only
>honored at 'Parse/Compile" time.)

Now THAT answered my question! I understand now. Form modules and
class modules as opposed to .bas modules.

Thank you. It's much clearer now.

Webbiz

Webbiz

unread,
Nov 20, 2009, 12:34:08 AM11/20/09
to
On Thu, 19 Nov 2009 16:00:15 -0600, "Larry Serflaten"
<serf...@usinternet.com> wrote:

<snip>

>When you create an instance of a class, its module is loaded into memory
>and stays in memory all while the reference to the class remains in scope.
>You get two events that give you an opportunity to act on these transitions.
>Initialize fires when the class is being loaded into memory, and Terminate
>fires when the class is being unloaded from memory. Between these two
>events, the public variables and methods you add to the code module of
>the class are available for use.

<snip>

Larry,

Nice writeup. Appreciate the explanation and it's understood.

:-)
Webbiz

Nobody

unread,
Nov 20, 2009, 2:53:04 AM11/20/09
to
"Webbiz" <nos...@forme.thanks.com> wrote in message
news:l79cg5t1gbip8ts67...@4ax.com...

> Looking up everything that "Nothing" is suppose to do, it seems to be
> all about removing the 'reference' to something. Global variables do
> not need object referencing to begin with, no?

Yes, it decreases reference count by one, and once the reference count
reaches zero, the object is destroyed.

You may also want to check these posts, which covers showing forms using
"Form1" or "frm" declared as New Form1, and when Terminate is called.

http://groups.google.com/group/microsoft.public.vb.general.discussion/msg/53214c5d7cbc46d1

http://groups.google.com/group/microsoft.public.vb.general.discussion/msg/a1abb49991d5d854


0 new messages