Soft-coded event handlers.

Status
Not open for further replies.

ChrisO

Registered User.
Local time
Tomorrow, 00:39
Joined
Apr 30, 2003
Messages
3,202
Posted the 27th Feb 2009

G’day all.

Over the years, many people have inquired about the event handlers on a Form.

For example, in…

On Click……….[Event Procedure]

What exactly is ‘[Event Procedure]’?
Well, it’s a common old garden variety…string

But it’s a string with a difference; it is re-evaluated each time it is required to run.

In this case the ‘[Event Procedure]’ string instructs the compiler to attempt to find a Subroutine that matches a predefined prototype of the click event to service.
The ‘[Event Procedure]’ click event handler prototype for a command button named cmdMyCommandButton would be…

Private Sub cmdMyCommandButton_Click()

-------------------------------------------------------

And so the fun begins…

Since the ‘[Event Procedure]’ string can instruct the compiler to look for a predefined prototype, then so too can anything else put there.

For example, if ‘[Event Procedure]’ is replaced with…
=HandleClick()

and the HandleClick predefined prototype is defined as…
Code:
Public Function HandleClick()
  
    MsgBox "Here in click handler."
  
End Function
then there will be a direct call to the Function HandleClick() and no normal event handler is required.

-------------------------------------------------------

But let’s pause for a minute or two to ask the all-important question…WHY?

Like almost everything we code there are more ways to do it than we can poke a stick at. Some user interfaces require large numbers of similar controls such as labels or text boxes. Examples of these interfaces are a date picker that would have a grid of 31 controls, the seating layout of a theatre that could have many hundreds of controls or a hotel reservation system that could have thousands of controls. On a normal Form we are limited to around 750 controls but if the interface requires thousands of controls we can move to a continuous Form. (There are limitations.)

The point I’m trying to get at is that it is not reasonable, and could be impossible, to hard code the event handlers for hundreds of controls.

So what is proposed in this post is to be able to set the Event Handler string at runtime. Not only should we be able to point each control event handler ‘call-string’ to a common handler but we should also be able to pass the control’s name. When we can pass the control’s name to a common handler we can process that control as an individual. Apart from the control’s name, we may also like to pass other information to the common handler but that depends on the application.

The important thing to keep in mind is that we are trying to funnel all similar event calls (click, got focus, mouse move, whatever) through a common process. In other words, a common handler, funnel or vena contractor for each event. The benefit of forcing events through the one handler is that all changes/modifications/bug fixes will apply to all control events of this particular type.

-------------------------------------------------------

Anyhow enough waffle from me, so let’s see what it might look like, and in this case use a grid of 8 x 8 textboxes.
(For the sake of simplicity no error handling is included.)

In the module behind the Form: -
Code:
Option Explicit
Option Compare Text
 
 
Private Sub Form_Open(ByRef intCancel As Integer)
    Dim lngIndex       As Long
    Dim strControlName As String
     
    For lngIndex = 1 To 64
        strControlName = "Text" & CStr(lngIndex)
        Me(strControlName).OnDblClick = MakeFunctionCall("HandleOnDblClick", strControlName)
        Me(strControlName).OnMouseMove = MakeFunctionCall("HandleOnMouseMove", strControlName)
    Next lngIndex
 
End Sub
 
 
Private Function HandleOnDblClick(ByVal strThisControlName As String)
 
    MsgBox strThisControlName
 
End Function
 
 
Private Function HandleOnMouseMove(ByVal strThisControlName As String)
 
    MsgBox strThisControlName
 
End Function


And to simplify the construction of the event handler string we can have in a standard module: -
Code:
Option Explicit
Option Compare Text
 
 
Public Function MakeFunctionCall(ByVal strFunctionName As String, _
                            ParamArray vntArgList() As Variant) As String
 
    Dim lngElement  As Long
    Dim strFunction As String
     
    [color=green]' The first argument is NOT optional.
    ' Add Function name and opening bracket.[/color]
    strFunction = "=" & strFunctionName & "("
     
    [color=green]' All the remaining arguments are optional.
    ' Loop through argument range, if passed.[/color]
    For lngElement = LBound(vntArgList) To UBound(vntArgList)
        strFunction = strFunction & Chr$(34) & vntArgList(lngElement) & Chr$(34) & ", "
    Next lngElement
                                  
    [color=green]' Did we receive any arguments?
    ' If so, trim off trailing ", ".[/color]
    If Right$(strFunction, 2) = ", " Then
        strFunction = Left$(strFunction, Len(strFunction) - 2)
    End If
     
    [color=green]' Set return valve and closing bracket.[/color]
    MakeFunctionCall = strFunction & ")"
                                  
End Function


In the above example there are 64 text boxes named Text1 through Text64.
Each text box calls a common function for its ‘On Double Click’ and ‘On Mouse Move’ events.

And so in closing, the event handler property is a common old garden variety string…but a string with a difference.

I hope that raises more questions than it answers…

Regards,
Chris.
 
hmmm.... theoretically you could 'soft-code' error handlers... nearly all my subroutines have the same error handling, except for a few with special cases. would this kind of 'outsourcing' of code make the database faster?

one other question i had was whether softcoding event handling of 64 textboxes (i realise you gave this as an example only, but...) would be useful - after all, wouldn't a developer want to create a separate result from each textbox event? and if they are all funneled to one handler, wouldn't that remove the possibliity of flexibility? i understand you could build into that soft-code some special cases, in which case doesn't that just make the code, that pertains to one control, appear in one place for one part of it, and another place for another part of it?

