Object wrappers and EventSinks

Object wrappers and Event sinks

The problem with the timer class is that while it is, in fact, a class, it doesn’t deal with events  —  one of the main attractions of classes.  Since every Access programmer deals with form and control events, let’s go ahead and start there for the next post.

Object wrappers

One of the more useful things we can do with classes is to wrap a form or control and then sink events from the wrapped object.  This post will demonstrate that technique.

A very simple example of wrapping a control is to take a text box and do something useful with it in a standardized way.  For this example, we will change the background color of a text box as it receives the focus.

Create a form.  Create three text box controls on that form.  When I created them they were named Text0, Text2 and Text4.


Create a database called clsTxtBoxDemo.
Insert a class module and paste the following code
Option Compare Database
Option Explicit’clsCtlTxtDim WithEvents mtxt As TextBox
Const cnEvProc As String = “[Event Procedure]”
Dim lngBackColor As Long    ‘A place to store the original back color so it can be restored when donePrivate Sub Class_Terminate()
MsgBox “unload class for: ” & mtxt.Name
Set mtxt = Nothing
End Sub

Function mInit(ltxt As TextBox)
Set mtxt = ltxt
lngBackColor = mtxt.BackColor   ‘Save the back color of the control
MsgBox “Init the class for: ” & mtxt.Name

‘The text string “[Event Procedure]” placed into any event property
’causes Access to begin raising events for that event property

mtxt.OnGotFocus = cnEvProc ‘Cause Access to start raising this event
mtxt.OnLostFocus = cnEvProc  ‘Cause Access to start raising this event

End Function

Private Sub mtxt_GotFocus()
mtxt.BackColor = vbCyan ‘I hard coded this to make it simple.  You can use some method to pass this in
End Sub

Private Sub mtxt_LostFocus()
mtxt.BackColor = lngBackColor   ‘Restore the back color as we leave
End Sub

Next, insert the following code into the form.  If your text controls are not named Text0, Text 2 and Text4, then rename them to those names for the purposes of this demonstration.


Option Compare Database
Option Explicit
Private fcCtlTxt0 As clsCtlTxt
Private fcCtlTxt2 As clsCtlTxt
Private fcCtlTxt4 As clsCtlTxt
Private Sub Form_Close()
‘Always clean up classes which wrap access controls
‘Failure to do so can cause problems closing the forms that the control is on and so forth
    Set fcCtlTxt0 = Nothing
    Set fcCtlTxt2 = Nothing
    Set fcCtlTxt4 = Nothing
End Sub
Private Sub Form_Open(Cancel As Integer)
   ‘Initialize an instance of the class
    Set fcCtlTxt0 = New clsCtlTxt
   ‘And pass in a pointer to one of the text boxes.
    fcCtlTxt0.mInit Text0
    Set fcCtlTxt2 = New clsCtlTxt
    fcCtlTxt2.mInit Text2
    Set fcCtlTxt4 = New clsCtlTxt
    fcCtlTxt4.mInit Text4
End Sub

Open the form.  One of the controls will have the focus, and that text box will have a light blue background.  Tab through the controls and notice that the control with the focus has a blue background.

As programmers we learned how to create event sinks in the form module, which is a class instance.  Once we did that, we would perform some action when that code ran, such as changing the background color of a text box as it got the focus and setting it back to the original color as it lost the focus.  This is old news.

What we’ve just learned is that we can place all of that code out into a class, and when the control’s event fires, control is passed into the event sink in the class rather than in the form’s class.  Notice that there is no longer any code in the form specific to events for the text boxes.  This is a fundamental lesson about classes:  Objects that can raise events can have their events sunk in a class.

We have created a text box wrapper class (my terminology).  We instantiated the class three times in the form, and passed in pointers to three text boxes.  Inside the class, we saved a pointer to the text box in a variable dimensioned using the key word WithEvents.  The WithEvents keyword tells the compiler that this class expects to sink events for the object stored in that variable — in this case, the text box.

It is important to understand that we cannot make this generic; i.e., we cannot pass in a textbox as object and store that in an object variable Withevents.  The reason is simply that the object data type cannot figure out what events the object can raise and so cannot figure out what events to sink for the object.  If we pass in a control of any type, it must be passed in to mInit into a variable of that specific control type.  A textbox passed in to a textbox variable, a combo passed into a combo variable, etc.

Once we do that, however, and once we store the control into a variable inside of the class dimensioned with the keywordWithEvent, we can then sink any or all of the events that the control can raise.  This class can, if we desire, sink the click event, AfterUpdate, KeyDown, and so forth.  Any or all of the events can be sunk inside of our class.

Leave a Reply

Your email address will not be published. Required fields are marked *