Table of Contents
Using the EVENTLIB library
by Richard Russell, August 2014
(This article is an extended version of the forum message announcing the EVENTLIB library).
The EVENTLIB library is designed to circumvent some limitations in the built-in ON MOUSE, ON MOVE, ON SYS and ON TIME event-handing mechanism in BBC BASIC for Windows, in particular the fact that event handlers are called asynchronously (which can be useful but can cause complications). It consists of only three procedures as follows:
PROC_eventinit
This initialises the library and sets up a 32-event FIFO queue. Importantly, it can be called multiple times so in a modular program each section of code needing to receive event notifications can call it independently. All the ON… events except ON CLOSE are trapped (ON MOUSE, ON MOVE, ON SYS and ON TIME).
Note that if your program calls FN_setproc (in WINLIB5 and WINLIB5A) to set up a menu-selection or button-click event handler, you should make sure that you call PROC_eventinit afterwards. In general you should call PROC_eventinit after any conventional ON MOUSE, ON MOVE, ON SYS and ON TIME statements, so that they receive 'unregistered' events.
PROC_eventregister(WM_xxxx, PROChandler())
This registers a procedure to be called when the specified event occurs; the event is identified by its @msg% value. PROC_eventregister can be called multiple times with the same event identifier, in which case all the specified handlers will be called sequentially. The handler needs to be defined to receive three parameters as follows:
DEF PROChandler(msg%, wparam%, lparam%)
PROC_eventpoll
This simply polls the queue to see if any events are pending, and if so calls their registered handlers (if any) in the sequence in which the events occurred. If multiple handlers are registered for an event, they are all called (the last one registered is called first). Typically a program will wait in a polling loop such as:
REPEAT PROC_eventpoll WAIT 0 UNTIL FALSE
If you need to be informed that the event queue overflowed, you can register a handler for that by specifying an event ID of zero:
PROC_eventregister(0, PROCoverflow())
Despite the library's simplicity it is quite powerful, and goes a long way to solving the problem of distributing events to multiple handlers (potentially in multiple libraries) and ensuring they are called synchronously. It is designed to use only a small amount of memory.
Here's a simple test program illustrating its use:
WM_MOVE = 3 WM_SIZE = 5 WM_TIMER = 275 WM_LBUTTONDOWN = 513 WM_RBUTTONDOWN = 516 INSTALL @lib$+"EVENTLIB" PROC_eventinit PROC_eventregister(WM_TIMER, PROCtimer()) PROC_eventregister(WM_TIMER, PROCanothertimer()) PROC_eventregister(WM_MOVE, PROCmove()) PROC_eventregister(WM_SIZE, PROCsize()) PROC_eventinit PROC_eventregister(WM_LBUTTONDOWN, PROCmouse()) PROC_eventregister(WM_RBUTTONDOWN, PROCmouse()) PROC_eventregister(0, PROCoverflow()) REPEAT PROC_eventpoll WAIT 0 UNTIL FALSE END DEF PROCtimer(M%, W%, L%) PRINT "Timer fired: "~ M% W% L% ENDPROC DEF PROCanothertimer(M%, W%, L%) PRINT "Timer fired (2) "; ENDPROC DEF PROCmove(M%, W%, L%) PRINT "Window moved: "~ M% W% L% ENDPROC DEF PROCsize(M%, W%, L%) PRINT "Window resized: "~ M% W% L% ENDPROC DEF PROCmouse(M%, W%, L%) PRINT "Mouse clicked: "~ M% W% L% ENDPROC DEF PROCoverflow(M%, W%, L%) PRINT "Event queue overflowed!!" ENDPROC