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…
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: -
And to simplify the construction of the event handler string we can have in a standard module: -
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.
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
-------------------------------------------------------
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.