Understanding the Sender parameter in Delphi Event Handlers

Once upon a time, in the Delphi land there was an Object called the Sender

A women helps a coworker
Tim Klein/Photodisc/Getty Images

Event handlers and the Sender

Take a look at the following event handler for the OnClick event of a button (named "Button1"):
 procedure TForm1.Button1Click(Sender: TObject) ;
The Button1Click method takes a pointer to a TObject called Sender. Every event handler, in Delphi, will have at least a Sender parameter. When the button is clicked, the event handler (Button1Click) for the OnClick event is called.

The parameter "Sender" references the control that was used to call the method.

If you click on the Button1 control, causing the Button1Click method to be called, a reference or pointer to the Button1 object is passed to Button1Click in the parameter called Sender.

Let's Share Some Code

The Sender parameter, when used properly, can give an incredible amount of flexibility in our code. What the Sender parameter does is let us know which component triggered the event. This makes it easy to use the same event handler for two different components.

For example, suppose we want to have a button and a menu item do the same thing. It would be silly to have to write the same event handler twice.

To share an event handler in Delphi, do the following:

  1. Write the event handler for the first object (e.g. button on the SpeedBar)
  2. Select the new object or objects - yes, more than two can share (e.g. MenuItem1)
  3. Go to the Event page on the Object Inspector.
  4. Click the down arrow next to the event to open a list of previously written event handlers. (Delphi will give you a list of all the compatible event handlers that exist on the form)
  1. Select the event from the drop-down list. (e.g. Button1Click)
What we have done here is create a single event-handling method that handles the OnClick event of both a button and a menu item. Now, everything we have to do (in this shared event handler) is to distinguish which component called the handler.
For example, we might have a code like this:
 procedure TForm1.Button1Click(Sender: TObject) ;
   {code for both a button and a menu item}
   {some specific code:}
   if Sender = Button1 then
    ShowMessage('Button1 clicked!')
   else if Sender = MenuItem1 then
    ShowMessage('MenuItem1 clicked!')
    ShowMessage('??? clicked!') ;
In general, we check if the Sender is equal to the name of the component.

Note: the second else in the if-then-else statement handles the situation when neither the Button1 nor the MenuItem1 have caused the event. But, who else might call the handler, you could ask. Try this (you'll need a second button: Button2) :

 procedure TForm1.Button2Click(Sender: TObject) ;
    Button1Click(Button2) ;
    {this will result in: '??? clicked!'}

IS and AS

Since Sender is of type TObject, any object can be assigned to Sender. The value of Sender is always the control or component that responds to the event. We can test Sender to find the type of component or control that called the event handler using the reserved word is. For example,
 if Sender is TButton then
To scratch the surface of "is" and "as" operators add an Edit box (named Edit1) to the form and place the following code in the OnExit event handler:
 procedure TForm1.Edit1Exit(Sender: TObject) ;
   Button1Click(Edit1) ;
Now change the ShowMessage('??? clicked!') ; part in the Button1 OnClick event handler to:
 {... else}
   if Sender is TButton then
     ShowMessage('Some other button triggered this event!')
   else if Sender is TEdit then
     with Sender as TEdit do
       Text := 'Edit1Exit has happened';
       Width := Width * 2;
       Height := Height * 2;
      end {begin with}
Ok, let's see: if we click on the Button1 the 'Button1 clicked!' will appear, if we click on the MenuItem1 the 'MenuItem1 clicked!' will pop up. However if we click on the Buton2 the 'Some other button triggered this event!' message will appear, but what will happen when you exit the Edit1 box? I'll leave this to you.


As we can see, the Sender parameter can be very useful when used properly. Suppose we have a bunch of Edit boxes and Labels that share the same event handler. If we want to find out who triggered the event and act, we'll have to deal with Object variables. But, let's leave this for some other occasion.