[AccessD] Trapping Events In A Class (custom events as well as built-in)

jwcolby jwcolby at colbyconsulting.com
Wed Aug 8 14:37:54 CDT 2012


A.D.

 >Coming back to the original question, it would seem that for such a form, if both sets of events 
(built-in as well as custom) are to be utilized in a wrapper class, setting up of two separate 
pointers would be necessary.

It certainly does appear that way.  If my class is going to sink such events I usually create 
WithEvent pointers in the form wrapper for the control that will be raising the event and then 
handle it in that form wrapper class.  What you are essentially saying is that you want the wrapper 
class to handle the event in the end so why not just sink the event directly in the form wrapper class?

Basically I remove all of that stuff from the form itself and place it in the form wrapper.  Now I 
either pass in the control in my wrapper mInit() method or I reach up into the form and get a 
pointer to those controls.  I always pass a pointer to the form to my wrapper class and store it so 
getting stuff from the form is trivial.

In fact if the control itself has any other functionality it needs to handle I will create a wrapper 
for the control itself as well.  Combos and text boxes are examples of such controls.

As an example in my framework I have a mFindControls method which literally iterates the form's 
controls collection and attempts to create a wrapper for each control found, the type of which is 
called out in a big case statement.  I have prewritten wrapper classes for some but hardly all of 
the various types of controls.  However if down the road I need a new wrapper class for a control 
type not yet covered, I write it and hook it into this case statement.  This is how my framework 
evolved over time.

I use naming conventions to trigger loading variations of control wrappers as needed.  As an example 
I will have a txtPKID text box bound to my PKID (always a long int right!) and when found I plug 
that into a dimensioned variable in the class header (no wrapper at all).  I use that control to 
tell the form wrapper what PKID the form is currently on in case I need to sync a combo box or whatever.

OTOH I have a class which I load for text boxes not matching my naming conventions.  This allows me 
to (for example) look at the data type of the field that the text box is bound to (this is possible 
with DAO) and set a standardized date/time format in the text box's format property if the control 
is bound to a date/time data type.

     For Each ctl In mfrm.Controls   'Find each control in the form's control collection
         With ctl
             On Error Resume Next
             If blnNoRecordset = False Then
                 intCtlDatatype = mrst.Fields(ctl.ControlSource).Type
             End If
On Error GoTo Err_mFindControls
             Select Case .ControlType    'Determine it's type
             Case acTextBox  'Find all text boxes and load class to change backcolor
                 '
                 'There can be two text boxes used for specific purposes.
                 'If they exist they will have specific names.
                 '
                 Select Case .name
                 '
                 'txtPKID is the control bound to the PK of the recordset
                 'and is used for finding records, the recordselector combo etc.
                 '
                 Case "txtPKID"
                     Set mtxtPKID = ctl

                 '
                 'txtParentPKID is bound to the parent form's PK in a subform
                 'and allows the framework to discover when the parent record changed
                 'so that objects in the subform can be requeried when the parent form
                 'changes from record to record
                 '
                 Case "txtFKParentID"
                     Set mtxtFKParentID = ctl
                     mstrFKFldName = mtxtFKParentID.ControlSource
                     On Error Resume Next
                     mlngParentPK = mtxtFKParentID.Value
                 Case Else
                     mcolClasses.Add New dclsCtlTxtBox, .name
                     mcolClasses(.name).mInit Me, mfrm, ctl, intCtlDatatype
                 End Select
             Case acSubform
                 mcolSubForms.Add New dclsCtlSFrm, .name
                 mcolSubForms(.name).mInit Me, mfrm, ctl
             Case acTabCtl   'tab pages are handled in the tab control
                 mcolTabs.Add New dclsCtlTab, .name
                 mcolTabs(.name).mInit Me, mfrm, ctl
             Case acOptionGroup
             Case acCheckBox
             Case acOptionButton
             Case acCommandButton
             Case acToggleButton
             Case acListBox
             Case acComboBox
                 If .name = "cboRecSel" Then
                     Set mdclsCtlCboRecSel = New dclsCtlCboRecSel
                     'mcolClasses.Add New dclsCtlCboRecSel, .Name
                     mdclsCtlCboRecSel.mInit Me, mfrm, ctl, mfrm!txtPKID, mblnUsesADO
                     'mdclsCtlCboRecSel.cGI.pIsADOFrm = mblnUsesADO
                 Else
                     Dim lclsCtlCbo As dclsCtlCbo
                     Set lclsCtlCbo = New dclsCtlCbo
                     lclsCtlCbo.mInit Me, mfrm, ctl, intCtlDatatype
                     lclsCtlCbo.cGI.pIsADOFrm = mblnUsesADO
                     mcolClasses.Add lclsCtlCbo, .name
'                    mcolClasses(.name).mInit Me, mfrm, ctl, intCtlDatatype
                 End If
             Case Else
             End Select


John W. Colby
Colby Consulting

Reality is what refuses to go away
when you do not believe in it

On 8/8/2012 2:44 PM, A.D. Tejpal wrote:
> JC,
>
>      It so happens that hooking of events is not the issue here. In the class module, setting required event properties to "[Event Procedure]" is a fundamental step, without which the event won't fire. That aspect is always taken care of.
>
>      My question refers to a form where a certain event has been raised via RaiseEvent statement. Let us say a filter and / or search action is carried out through a combination of controls like option groups / combo boxes / text boxes / check boxes etc. On successful filter / search, event EvFilterSearch() is raised via RaiseEvent statement in form's module. In the wrapper class, excessive cluttering up can be avoided by simply trapping EvFilterSearch() - rather than setting up WithEvents pointers to individual controls.
>
>      In the wrapper class, if the pointer to such a form (named MyForm) is declared as Access.Form, and an attempt made to hook the events after due instantiation, it will be found that there is no property matching EvFilterSearch event. This event is also found missing from the drop down list at top right of VBA window, which shows all built-in events like Load / Current etc, including those for which explicit hooking by setting event property to "[Event Procedure]" has not been done. Of course, unless hooked, code in stubs for un-hooked events won't execute.
>
>      On the other hand, if the pointer is declared as Form_MyForm (instead of Access.Form), EvFilterSearch event gets displayed in the drop down list at top right of VBA window. Built-in events like Load / Current do not get displayed in this list. Moreover, no explicit hooking for this custom event is needed. In fact you can't do it, as the item is still found missing from properties list of the pointer (interestingly, the properties list does include the built-in events). Code in stub generated for this event gets executed smoothly.
>
>      Coming back to the original question, it would seem that for such a form, if both sets of events (built-in as well as custom) are to be utilized in a wrapper class, setting up of two separate pointers would be necessary.
>
> Best wishes,
> A.D. Tejpal
> ------------




More information about the AccessD mailing list