While reviewing the code for WindowResizerClass (in an attempt to get more agreeable resizing behavior for ClarionTest) I came across a usage of RegisterEvent that I hadn't noticed before:
REGISTEREVENT (EVENT:DoResize, ADDRESS(SELF.TakeResize), ADDRESS(SELF))
The help says this about RegisterEvent:
REGISTER registers an event handler PROCEDURE called internally by the currently active ACCEPT loop of the specified window whenever the specified event occurs. This may be a User-defined event, or any other event. User-defined event numbers can be defined as any integer between 400h and 0FFFh.
Register is a synonym for RegisterEvent - I suggest using the latter as it's more descriptive. Basically this means that RegisterEvent installs a callback procedure for your accept loop, to be called whenever the specified event occurs. You can install event handlers for windows and for individual controls.
The bit I hadn't noticed was the ability to specify a class method as the callback by passing in the address of the method and the address of the class.
Using class methods as callbacks in Clarion is often problematic because internally the first parameter to any method is the class itself. This is why using Omitted(parameternumber) is unwise with class methods that have optional parameters - if the first parameter of a method is omittable, you have to specify Omitted(2) rather than Omitted(1). Just use Omitted(parametername) - it will save you a lot of trouble.
Similarly, you can't use class methods as WinAPI callbacks because of that hidden first parameter.
But RegisterEvent is part of the Clarion runtime, and it's smart enough to handle a method if that's what you throw at it.
Here's a small sample program to demonstrate:
PROGRAM EventQueue queue,type EventTime long end EventHandler class EventQ &EventQueue Construct procedure Destruct procedure TakeEvent procedure,long end MAP END Window WINDOW('Caption'),AT(,,176,262),GRAY,FONT('Microsoft Sans Serif',8),TIMER(100) LIST,AT(3,2,169,257),USE(?LIST1),FROM(EventHandler.EventQ), | FORMAT('20L(2)|M@t4@') END CODE open(window) accept case event() of EVENT:OpenWindow RegisterEvent(event:timer,address(EventHandler.TakeEvent),address(EventHandler)) end end UnRegisterEvent(event:timer,address(EventHandler.TakeEvent),address(EventHandler)) EventHandler.Construct procedure code self.EventQ &= new EventQueue EventHandler.Destruct procedure code free(self.EventQ) dispose(self.EventQ) EventHandler.TakeEvent procedure code self.EventQ.EventTime = clock() add(self.EventQ,-self.EventQ.EventTime) return level:benign