What follows is an excerpt from the Book.
When you open a class for editing in REALbasic, something you may see is one or more Event Handlers:
Figure 32: The Event Handlers for a Window
How these Event Handlers appear is this: a class can contain an Event Definition, which is essentially half a method definition: defining an Event defines something like a method that its subclasses have the opportunity to implement. An Event Definition in a class immediately results in all subclasses showing a corresponding Event Handler, which represents that opportunity to act.
Once a class defines an Event, that class can call the event just like a method call, except you put the keyword RaiseEvent in front of it. The most immediate subclass that provides code in its corresponding Event Handler will have that code invoked when the superclass calls the Event.
Note that once you provide an Event Handler in ClassB for an event in its superclass, ClassA, any further subclasses of ClassB won't even show the Event Handler. This is reasonable, since there is no way for the Event Handler in the further subclass to be invoked. However, ClassB is free to provide an Event Definition with the same arguments (and return type, if it's a function) as the original, and to call it in turn, thus effectively propagating the event down the inheritance chain. This is a normal and natural way to use Event Handlers in REALbasic.
A few notes before we look at an example.
The REALbasic documentation implies that Event Handlers are only for use with subclasses of Controls. Not so. You can and should use Event Handlers across any classes you create.
Otherwise unhandled Events issued by controls can also be handled by code in a Window, by placing an instance of the control in the Window, and putting code in the Event Handlers for the control in the Window's code editor. This is a good way of dealing with the specifics of what a particular control instance should do in a particular window.
Also, you may be wondering what happens if a class calls an event handler, but either it has no subclasses, or none of its subclasses provide a handler for the event. The answer is: if the Event is a regular method, nothing happens. If the Event is a function, Nil, 0, False or the empty string is returned. As we will see, you can sometimes rely on this to detect whether a subclass provides a handler.
Event Handler Example
As an example of using Events, we will look at a classic example: creating an EditField subclass that restricts what the user can enter (in this case, it will only let the user enter numbers). We will do this by adding suitable code to the KeyDown Event Handler for an EditField subclass.
Figure 33: Code for the NumEdit.KeyDown EventHandler
This works because of the way the KeyDown event works: it is a Boolean function—if the function returns False (note that this is what happens when the subclass doesn't provide an Event Handler), the keystroke is accepted, but if it returns True, the keystroke is ignored.
Figure 34: Add a new KeyDown Event
And change the original Event Handler so that rather than just return False, we return whatever we get back from the New Event:
Figure 35: The KeyDown Event Handler, now delegating to a similar Event
Note that if there is no subclass, the call to the Event will return False, so this Event Handler will just be returning False in that case. So we can still use an instance of our NumEdit class as before.
Figure 36: The KeyDown Event Handler in the subclass
The new event handler tests what the string—with the new keystroke inserted—would be as a number, and rejects it if it would be over the Maximum property's value.
Note how the NumEdit class had complete control over how further subclasses can extend it. It could, for example, have invented new Events (perhaps it could have AlphaKeyDown and NumKeyDown Events) instead of, or as well as, KeyDown. We will discuss how to design with Events in the next chapter.blog comments powered by Disqus