| Line 56: | Line 56: | ||
When you instantiate MyClass, you'll have an object that handles window activations. You could use this object for any window event, or, really, any event whose parameter count matched that of the event handler. | When you instantiate MyClass, you'll have an object that handles window activations. You could use this object for any window event, or, really, any event whose parameter count matched that of the event handler. | ||
| − | What if you wanted to handle events that passed different numbers of parameters? Since you can only designate one class method as being the default, you would need to create a way to | + | What if you wanted to handle events that passed different numbers of parameters? Since you can only designate one class method as being the default, you can't just use your class as the event handler. Instead, you would need to create a way to pass the event information to specific methods inside your class. You can do that by creating a separate kind of "proxy" class, which would be responsible for sending information from the event to the appropriate method in your class. |
An example may help clear things up. | An example may help clear things up. | ||
Revision as of 14:42, 2 April 2012
Classes are a common approach for keeping track of and modifying data, but they can also be used as a convenient way to create a stateful process of acting upon some given data.
Class properties can be as simple as:
Public MyPropertyIf your instantiation of your class was an object called MyObject, you could set and retrieve the property with:
MyObject.MyProperty = "hello" ' setting the property MsgBox MyObject.MyProperty ' getting the property
Class methods, which are just subs and functions, are also fairly easy to access:
Public Class Hello() MsgBox "Hello. How are you today?" End Class
The method would be accessed via:
MyObject.Hello()
Handling events inside of a class, on the other hand, is slightly more complicated.
When you connect to an event in Window-Eyes, you typically pass the name of the function, such as:
ConnectEvent Application, "OnHotkey", "MyHotkeyProc"
You can also pass the address of a function, using:
ConnectEvent Application, "OnHotkey", GetRef("MyHotkeyProc")
Window-Eyes handles obtaining the address of your function for you, which is typically why you don't find GetRef used when connecting to events. Another thing Window-Eyes will do for you is obtain the default method of an object, and use that as the event function. For example:
ConnectEvent Application, "OnHotkey", MyObject
Armed with that knowledge, you may begin to see how you can create a class designed to handle events within itself.
Class MyClass Private myEventHanvler Public Default Sub EventHandler(Window) ' Do something with the Window End Sub Public Sub Class_Initialize() myEventHanvler = ConnectEvent(DesktopWindow, "OnChildActivate", Me) End Sub Public Sub Class_Terminate() Disconnect myEventHanvler End Sub End Class
When you instantiate MyClass, you'll have an object that handles window activations. You could use this object for any window event, or, really, any event whose parameter count matched that of the event handler.
What if you wanted to handle events that passed different numbers of parameters? Since you can only designate one class method as being the default, you can't just use your class as the event handler. Instead, you would need to create a way to pass the event information to specific methods inside your class. You can do that by creating a separate kind of "proxy" class, which would be responsible for sending information from the event to the appropriate method in your class.
An example may help clear things up.
Class EventHandlerClass ' Declare private variables Private winEventHandler Private winEventProxy Private speechEventHandler Private speechEventProxy Public Sub Class_Initialize() ' Class constructor ' Each of these "proxy" variables contain an instantiated copy of the ' respective proxy class, followed by a call to that object's Init ' method, passing a copy of this EventHandlerClass, and the name of the ' method used as the event handler. Set winEventProxy = (New SingleParameterProxyClass).Init(Me, "WinProc") Set speechEventProxy = (New DualParameterProxyClass).Init(Me, "SpeechProc") End Sub Public Function Init() ' This method connects to the events we're interested in using the ' appropriate proxy object as the event handler. winEventHandler = ConnectEvent(DesktopWindow, "OnChildActivate", winEventProxy) msaaEventHandler = ConnectEventWithParameter(Speech, "OnSpeak", speechEventProxy, Now()) Set Init = Me End Function Public Sub WinProc(wObj) ' Window event handler End Sub Public Sub Speechproc(originalString, speakTime) ' Speech event handler End Sub Public Sub Dispose() ' This method helps ensure that the events are disconnected correctly. ' It should be called before the instantiated EventHandlerClass is ' disposed of. If winEventHandler <> 0 Then Disconnect winEventHandler End If If speechEventHandler <> 0 Then Disconnect speechEventHandler End If End Sub Public Sub Class_Terminate() ' Class destructor Set winEventProxy = Nothing Set speechEventProxy = Nothing End Sub End Class ' The SingleParameterProxyClass marshals calls to the specified function inside ' the caller. This particular class deals events or procedures that take a ' single argument. Class SingleParameterProxyClass Private caller Private functionName ' VBScript doesn't appear to report the default method correct, ' so we need to make sure that it's defined first. Public Default Sub Main(parm1) Eval "caller." & functionName & "(parm1)" End Sub Public Function Init(c, fn) Set caller = c functionName = fn Set Init = Me End Function End Class ' DualParameterProxyClass - marshals calls to the specified function inside the ' caller. This particular class deals events or procedures that take two ' arguments. Class DualParameterProxyClass Private caller Private functionName ' VBScript doesn't appear to report the default method correct, ' so we need to make sure that it's defined first. Public Default Sub Main(parm1, parm2) Eval "caller." & functionName & "(parm1, parm2)" End Sub Public Function Init(c, fn) Set caller = c functionName = fn Set Init = Me End Function End Class ' You can now instantiate the EventHandlerClass, and begin using it for ' handling the designated events. Dim myEventHandler : Set myEventHandler = (New EventHandlerClass).Init() ' Connect to the ClientInformation shutdown event so that the event handler ' can be cleaned up nicely before exiting. ConnectEvent ClientInformation, "OnShutdown", "OnShutdown" Sub OnShutdown() If Not myEventHandler Is Nothing Then myEventHandler.Dispose() End If End Sub