thanks,
still very green about all things access! ;)
 
>>theoretically you could 'soft-code' error handlers<<

No, because Access (and Windows in general) is an event driven environment so you would need to find an event that triggered a call to a procedure on error. That does not exist in Access. All that exists is a GoTo (Jump) instruction to a label within the same procedure that the error occurred. We can not Call (Jump to Subroutine) within Access based directly on the error event. ***We must Jump to a label and then Jump to Subroutine within the procedure.***



>>would this kind of 'outsourcing' of code make the database faster?<<

I’m not ‘outsourcing’ anything and why would you want to know if it’s faster?
If you want to know if something is faster then you need to time it under your conditions. And there’s no silver bullet when timing code, it requires expert technique.



>>wouldn't a developer want to create a separate result from each textbox event?<<

Of course and the code does just that. Each of the above 64 text boxes calls a common procedure and also passes its own name. By passing its own name each of the 64 text boxes becomes unique within the HandleOnDblClick and HandleOnMouseMove handlers.
But I have already said that in the text of the post, Note: -
>>Not only should we be able to point each control event handler ‘call-string’ to a common handler but we should also be able to pass the control’s name. When we can pass the control’s name to a common handler we can process that control as an individual.<<

Edit to replace: -
***We must Jump to a label and then Jump to Subroutine within the procedure.***
With: -
We must Jump to a label within the procedure and then Jump to Subroutine.
 
Last edited:
thats a nice idea chris

the handle button click thing is what ms put on their standard switchboard - i expand 8 items to 17, and it was a bind naming and annotating all the buttons/labels, but i only had to do it once.

i also tried to come up with a predefined quotation which included 40 product options, and again setting all the names and events was a bind (eventually i found am uch quiicker way to do it)

practically, does this store the click event handler permanently on the forms controls, or is this just a run time thing - to take your example of a theatre booking system, it would take a long while to populate 500 seats wouldnt it? or perhaps not?
 
G’day Gemma.

>>are you storing the click event handler permanently on the forms controls, or is this just a run time thing<<

It’s just a run time thing and obviously needs to be done before the event will be called, usually on Form open.

Incidentally, setting the event handler call in code allows for the switching of even standard events to on/off.
Event handler call to on use [Event Procedure]. Event handler call to off use a zero length string.

By the way, a direct call to user written event handler requires that the handler to be a Function, and not a subroutine, otherwise the handler will be called more than once.

The time to set the handlers is really not a concern but I think it would be less than 2 seconds. If we think about it, 2 seconds isn’t too long to wait for a Form to open.

Regards,
Chris.
 
hmmm.... theoretically you could 'soft-code' error handlers... nearly all my subroutines have the same error handling, except for a few with special cases. would this kind of 'outsourcing' of code make the database faster?

one other question i had was whether softcoding event handling of 64 textboxes (i realise you gave this as an example only, but...) would be useful - after all, wouldn't a developer want to create a separate result from each textbox event? and if they are all funneled to one handler, wouldn't that remove the possibliity of flexibility? i understand you could build into that soft-code some special cases, in which case doesn't that just make the code, that pertains to one control, appear in one place for one part of it, and another place for another part of it?

thanks,
still very green about all things access! ;)


wiklendt,

would this kind of 'outsourcing' of code make the database faster?

I believe that the idea here it to make code Reusable. At least that is what work towards. This really is not "outsourcing". Think more of "centralizing"

See: Reusability

Since the code exist once and not 64 copies of the same thins, the size of the VBA code will be a lot smaller. It is very possible that this will make the database faster because it has a smaller "footprint".

What I consider even more important than speed is the stability of the code and how easy it will be to maintain. I optimize for speed during the testing phase.

On stability: Since you hae a single routine, you only have to test it onces. Once fully test, when you add the same ability to another control, you do not have to go through all the testing al aver again. I find that a lot of "bugs" are introduced by duplicating code over and over and not fully testing the code. Since I find testing to be very neglected/ignored by new/inexperienced programmer, have libraries or resuabel code that has been rigiously test make their work a lot more "error free".

On Maintaining: If your business rules change, you would only have to update a single function, not 64 like in the exam ple. Again you have to test one fucntion, not 64.

If you really like to spend hours testing and/or letting a few bugs get released into production applications, then reusable code is not for you.

still very green about all things access!
Access is object based and event driven. IMHO, the more you can learn about Object Orient programming theory and event drive programming theory will help you with Access.
 
Last edited:
What an interesting philosophical discussion Chris. Way over MY head for sure! ;)
 
Well it needn’t be Adam but it does largely depend on the type of user interface required.

I’ve attached an interface demo of a theater reservation interface which was built for someone else about 4 years ago.

If you have any questions someone should be able to answer them.

Regards,
Chris
 

Attachments

Well it needn’t be Adam but it does largely depend on the type of user interface required.

I’ve attached an interface demo of a theater reservation interface which was built for someone else about 4 years ago.

If you have any questions someone should be able to answer them.

Regards,
Chris

Chris,

Thanks for sharing the example! :)

Great as usual!
 
No problem Boyd, all I had to do was find it.

I guess the demo should give people an idea of the reason for this approach.

Regards,
Chris.
 
Status
Not open for further replies.

Users who are viewing this thread

Back
Top Bottom