1. Home
  2. Computing & Technology
  3. Delphi Programming
RTL referenceGlossary|Tips/Tricks|FREE App/VCL|Best'O'Net|Books|Link To
 
Creating Custom Delphi Components - Inside and Out
Page 7: On Events
 More of this Feature
• Page 1: About components
• Page 2: New...Component
• Page 3: On Fields
• Page 4: On Properties
• Page 5: On Constructors
• Page 6: On Destructors and Methods
• Page 8: Hiding data
• Page 9: Virtual functions and Abstract Classes
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• VCL Writing/Enhancing
• Custom Component Dev.
• OOP in Delphi
• Free Source Components

   Events
Events are defined by you, the component writer, and allow you to tell the user when certain things happen. Events are entirely arbitrary, but try to keep the names descriptive. The standard notation for events is "OnXYZ" (for example "OnMouseDown"). Events don't need to be prefixed with "On", but it's a good idea because it follows standards and makes more sense.

Events are procedural pointers. This means that they can get set to different procedures/functions as long as the parameter list is correct. They can also be assigned the value "Nil", which means they don't point to anything (the event hasn't been handled). This is the default starting value for all events.

To create an event you first of all declare it as a procedure/function "of Object". What does that mean? Well, just what it says. if I said "The Money of Ali" (I wish!) you would know what I meant, and "Of Object" means literally that - it's a method that belongs to an Object (i.e. a class).

The "Of Object" distinction is quite important. Whenever you write a method for a class it gains an extra, hidden, parameter - "Self". This is set to the current object that owns the method (e.g. "Something" in "Something.DoAMethod"). This means that the following two procedures are NOT identical (and thus not assignable to each other):

procedure Something(i: Integer);
procedure TFromAClass.Something(i: Integer);

The second procedure gets translated into:

procedure TFromAClass.Something(Self: TFromAClass; i: Integer);

Now it should be pretty clear why you need to use "of object". Since your events will belong to components (i.e. classes) they need to take care of this little complication. Adding "of object" means the compiler now knows there will be this implicit Self parameter and doesn't bother you any more.

There is a standard event type called TNotifyEvent. This is the generic event routine, which wants the parameter "Sender: TObject". Let's give this a shot, first of all:

type
  TEventful = class(TObject)
  private
    FData: Integer;
    FMyEvent: TNotifyEvent;
    procedure SetMe(NewValue: Integer);
  published
    property Data: Integer read FData write SetMe;
    property OnSomething: TNotifyEvent read FMyEvent write FMyEvent;
  end;

procedure TEventful.SetMe(NewValue: Integer);
begin
  if (NewValue <> FData) then
  begin
    FData := NewValue;
    if (FData in [0..10]) and (Assigned(FMyEvent)) then
      FMyEvent(Self);
  end;
end;

This contrived example has an integer that the user can set. If they set it to a value between 0 and 10 inclusive then our event, "OnSomething", gets generated. There are a few points to discuss in the above example.

The main point is that our event is actually a variable of type TNotifyEvent! If you remember, I mentioned before how events were procedural pointers? Well, if you think about the above example you might notice the property OnSomething can be freely assigned to anything of type TNotifyEvent. So you can have, for example:

procedure TSomething.OnButtonClick(Sender: TObject);
begin
end;

procedure TSomething.OnYoMomma(Sender: TObject);
begin
end;

procedure TSomething.ChangeMe;
var
  x: TEventful;
begin
  x := TEventful.Create;
  x.OnSomething := OnButtonClick;
  // or...
  x.OnSomething := OnYoMomma;  // :-p
  x.Free;
end;

You can now see what I meant about changing your event freely.

The next point to discuss is TNotifyEvent itself. I said before that you needed methods "of Objects" to do events. Why the heck did I use a TNotifyEvent? Relax, there's a perfectly obvious solution. TNotifyEvent is exactly that, but it's just been made a type to save you typing (pun!). TNotifyEvent's declaration looks like this:

type
  TNotifyEvent = procedure(Sender: TObject) of object;

There, now everyone's happy :-).

After this, there is yet another point to discuss - "Assigned". Simply put, since events might not be handled you need to check first before calling them, or you'll end up with an exception. Remember that most event handlers are left empty, after all! Always use "Assigned" before calling your event.

Now we're on to the final point (so many points from one example!). The parameter I passed in was "Self". Because TNotifyEvent wants a parameter "Sender" we need to supply it. Remember that calling events from your component is exactly the same as calling a procedure normally. If it asks you for parameters, give them. In this case I passed in "Self", which, if you remember, points to the current object. This means that many objects can be given the same event handler and the code will be able to tell which "Sender" generated the event. A-ha, suddenly Delphi seems a little more understandable ;-).

Right, having said that, here's another example... remember that events are just fancy procedures:

type
  TMagicEvent = procedure(Sender: TObject; const HelloMsg: String) of object;

  TEventful = class(TObject)
  private
    FData: Integer;
    FMyEvent: TMagicEvent;
    procedure SetMe(NewValue: Integer);
  public
    property OnSomething: TMagicEvent read FMyEvent write FMyEvent;
  published
     property Data: Integer read FData write SetMe;
  end;

procedure TEventful.SetMe(NewValue: Integer);
begin
  if (NewValue <> FData) then
  begin
    FData := NewValue;
    if Assigned(FMyEvent) then
    begin
      case FData of
        0..10: FMyEvent(Self, 'Between 1 and 10');
        11..20: FMyEvent(Self, 'Between 11 and 20');
        else FMyEvent(Self, 'You chose a dumb number.');
      end; 
    end;
  end;
end;

I'm nearly done talking about events, so hang in there. The first point from this example is that I made the event public, just in case you thought you could only have published ones. Events, as with everything else, can go in any of the four sections. Remember that!

You can hopefully see what events are now - they're just fancy methods. Look at the case statement above... this quite clearly demonstrates it. You can give events any parameter list. They are just methods. This means you don't need to use the Sender: TObject parameter if you don't want to - but that's not a good idea, because code might need to know what object generated the event. It's best to keep it there, but if you're sure you won't need it you can quite easily remove it.

After all that ranting, we're done talking about events. Ever onwards...

   Question, Suggestions...
If you have any questions or comments to this (huge) article, please post them on the Delphi Programming Forum. Discuss!

Next page > Hiding data > Page 1, 2, 3, 4, 5, 6, 7, 8, 9

All graphics (if any) in this feature created by Zarko Gajic.

 More Delphi
· Learn another routine every day - RTL Quick Reference.
· Download free source code applications and components.
· Talk about Delphi Programming, real time.
· Link to the Delphi Programming site from your Web pages.
· Tutorials, articles, tech. tips by date: 2001|2000|1999|1998 or by TOPIC.
· NEXT ARTICLE: GDI Graphics In Delphi.
From simple lines to direct API calls: the ultimate tutorial to GDI graphics in Delphi. This tutorial will introduce you to some of the techniques in the GDI Delphi drawing. Look for: drawing lines and shapes, drawing pictures, flicker-free drawings, off-screen bitmaps, GDI drawings the API way...
 Stay informed with all new and interesting things about Delphi (for free).
Subscribe to the Newsletter
Name
Email

 Got some code to share? Got a question? Need some help?
Explore Delphi Programming
About.com Special Features

Holiday Central

What to eat, where to go, fun things to do and how to save money on the perfect gifts. More >

Family Tech Center

Stay connected and entertained with reviews on tips on the latest HDTVs, cellphones and more. More >

  1. Home
  2. Computing & Technology
  3. Delphi Programming

©2009 About.com, a part of The New York Times Company.

All rights reserved.