Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Passing OBJECT variables between forms

Status
Not open for further replies.

Schof

Programmer
Nov 18, 2002
103
CA
I have defined a public object variable in a form:

Public TV As Object

A button opens another form containing a treeview object. The user picks items in the treeview and then closes the form. When the form closes I set the public object variable to be the treeview object in the closing form:

Private Sub Form_Close()
set Forms("XYZ").TV = Me.Treeview
msgbox Forms("XYZ").TV.Nodes.Count
End Sub

The operation appears to work because it correctly tells me the node count. However, once the treeview form is closed the TV object becomes empty. Can anyone explain why this is the case and how I can properly set the TV object so I can use it in the original (ie. "XYZ") form?

I tried creating a public procedure in the original form and calling it from the Form_Close procedure in the treeview form but it gave the same result.

Public Sub setTV(ByVal updatedTV As Object)
Set TV = updatedTV
MsgBox TV.Nodes.Count
End Sub
 
Hi Schof,

Think of it this way, and it should have you to understand how database objects are consumed in the database:

Your friend comes over (the form), and brings his cool camera (TreeView object on the form) for you to use while he's there. When he leaves (form closes), the camera (treeview object) isn't there for you to use anymore, because he's taken it with him. Sure, you can tell him how many pictures (nodes.count) that you've taken while he's there, and store that information so that you can tell someone else, but you can't really use the camera again until he comes back, right?

Now, if you want to be able to use the camera anytime you want, your friend needs to be there right? Same thing with using objects in VB / VBA.

A solution for you would be to not allow the form to close while you need the TreeView control. You can try using a DoCmd.MoveSize ,,0,0 to make the form virtually invisible to the user, but you can still access the TreeView object because the form is still open. In the form that contains the TreeView object, if you were going to use the DoCmd.Movesize method above, you need to place the following line of code into the GotFocus event of the form:

DoCmd.Movesize , , 500,500 ' or whatever size you want you form

otherwise, you'll never see your form again until you close the database and re-load it!

Let me know if I can do aynthing else, or if this cleared up anything for you.

HTH

Greg

Boss quote from an office meeting: We're going to continue to have these meetings until we figure out why no work is getting done ...
 
I like your analogy Greg! How about we introduce the concept of memory cards? Both my friend and I have the same digital cameras but only one memory card. So my buddy takes all these cool pictures and before he leaves gives me the memory card. Considering we have the same camera and the memory card is compatible why can't I look at the pictures?

Can't I create a copy of the TreeView object and use it in another form? I use global variables all the time to pass data between forms. Is the behaviour different when dealing with objects?

I can probably try hiding the TreeView form (instead of closing it) but then I need to figure out how to create and manage multiple instances when I want to call the TreeView form more than once from a single form. Probably another discussion...
 
Schof,

You are correct in stating that the behaviour is different when dealing with objects ... think of your memory card as a global variable, when can be used in multiple places (such as your camera and his), but his camera can only be used by you when he is there.

My question to you is: why would you need to create multiple instances of the TreeView form? It's already loaded - simply modify what you need to on the loaded form, and call the DoCmd.movesize method from the forms GotFocus event. At anytime in your code, if you happen to call the DoCmd.OpenForm method for this form, and the form is already open, it'll just set the focus back to the form.

Of course, in Visual Basic, it would create another instance of the object. But we're using Access, and VBA - different story. :)

HTH

Greg

Boss quote from an office meeting: We're going to continue to have these meetings until we figure out why no work is getting done ...
 
hmmm, thats strange, schof's method works fine for me.

Schof's, how are you opening the treeview form:
a) docmd.openform, or
b) set frm = new form; frm.visisble = true

I only tested using the docmd method.

Cheers,
Dan
 
Dan, I opened the form using method a). It works until the treeview form is closed, in which case the TV object becomes empty. Did you close the treeview form and manage to have the TV object maintain its state? I will probably try method b) on Monday to see if it works. I'll post what I find out.
 
Yes, I did. Below is the code that I used. The first form ("form1") has a button called cmdOpenForm which opens the second form as a dialog form. When form2 closes, it calls a public function in form1 to set the module level object "mvwTest".

