RAD Studio
ContentsIndex
PreviousUpNext
Creating events
Name 
Description 
An event is a link between an occurrence in the system (such as a user action or a change in focus) and a piece of code that responds to that occurrence. The responding code is an event handler, and is nearly always written by the application developer. Events let application developers customize the behavior of components without having to change the classes themselves. This is known as delegation.
Events for the most common user actions (such as mouse actions) are built into all the standard components, but you can also define new events. To create events in a... more 
An event is a mechanism that links an occurrence to some code. More specifically, an event is a method pointer that points to a method in a specific class instance.
From the application developer's perspective, an event is just a name related to a system occurrence, such as OnClick, to which specific code can be attached. For example, a push button called Button1 has an OnClick method. By default, when you assign a value to the OnClick event, the Form Designer generates an event handler called Button1Click in the form that contains the button and assigns it to OnClick... more 
Closures are used to implement events. A closure is a special pointer type that points to a specific method in a specific class instance. As a component writer, you can treat the closure as a place holder: your code detects that an event occurs, so you call the method (if any) specified by the user for that event.
Closures maintain a hidden pointer to a class instance. When the user assigns a handler to a component's event, the assignment is not just to a method with a particular name, but rather to a specific method of a specific class instance.... more 
Delphi uses method pointers to implement events. A method pointer is a special pointer type that points to a specific method in a specific class instance. As a component writer, you can treat the method pointer as a placeholder: When your code detects that an event occurs, you call the method (if any) specified by the user for that event.
Method pointers work just like any other procedural type, but they maintain a hidden pointer to a class instance. When the application developer assigns a handler to a component's event, the assignment is not just to a method with a... more 
All controls, for example, inherit a dynamic method called Click for handling click events:  
Components use properties to implement their events. Unlike most other properties, events do not use methods to implement their read and write parts. Instead, event properties use a private class field of the same type as the property.
By convention, the field's name is the name of the property preceded by the letter F. For example, the OnClick method's pointer is stored in a field called FOnClick of type TNotifyEvent, and the declaration of the OnClick event property looks like this:  
Because an event is a pointer to an event handler, the type of the event property must be a method-pointer type. Similarly, any code to be used as an event handler must be an appropriately typed method of a class.
All event-handler methods are procedures. To be compatible with an event of a given type, an event-handler method must have the same number and type of parameters, in the same order, passed in the same way.
Delphi defines method types for all its standard events. When you create your own events, you can use an existing type if that is... more 
Although the compiler allows you to declare method-pointer types that are functions, you should never do so for handling events. Because an empty function returns an undefined result, an empty event handler that was a function might not always be valid. For this reason, all your events and their associated event handlers should be procedures.
Although an event handler cannot be a function, you can still get information from the application developer's code using var parameters. When doing this, make sure you assign a valid value to the parameter before calling the handler so you don't require the user's code... more 
Event handlers must have a return type of void. Even though the handler can return only void, you can still get information back from the user's code by passing arguments by reference. When you do this, make sure you assign a valid value to the argument before calling the handler so you do not require the user's code to change the value.
An example of passing arguments by reference to an event handler is the key-pressed event, of type TKeyPressEvent. TKeyPressEvent defines two arguments: one to indicate which object generated the event, and one to indicate which... more 
Because an event is a pointer to an event handler, the type of the event property must be a closure type. Similarly, any code to be used as an event handler must be an appropriately typed method of a class.
To be compatible with an event of a given type, an event-handler method must have the same number and type of parameters, in the same order, passed in the same way.
C++Builder defines closures for all its standard events. When you create your own events, you can use an existing closure if that is appropriate, or define one of your... more 
When creating events, remember that developers using your components may not attach handlers to them. This means that your component should not fail or generate errors simply because there is no handler attached to a particular event. (The mechanics of calling handlers and dealing with events that have no attached handler are explained in Calling the event.)
Events happen almost constantly in a GUI application. Just moving the mouse pointer across a visual component sends numerous mouse-move messages, which the component translates into OnMouseMove events. In most cases, developers do not want to handle the mouse-move events, and this... more 
The controls that come with the component library inherit events for the most common occurrences. These are called the standard events. Although all these events are built into the controls, they are often protected, meaning developers cannot attach handlers to them. When you create a control, you can choose to make events visible to users of your control.
There are three things you need to consider when incorporating the standard events into your controls:  
There are two categories of standard events: those defined for all controls and those defined only for the standard windowed controls. 
The declarations of the standard events in TControl and TWinControl are protected, as are the methods that correspond to them. If you are inheriting from one of these abstract classes and want to make their events accessible at runtime or design time, you need to redeclare the events as either public or published.
Redeclaring a property without specifying its implementation keeps the same implementation methods, but changes the protection level. You can, therefore, take an event that is defined in TControl but not made visible, and surface it by declaring it as public or published. 
If you want to change the way your component responds to a certain kind of event, you might be tempted to write some code and assign it to the event. As an application developer, that is exactly what you would do. But when you are creating a component, you must keep the event available for developers who use the component.
This is the reason for the protected implementation methods associated with each of the standard events. By overriding the implementation method, you can modify the internal event handling; and by calling the inherited method you can maintain the standard handling,... more 
Defining entirely new events is relatively unusual. There are times, however, when a component introduces behavior that is entirely different from that of any other component, so you will need to define an event for it.
There are the issues you will need to consider when defining an event:  
You need to know what triggers the event. For some events, the answer is obvious. For example, a mouse-down event occurs when the user presses the left button on the mouse and Windows sends a WM_LBUTTONDOWN message to the application. Upon receiving that message, a component calls its MouseDown method, which in turn calls any code the user has attached to the OnMouseDown event.
However, some events are less clearly tied to specific external occurrences. For example, a scroll bar has an OnChange event, which is triggered by several kinds of occurrence, including keystrokes, mouse clicks, and changes in other... more 
There are two kinds of occurrence you might need to provide events for: user interactions and state changes. User-interaction events are nearly always triggered by a message from Windows, indicating that the user did something your component may need to respond to. State-change events may also be related to messages from Windows (focus changes or enabling, for example), but they can also occur through changes in properties or other code.
You have total control over the triggering of the events you define. Define the events with care so that developers are able to understand and use them. 
Once you determine when the event occurs, you must define how you want the event handled. This means determining the type of the event handler. In most cases, handlers for events you define yourself are either simple notifications or event-specific types. It is also possible to get information back from the handler. 
Once you have determined the type of your event handler, you are ready to declare the method pointer and the property for the event. Be sure to give the event a meaningful and descriptive name so that users can understand what the event does. Try to be consistent with names of similar properties in other components. 
You should centralize calls to an event. That is, create a virtual method in your component that calls the application's event handler (if it assigns one) and provides any default handling.
Putting all the event calls in one place ensures that someone deriving a new component from yours can customize event handling by overriding a single method, rather than searching through your code for places where you call the event.
There are two other considerations when calling the event:  
You should never create a situation in which an empty event handler causes an error, nor should the proper functioning of your component depend on a particular response from the application's event-handling code. 
For some kinds of events, developers may want to replace the default handling or even suppress all responses. To allow this, you need to pass an argument by reference to the handler and check for a certain value when the handler returns.
This is in keeping with the rule that an empty handler should have the same effect as no handler at all. Because an empty handler will not change the values of arguments passed by reference, the default handling always takes place after calling the empty handler. 
Copyright(C) 2008 CodeGear(TM). All Rights Reserved.
What do you think about this topic? Send feedback!