Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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:

Code Block

  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