Code Samples, Tips, Tricks and
other Neat Stuff for the VB developer

All Content Copyright © 2000
New Vision Software
All rights reserved

VB Petition

Many of you may not be aware that Microsoft's mainstream support for VB6 officially ended on March 31st, 2005.  Now that this has occurred, it becomes increasingly more likely that future updates to Windows may break existing VB code.  If you are concerned about this and/or are concerned about migration issues associated with bringing existing VB code to the .NET platform, please take a moment to read and sign the petition asking Microsoft to extend there COM based VB product line.  The impetus behind the petition is the desire to give companies and individuals with substantial investments in existing VB code a path forward to the latest development platform without the current requirement for wholesale rewrites of existing code.  Thanks for your support!

Bryan

   

Home

All Sample Projects

Grouped Samples

Common Dialogs

Control Stuff

Date & Timezone

Drawing

Graphics

Text

File Routines

Form Modifications

Icon Routines

Listbox & ComboBox

Menus

Mouse

Subclassing

Text Parsing Routines

UserControl Demos

Specific Samples

Activate Previous

Instance

API & OLE DragDrop

Environment Variables

GUID - UUID

ListView

Message Box

Collections

Thunking

File Split Utility

Save Clipboard Utility

Visual Basic Tips!


 

Raising Events From Objects In A Collection

Without Circular Reference Problems

by Bryan Stafford - New Vision Software

How to go about raising events from the child objects in a collection?  This is a question that has been asked many times in the various on-line forums ever since creating collection classes became possible in Visual Basic.  This feat is actually relatively easy to accomplish, all you have to do is pass a variable, that references the parent collection object, to the child.  The child then calls the parent through this reference whenever it needs to raise an event back to the collection client.  Unfortunately, this creates a circular reference problem.  Circular references are a problem because, until all references to an object are destroyed, the referenced object cannot be destroyed.  When a child of a collection holds a reference to its parent, there must be a method to release this reference and it is up to you, the developer, to call the method or the parent object will never be unloaded.  If you forget even once, you’ve blown it!  This is the stuff that memory leaks are made of.  (See Object References Explained for more info about how object references work)

So, we need a method to allow the child of a collection to hold a reference to its parent without creating circular references.  Surprisingly, this is not as difficult as it sounds.  The method I will describe uses un-referenced pointers obtained using the ObjPtr() function.  The ObjPtr() function resides in a normally hidden part of the VB language but it can be viewed if you open the object browser and select the “Show Hidden Members” option from the right click context menu.  It returns an un-referenced “dumb” pointer to any VB object that you pass to it.  Once a child object has a pointer to its parent, it is a fairly simple process to turn the dumb pointer into a fully referenced VB object.  You simply copy the dumb pointer into the memory location of a variable dimensioned as the desired object type.  (keeping VB from crashing is slightly more complicated but you can see the details in the ResolvePointer function in the frmMDIChild FRM module in the sample project)

Now we know how to get our pointer but since it is un-referenced, there is no guarantee that the desired object will still be there when we try to resolve the pointer.  We handle this situation by creating a means by which the collection object can register itself for the duration of its existence (think of this as referencing the object with no strings attached).  In the initialize event of the collection class, we register its existence and in the terminate event, we clear the registration.  This allows any child object that wishes to access the parent collection to first check to make sure the parent still exists before trying to resolve a pointer.  See the functions in the MValidatePointer BAS module for all of the gritty details of the object registration routines.

We now have all the background information we need to proceed with a step-by-step explanation of the event raising process. 

1.       Declare the collection object “WithEvents” in the client module where it will be used.

2.       In the Initialize event of the collection class, register the object using the registration routine in the MValidatePointer BAS module.

3.       As each child is created and added to the collection, a dumb pointer to the collection object is passed to the child.

4.       When a child object of the collection needs to raise an event, it calls a method on the parent through the dumb pointer which it resolves before making the call.

5.       In the event sub on the parent, the desired event is raised in the collection client.  The collection Key of the object as well as the index can be passed to the client in the event.

That's all there is to it!  You now have the tools you need to create your own control and object arrays with full event support.  Download the fully commented Collection WithEvents sample project to see this method in action!

Download the Collection WithEvents sample project  (8KB)