Event collection can take place under either WAIT ... PROC or GETEVENT. EventMan.DoWait() and EventMan.DoGetEvent() are provided as defaults for this.
Event analysis:
---------------
Event analysis involves several steps:
1. Get target window handle (placed in EventMan.TargetWindow)
2. Set object tag (placed in EventMan.ObjectTag)
3. Set event tag (placed in EventMan.EventTag)
EventMan automatically places the target window handle in
EventMan.TargetWindow using EventMan.GetTargetWindow(..)).
EventMan provides a default procedure in EventMan.SetObjectTagProc (EventMan.SetWindowAsObjectTag()) for setting EventMan.ObjectTag. This procedure simply sets EventMan.ObjectTag to StrVal(EventMan.TargetWindow).
Your application can substitute a more sophisticated procedure which might, for instance, set EventMan.ObjectTag to "INVOICE" rather than a window number. EventMan.SetIndexedObjectTag() is provided for this purpose. It looks up your custom ObjectTag from a list of window numbers. With this alternative, your application must maintain the cross referencing information in the dynarrays EventMan.WindowObjectTag[] and EventMan.ObjectTagWindow[]. The advantage to this is that by avoiding the use of window handles for ObjectTags, EventMan.Dictionary[] updates are not required each time a window is loaded or unloaded.
For type handling, EventMan provides EventMan.SetObjectTagAndType() and EventMan.DispatchEventTagToType().
EventMan sets EventMan.EventTag according to some simple rules that are set out in detail below (See EventMan.SetEventTag()).
Event dispatch:
---------------
Finally EventMan dispatches the event. EventMan provides a default dispatcher (EventMan.DispatchEventTag()) in EventMan.DispatchEventTagProc, although your application can substitute its own more sophisticated dispatcher (advanced applications only). The default dispatcher first looks for
if it didn't find the first form. Therefore default behavior can be provided by your application. It EXECPROCs any entry it finds. If it finds no entry, then it simply returns EventMan.DefaultReturnCode, otherwise it returns the returned value of the EXECPROC'd procedure.
With EventMan.DispatchEventTagToType() EventMan additionaly checks to see if there is a hnadler for the type of object targeted, if not for the object itself, before checking for a default handler.
Event handling:
---------------
Event handlers, the procedures that are EXECPROC'd by the event dispatcher, must be provided by your application, and must always return the values 0, 1, or 2, according to the rules provided for WAIT ... PROC commands.
Special support is provided for IDLE event processing, and for MOUSE event processing, as well as populating and de-populating EventMan.Dictionary[].
Look for event packet details in EventMan.EventBag[].
For some ideas on how to use EventMan, see EDEMO.SC.
EventMan.EventBag[] ; as collected by wait or getevent
EventMan.ObjectTagWindow ; For tracking object window handles
EventMan.WindowObjectTag ; For tracking window object tags
EventMan.ObjectTagType ; For tracking object types
EventMan.EventType ; TRIGGER or EventMan.EventBag["Type"]
EventMan.MouseModeButton ; Button pressed with last DOWN, or "NONE"
EventMan.TargetWindow ; set by collectors from EventMan.GetTargetWindow(..)
EventMan.ObjectTag ; string value for EventMan.Dictionary set by
; EventMan.SetWindowAsObjectTag() or
; EventMan.SetObjectTagProc
EventMan.EventTag ; sometimes composite string value for
; EventMan.Dictionary set by EventMan.SetEventTag()
EventMan.ReturnCode ; must be set by DispatchEventTagProc
EventMan.DefaultReturnCode ; return code when handler search fails
EventMan.GetEventProc ; getevent specs for DoGetEvent
EventMan.SetObjectTagProc ; sets EventMan.ObjectTag based on
; Eventman.TargetWindow
EventMan.DispatchEventTagProc ; dispatches event to EventMan.Dictionary
Detailed explanations:
Construction and destruction:
-----------------------------
EventMan.Constructor()
Syntax: EventMan.Constructor()
Returns: Nothing.
Description: Sets global variables, dynarrays and variables as required by EventMan.
Usage: Issue EventMan.Cosntructor() at the beginning of your application.
------
EventMan.Destructor()
Syntax: EventMan.Destructor()
Returns: Nothing.
Description: Removes global variables, dynarrays and variables as required by EventMan.
Usage: Issue EventMan.Destructor() at the end of your application.
The event dictionary and idle proc queue:
-----------------------------------------
EventMan.SetHandlersFrom()
Syntax: EventMan.SetHandlersFrom(HandlerBag)
HandlerBag is a dynarray of the form
HandlerBag[EventTag] = ProcName
where EventTag and ProcName are both strings. ProcName must be an EXECPROCable procedure name which returns 0, 1, or 2 according to the rules of the WAIT ... PROC command.
Returns: Nothing.
Description: EventMan.SetHandlersFrom() provides a convenient way to populate EventMan's event handler dictionary, EventMan.Dictionary[].
Usage: declare a global dynarray for an object in your application or for default behavior for events, and assign procedure names (event handler names) to event tags. If the procedures are associated with an object, then add the dynarray Element
HandlerBag["ObjectTag"] = ObjectTag
In the presence of an "ObjectTag" element for HandlerBag, EventMan.SetHandlersFrom() will convert the dynarray listing to the form
ObjectTag is a string that is used as an internal reference by the idle server mechanism.
IdleProcName is an EXECPROCable procedure name.
Returns: Nothing.
Description: EventMan.RegisterIdleServer() adds a procedure to a queue of procedures to be EXECPROC'd whenever an IDLE event is collected by EventMan. This procedure does not guarantee that the registered procedures will be fired in the order that they are registered.
Usage: If your application can benefit from asysnchronous events, then register procedures that execute those asynchronous events using EventMan.RegisterIdleServer(). The procedures so registered will be EXECPROC'd in sequence. EventMan keeps track of the last idle procedure which has been serviced, and starts at the beginning of the list after the last one has been serviced. To replace an object's procedure, just call EventMan.RegisterIdleServer() a second time with the same ObjectTag and a different IdleProcName.
Like all WAIT procedures, EventMan.CatchTrigger() has three parameters, as follows: EventMan.CatchTrigger(EventMan.TriggerTag, EventMan.EventBag, EventMan.TriggerCycle). EventMan.TriggerTag is a string, EventMan.EventBag is a dynamic array, and EventMan.CycleNumber is a number. See the documenation of the WAIT command in the Paradox manuals for details about these parameters.
Returns: 0, 1, or 2
Description: EventMan.CatchTrigger() is designed to collect, analyse, and dispatch events collected with the WAIT statement.
Usage: Unless there is a very compelling reason not to do so, EventMan.CatchTrigger() should be used with all WAIT PROC statements in your application.
Example:
WAIT WORKSPACE
PROC "EventMan.CatchTrigger" All
ENDWAIT
------
EventMan.DoGetEvent()
Syntax: EventMan.DoGetEvent()
Returns: Nothing.
Description: EventMan.DoGetEvent() is designed as an alalog to WAIT ... PROC "EventMan.CatchTrigger" ... ENDWAIT. It takes the general form:
ReturnCode = 0
While ReturnCode < 2
GetEvent ... To EventBag
<analyze event>
<dispatch event>
If ReturnCode = 0 Then
ExecEvent EventBag
Endif
EndWhile
Therefore event handling procedures that are written for the WAIT form of event handling can be used with the GETEVENT form of event handling as well. The main difference between the WAIT and GETEVENT forms of event handling is that the GETEVENT form does not collect TRIGGERS.
Usage: use EventMan.DoGetEvent() when there are no images on the workspace or when you do not want to collect TRIGGERs.
TriggerTag is a string that must be "EVENT" or a valid TRIGGER name.
EventBag is a dynamic array that must be a valid event packet if TriggerTag is "EVENT".
Returns: 0 or a valid window handle.
Description: Evaluates the current event in relation to the windows on (and above) the desktop, and determines the target window for the event. If there is no window, then EventMan.GetTargetWindow() returns the window handle of the desktop (0). EventMan.GetTargetWindow() assumes ECHO NORMAL.
Usage: EventMan.GetTargetWindow() is used by EventMan to set EventMan.TargetWindow. It is not necessary to use it directly in your applications, although unlike most other procedures of EventMan, it is written as an independent procedure that can be used on its own outside of the context of EventMan.
------
EventMan.SetWindowAsObjectTag()
Syntax: EventMan.SetWindowAsObjectTag()
Returns: Nothing, but sets EventMan.ObjectTag as a side effect.
Description: "EventMan.SetWindowAsObjectTag" is the default for EventMan.SetObjectTagProc. It sets EventMan.ObjectTag to StrVal(EventMan.TargetWindow) if EventMan.TargetWindow is a valid window handle, or to blank if EventMan.TargetWindow is not a valid window handle.
Usage: There is no need to call EventMan.SetWindowAsObjectTag() directly from your applications. It is called automatically by the event collectors EventMan.CatchTrigger() and EventMan.DoGetEvent().
------
EventMan.SetIndexedObjectTag()
Syntax: EventMan.SetIndexedObjectTag()
Returns: Nothing, but sets EventMan.ObjectTag as a side effect.
Description: "EventMan.SetIndexedObjectTag" is an alternative for EventMan.SetObjectTagProc. It sets EventMan.ObjectTag to EventMan.WindowObjectTag[EventMan.TargetWindow] unless EventMan.TargetWindow is not a valid window handle, in which case EventMan.ObjectTag is set to blank.
Usage: Set EventMan.SetObjectTagProc = "EventMan.SetIndexedObjectTag".
There is no need to call EventMan.SetIndexedObjectTag() directly from your applications. It will be called automatically by the event collectors EventMan.CatchTrigger() and EventMan.DoGetEvent(). However your applications will be responsible for maintaining accurate cross reference information in EventMan.ObjectTagWindow[] and Eventman.WindowObjectTag[].
Returns: Nothing, but sets EventMan.EventTag And EventMan.EventType as side effects.
Description: EventMan.SetEventTag() uses EventMan.EventBag[] to create a string naming the current event. This string is intended for use in conjunction with EventMan.ObjectTag to select an event handler from EventMan.Dictionary[] by the event dispatcher. The rules for converting EventMan.EventBag[] information to string form in EventMan.EventTag are as follows:
For a KEY event type: Strval(EventMan.EventBag["Keycode"]
For the IDLE event, EventMan.EventTag is set to "IDLE".
For a TRIGGER event type:
Note that EventMan.CatchTrigger() sets EventMan.EventTag to EventMan.TriggerTag and EventMan.EventType to "TRIGGER" if EventMan.TriggerTag is not "EVENT".
Usage: There is normally no reason to call EventMan.SetEventTag() directly from your application.
Event dispatch:
---------------
EventMan.DispatchEventBag()
Syntax: EventMan.DispatchEventBag() ; used by collectors
Returns: Nothing, although EventMan.ReturnCode is set by its sub-calls as a side effect.
Description: EventMan.DispatchEventBag() is used by the event collectors EventMan.CatchTrigger(), EventMan.DoGetEvent() and EventMan.CompleteMouseSequence() to dispatch events. It requires a valid EventMan.EventBag[] in the environment. It then calls EventMan.SetEventBag(). If EventMan.EventTag is "IDLE" then EventMan.DispatchEventBag() calls EventMan.DoIdleEvent(). If EventMan.EventTag is not "IDLE" or if the call to EventMan.DoIdleEvent() does not EXECPROC and idle event handler, then EventMan.DispatchEventProc EXECPROC's EventMan.DispatchEventTagProc. This is the heart of EventMan.
Usage: There is normally no reason to call EventMan.DispatchEventBag() directly from your application. However advanced applications can set EventMan.EventBag[] independently, and then call EventMan.DispatchEventBag() to push that event through the event dispatch mechanism independent of the event collection mechanism that captures events from Paradox.
Example: (for advanced applications)
EventMan.ObjectTag = "CLIENT"
Dynarray EventMan.EventBag[]
EventMan.EventBag["Type"] = "KEY"
EventMan.EventBag["Keycode"] = Asc("WinClose")
EventMan.DispatchEventBag()
------
EventMan.DispatchEventTag()
Syntax: EventMan.DispatchEventTag()
Returns: Nothing, although EventMan.ReturnCode is set as a side effect.
Description: EventMan.DispatchEventTag() is the default EventMan.DispatchEventTagProc used by EventMan.DispatchEventBag() (see above). EventMan.DispatchEventTag() looks for EventMan.Dictionary[EventMan.ObjectTag + EventMan.EventTag]. If found it EXECPROC's the value and sets EventMan.ReturnCode to Retval. If not found it looks for EventMan.Dictionary[EventMan.EventTag]. If found it EXECPROC's the value and sets EventMan.ReturnCode to Retval. If not found it simply sets EventMan.ReturnCode to EventMan.DefaultReturnCode.
Usage: There is normally no reason to call EventMan.DispatchEventTag() directly from your application. However advanced applications can set EventMan.EventTag independently, and then call EventMan.DispatchEventTag() to push that event through the event dispatch mechanism independent of the event collection mechanism that captures events from Paradox.
Example: (for advanced applications)
EventMan.ObjectTag = "CLIENT"
EventMan.EventTag = "POSTRECORD"
EventMan.DispatchEventTag()
------
EventMan.DoIdleEvent()
Syntax: EventMan.DoIdleEvent()
Returns: True if an idle event has been EXECPROC'd, otherwise False. If true has been returned, then EventMan.ReturnCode has been set to 1 as a side effect.
Description: EXECPROC's procedures registered by EventMan.RegisterIdleServer() (see above) on a rotating basis.
Usage: There is normally no reason to call EventMan.DoIdleEvent() directly from your application. It is automatically called by EventMan.DispatchEventTag().
Utility procs:
--------------
EventMan.DoWait()
Syntax: EventMan.DoWait()
Returns: Nothing.
Description: Provides a simple default shell for EventMan.CatchTrigger(), as follows:
Echo Normal
Wait WorkSpace
Proc "EventMan.CatchTrigger" All
EndWait
Usage: Use this as the default Wait command in your application until the event list to be captured can be refined.
Returns: Nothing, but Sets EventMan.EventBag[] as a side effect.
Description: Provides a simple GETEVENT statement to collect all events to EventMan.EventBag[], as follows:
GetEvent All To EventMan.EventBag
Usage: Acts as the default EventMan.GetEventProc used by EventMan.DoGetEvent(). When your application can refine the events to be collected, then place the refined GETEVENT statement into a procedure and assign that procedure name to EventMan.GetEventProc.
------
EventMan.EnableEvent()
Syntax: EventMan.EnableEvent()
Returns: 0
Description: Simply returns 0.
Usage: Intended for use with EventMan.Dictionary[] to override a default returncode of 1. Since the default EventMan.DefaultReturnCode is 0, it is unlikely that EventMan.EnableEvent would be used. It is included to provide symmetry to EventMan.DisableEvent().
------
EventMan.DisableEvent()
Syntax: EventMan.DisableEvent()
Returns: 1
Description. Simply returns 1.
Usage: Can be used to disable certain events, in conjunction with EventMan.Dictionary[].
Example: The following example prevents the user from shelling out to DOS from an application:
Returns: EventMan.ReturnCode, and also sets EventMan.ReturnCode as a side effect. It always returns a 1 or a 2.
Description: Mouse events are normally modal, beginning with a mouse DOWN event and ending with a mouse UP event. The purpose of EventMan.CompleteMouseSequence() is to ignore all events other than mouse events after a mouse DOWN event has been executed. With respect to subsequent mouse events, it treats them the same as any event collector (EventMan.CatchTrigger() and EventMan.DoGetEvent(), except that it does not set EventMan.TargetTag and EventMan.ObjectTag. Instead is uses the same EventMan.TargetTag and EventMan.ObjectTag that was set with the mouse DOWN event that is presumed to have preceded the call to EventMan.CompleteMosueSequence().
Usage: EventMan.CompleteMouseSequence() is designed to be used in a mouse DOWN handler. It should only be used where it is known that Paradox will not "eat" subsequent mouse events, otherwise it may get "stuck" waiting for EventMan.EventBag["Buttons"] = "NONE".