Microsoft access seems to perform a deep copy of the object even if you don't explicitly state ByVal. That is, both ByVal and ByRef gave the same result for me - a complete memmory copy.

have I understood your problem correctly? I can't think why its not working for you. Do you have any "on error resume next" statements in the close event of your treeview form?

First Form (form1)
[tt]
Option Compare Database
Private mtvwTest As Object

Private Sub cmdOpenForm_Click()
DoCmd.OpenForm "Form2", acNormal, , , , acDialog
End Sub

Private Sub cmdTest_Click()
Dim strMessage As String

strMessage = "There are " & mtvwTest.Nodes.Count & " nodes and the " & _
"value of the second node is " & mtvwTest.Nodes(2).Text

MsgBox strMessage
End Sub

Public Function SetTreeView(objTree As Object)
Set mtvwTest = objTree
End Function
[/tt]

Second Form (form2) - treeview form
[tt]
Option Compare Database
Private mobjTree As Object

Private Sub Form_Close()
Call Forms("Form1").SetTreeView(mobjTree)
Set mobjTree = Nothing

End Sub

Private Sub Form_Load()
Dim NodeNew As Node

Set mobjTree = New TreeView

Set NodeNew = mobjTree.Nodes.Add(, , "r", "RootName")
Set NodeNew = mobjTree.Nodes.Add("r", tvwChild, "FirstChild", "ChildName")

End Sub
[/tt]
 
Dan:

Your code is fine - but what you are actually doing is create an object on the fly - what Schof needs to do is to be able to maintain a reference to the actual ActiveX control on the form.

I think ... :p

Greg


Boss quote from an office meeting: We're going to continue to have these meetings until we figure out why no work is getting done ...
 
Oh ok, sorry about that...I see the problem now (thanks grtammi)

Change the On_Close event of the second form so that it reads:
[tt]
Private Sub Form_Close()
Call Forms("Form1").SetTreeView(me.myTreeView.Object)
Set mobjTree = Nothing

End Sub
[/tt]
this gives you access the nodes of the treeview, but you wont know which node was selected. So, perhaps your function prototype for form1 could add the treeview's state, e.g.

[tt]
Public Function SetTreeView(objTree As TreeView, SelectedNode as long)
Set mtvwTest = objTree
mlngSelectedNode = SelectedNode
End Function
[/tt]

Or, of course, just make form2 invisible :)

cheers,
Dan
 
I had previously tried creating a function similar to SetTreeView but all of the nodes were unchecked (which is the property I am really interested in). I tried setting the checked property but I guess it is read only because the setting never held.

I found a post (link below) on VBnet regarding Duplicating the Contents of a Treeview. Since this creates the treeview copy from scratch (instead of referencing the actual activeX control) it meets my needs perfectly. Thx for pointing me in the right direction guys!

 
Schof:

That code looks good, but I have one question:

What happens if the data in the source control changes? I'm guessing that you then have to worry about re-writing the global treeview variable to reflect changes, and you'll have to do a check every couple of minutes (even seconds) if your database is running multi-user.

Just 2 more cents for a grand total of 4 ... but since I'm Canadian, that amounts to just under 1 cent US, right? :p

Oh, and on a side note, I came across an interesting quote by Einstein that describes programmers to a T:

"It's kind of fun to do the impossible."

Greg


Boss quote from an office meeting: We're going to continue to have these meetings until we figure out why no work is getting done ...
 
Can't you just create a module and define the public variable in there. That variable will then be available to all forms within your database.
 
Greg, fortunately the data I use to populate the treeview with is pretty static so I don't need to worry about refreshing the global treeview variable. [Aside: Rest assured though that the population is done using metadata instead of being hard-coded.]

I have designed the treeview form such that the treeview will populate itself with either default data or (if it exists) the global variable from the calling form. This will allow the user to either just see which items are selected by default or to change that selection (any number of times).


Mark, I am using the variable to store a list of items selected by the user that some operation(s) are going to be performed on. The list is the same for each form (although that may change in the future) but which items are selected may change depending on the form. Furthermore, it is possible that I have multiple forms open that would each require their own list. That is why the public object variable is being defined at the form level.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top