[AccessD] Classes and Events: Exposing child classes in clsFrm

jwcolby jwcolby at colbyconsulting.com
Wed Feb 18 04:35:55 CST 2009


It is often useful to expose child classes to parent classes.  clsFrm is a base class which is 
responsible for among other things scanning all of the controls on the form and automatically 
loading a class for each control for which a class is available.  clsFrm will be manipulated from 
the parent form’s class in order to program clsFrm itself and also the clsCtlXXX classes that clsFrm 
loads.  In order to allow the developer to program the various classes, we need to expose the 
control classes.  That will be the subject of this lecture.

Before we get into the code I want to discuss class organization.  I like to organize my classes 
such that I have areas or regions of the class where I know to look for specific parts of the class. 
  Just like any other organizational task, organizing the class makes your programming more 
efficient.  Classes can get quite large, and knowing where in the class to go to look for specific 
pieces simply makes the maintenance of the class easier.


•	The Header.  The top of every class is called the header and I like to place constants first in 
the header, then variables, then Event declarations.
•	Directly underneath the header I like to place the Class_Initialize and Class_Terminate event 
stubs.  For whatever reason, if you create these event stubs late in the process of building a 
class, the editor will place them down at the end of the class.  I simply cut and paste them to the top.
•	Directly underneath Class_Terminate I place mInit()
•	Underneath mInit() I place all properties.  Properties consist of Property Get / Let / Set 
statements, and occasionally functions that I “label” as a property (rare, but there).  I always 
start the property name with p (lower case).  If the property will return a class pointer I start 
the property name with a lower case c.  I start a property name with a lower case col if it returns 
a collection.  I do this simply because I like my properties and methods to group in intellisense 
and I also can simply read the property name and know that it will return a variable, or a class or 
a collection.
•	Underneath the properties I place the object event sinks if any.
•	Underneath the event sinks I like to group private methods of the class, which I prefix with a 
lower case m.
•	Underneath the private methods I like to group the public methods, also prefixed with a lower case m.

These conventions are my own and I do not expect you to adopt them, though you may if you wish.  I 
have just found after years of programming that these conventions help me in my organization.

With that out of the way…

•	Open the demo database.
•	Open clsFrm
•	Add the following code to clsFrm directly underneath mInit():

Property Get cCtlCbo(strCboName As String) As clsCtlCbo
     Set cCtlCbo = mcolCtls(strCboName)
End Property

Property Get cCtlTxt(strCboName As String) As clsCtlTxt
     Set cCtlTxt = mcolCtls(strCboName)
End Property

•	Save the class.

These two properties expose combo and text box classes that are held in mcolCtls.  We pass in the 
text name of the control to the property.  Remember that the control scanner placed the clsCtlXXX 
instances into colCtls keyed on the control name so using the name we can index into the collection 
and grab the pointer to the correct class, and return that class pointer.  Notice that I defined the 
properties to return clsCtlCbo and clsCtlTxt.  Doing so allows the developer to directly use the 
methods and properties of the corresponding class without having to dimension a variable to store 
the class up in the form class.  In other words we can directly program the clsCtlXXX simply by 
calling the correct property, passing in the correct name of a control and then manipulating the 
properties of the returned class.  I will demonstrate that next.

•	Open frmDemoCtls in design view and immediately save as frmDemoCtls2.
•	In the form class delete the existing code and insert the following code:

Public fclsFrm As clsFrm

Private Sub Form_Open(Cancel As Integer)
      Set fclsFrm = New clsFrm
      fclsFrm.mInit Me
      With fclsFrm
	
      End With
End Sub

Notice that we now have a clean form with just fclsFrm to manipulate.  Underneath fclsFrm.mInit we 
have inserted a With block to allow us to directly manipulate fclsFrm.

Inside of the With block type in the following code.  Please do the typing yourself as I want you to 
experience the Intellisense response.

.cCtlCbo("Combo11").

Notice that as soon as you type in the trailing . intellisense presents you with properties of a 
specific instance of clsCtlCbo – the instance for combo11.  Type in the following code:

.cCtlCbo("Combo11").Ctl.

Again notice that as soon as you type in the trailing . intellisense presents you with the 
properties of the wrapped control for that specific clsCtlCbo.  Type in the following code:

.cCtlCbo("Combo11).ctl.Name

You have just asked for the name of the control contained in the clsCtlCbo instance for Combo11. 
Hit debug / compile.  You should get a compile error because you are not doing anything valid with 
the name property that you requested.  Add debug.print in front of this line of code like this:

Debug.Print .cCtlCbo("Combo11").ctl.Name

Now… until you actually run this code you cannot be sure that you will get a correct result, simply 
because you requested stuff for combo11.  If combo11 does not exist you will get a run time error 
when cCtlCbo tries to index into the collection.

Compile / save and open the form.

Walk through the same process using the following code:

Debug.Print .cCtlCbo("Combo11").cCtlLbl.ctl.Name

Notice that you have full intellisense as you type in the code – the properties for cCtlCbo, then 
the properties for cCtlLbl, then the properties for the label control.  We have full intellisense 
because we declared the property as returning the specific class or object.  For example in clsFrm:

Property Get cCtlCbo(strCboName As String) As clsCtlCbo
     Set cCtlCbo = mcolCtls(strCboName)
End Property

Returns a clsCtlCbo, and thus we can use intellisense to browse all of the properties of clsCtlCbo. 
  In the future as we add new control classes to the system, we will come into clsFrm and build a 
new property to expose each additional control wrapper class by its type.  This will ensure easy and 
efficient programming back in the parent form class.

In this lecture we have designed a method of exposing the classes that the scanner in clsFrm created 
and placed into mcolCtls.  We created a property for each type of clsCtlXXX such that the property 
returns that specific class type.  We then built code back in the frmDemo to demonstrate the ease of 
programming that intellisense will provide because we have a property for each class type.  Because 
there are a fixed number of controls provided by Access, there will always be a limited number of 
control wrappers and thus having a system to explicitly expose each class type makes good sense.

-- 
John W. Colby
www.ColbyConsulting.com



More information about the AccessD mailing list