Events (Delphi)

From RAD Studio
Jump to: navigation, search

Go Up to Classes and Objects Index

This topic describes the following material:

  • Event properties and event handlers
  • Triggering multiple event handlers

About Events

An event links an occurrence in the system with the code that responds to that occurrence. The occurrence triggers the execution of a procedure called an event handler. The event handler performs the tasks that are required in response to the occurrence. Events allow the behavior of a component to be customized at design-time or at run time. To change the behavior of the component, replace the event handler with a custom event handler that will have the desired behavior.

Event Properties and Event Handlers

Components that are written in Delphi use properties to indicate the event handler that will be executed when the event occurs. By convention, the name of an event property begins with "On", and the property is implemented with a field rather than read/write methods. The value stored by the property is a method pointer, pointing to the event handler procedure.

In the following example, the TObservedObject class includes an OnPing event, of type TPingEvent. The FOnPing field is used to store the event handler. The event handler in this example, TListener.Ping, prints 'TListener has been pinged!'.

 program EventDemo;
 
 {$APPTYPE CONSOLE}
 type
   { Define a procedural type }
   TPingEvent = procedure of object;
 
   { The observed object }
   TObservedObject = class
   private
     FPing: TPingEvent;
 
   public
     property OnPing: TPingEvent read FPing write FPing;
 
     { Triggers the event if anything is registered }
     procedure TriggerEvent();
   end;
 
   { The listener }
   TListener = class
     procedure Ping;
   end;
 
 
 procedure TObservedObject.TriggerEvent;
 begin
   { Call the registerd event only if there is a listener }
   if Assigned(FPing) then
     FPing();
 end;
 
 procedure TListener.Ping;
 begin
   Writeln('TListener has been pinged.');
 end;
 
 var
   ObservedObject: TObservedObject;
   Listener: TListener;
 
 begin
   { Create object instances }
   ObservedObject := TObservedObject.Create();
   Listener := TListener.Create();
 
   { Register the event handler }
   ObservedObject.OnPing := Listener.Ping;
 
   { Trigger the event }
   ObservedObject.TriggerEvent();//Should output 'TListener has been pinged'
   Readln;                       // Pause console before closing
 end.

Triggering Multiple Event Handlers

In Delphi, events can be assigned only a single event handler. If multiple event handlers must be executed in response to an event, the event handler assigned to the event must call any other event handlers. In the following code, a subclass of TListener called TListenerSubclass has its own event handler called Ping2. In this example, the Ping2 event handler must explicitly call the TListener.Ping event handler in order to trigger it in response to the OnPing event:

 program EventDemo2;
 
 {$APPTYPE CONSOLE}
 
 type
   { Define a procedural type }
   TPingEvent = procedure of object;
 
   { The observed object }
   TObservedObject = class
   private
     FPing: TPingEvent;
 
   public
     property OnPing: TPingEvent read FPing write FPing;
 
     { Triggers the event if anything is registered }
     procedure TriggerEvent();
   end;
 
   { The listener }
   TListener = class
     procedure Ping;
   end;
 
   { The listener sub-class }
   TListenerSubclass = class(TListener)
     procedure Ping2;
   end;
 
 procedure TObservedObject.TriggerEvent;
 begin
   { Call the registerd event only if there is a listener }
   if Assigned(FPing) then
     FPing();
 end;
 
 procedure TListener.Ping;
 begin
   Writeln('TListener has been pinged.');
 end;
 
 procedure TListenerSubclass.Ping2;
 begin
   { Call the base class ping }
   Self.Ping();
   Writeln('TListenerSubclass has been pinged.');
 end;
 
 var
   ObservedObject: TObservedObject;
   Listener: TListenerSubclass;
 
 begin
   { Create object instances }
   ObservedObject := TObservedObject.Create();
   Listener := TListenerSubclass.Create();
 
   { Register the event handler }
   ObservedObject.OnPing := Listener.Ping2;
 
   { Trigger the event }
   ObservedObject.TriggerEvent();//Should output 'TListener has been pinged'
                              //and then 'TListenerSubclass has been pinged'
   Readln;                    // Pause console before closing
 end.

See Also