You are here:About>Computing & Technology>Delphi Programming> Coding Delphi Applications> OOP in Delphi> Simulating multicast events in Win32 Delphi
About.comDelphi Programming
Simulating multicast events in Win32 Delphi
In Win32 Delphi OOP, only one method can be assigned as a handler to a component's event. In Delphi for .Net, multiple event handlers can be bound to the same event. Here's a simulation of multicast events in Win32 Delphi.
 More of this Feature
• Download Source Code
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• OOP in Delphi
• Simulating class properties in Win32 Delphi
• Language features in Delphi for .NET

When you develop (Win32) applications using Delphi you almost always write the code to handle some component's event(s). For example, when you drop a TButton on a form and double click it, an empty event handler is created where you write the code to react on the user click action.
Win32 Delphi allows you to assign only one method as a handler to an event of a component.

With Delphi for .NET a notion of multicast events was introduced. A developer can assign two or more methods to be called when an event gets fired.

Let's see how to build a Win32 Delphi object that maintains a list of the methods its event(s) is handled by - thus creating a simulation of multicast event handling.
Before we start, I strongly suggest that you freshen up your Delphi OOP and custom component development memory...

A simple example of multicast event handling in Win32 Delphi
First, we'll define a simple class (TMultiEventClass) with only one event of TMutliEvent type. In order to store a list of methods that will be called when event is fired (using the FireMultiEvent) we'll use a fMultiEventHandlers TList object. The TList Delphi class is designed to be used as a storage mechanism for an array of pointers.
By design, each method (function or procedure) in Delphi code can be represented with a TMethod Delphi type. A TMethod type can be used, for example, to execute a method by its name.

type
  PMethod = ^TMethod;

  TMutliEvent = procedure(const Value : string) of object;

  TMultiEventClass = class
  private
    fMultiEventHandlers : TList;
  public
    constructor Create;
    destructor Destroy; override;

    procedure AddMultiEvent(const Value: TMutliEvent);
    procedure RemoveMultiEvent(const Value: TMutliEvent);

    procedure FireMultiEvent;
  end;

The above code is the interface part of the TMultiEventClass class. The fMultiEventHandlers is a private list used to store pointers to methods that will handle an event of type TMutliEvent.
Since this class allows multiple event handler to be assigned to one event we also need two procedures to add an event handler and to remove an event handler: AddMultiEvent and RemoveMultiEvent.

Here's the implementation part:

{ TMultiEventClass }

//create the event handlers storage
constructor TMultiEventClass.Create;
begin
  inherited Create;
  fMultiEventHandlers := TList.Create;
end;

//clean up
destructor TMultiEventClass.Destroy;
var
  cnt: Integer;
begin
  for cnt := 0 to -1 + fMultiEventHandlers.Count do
    Dispose(fMultiEventHandlers[cnt]);
  fMultiEventHandlers.Free;

  inherited;
end;

//add an event handler to the list
procedure TMultiEventClass.AddMultiEvent(
  const Value: TMutliEvent);
var
  h: PMethod;
begin
  h := New(PMethod);
  h^.Code := TMethod(Value).Code;
  h^.Data := TMethod(Value).Data;
  fMultiEventHandlers.Add(h);
end;

//remove an event handler from the list (if there)
procedure TMultiEventClass.RemoveMultiEvent(
  const Value: TMutliEvent);
var
  cnt: Integer;
begin
  for cnt := 0 to -1 + fMultiEventHandlers.Count  do
  begin
    if (TMethod(Value).Code = 
        TMethod(fMultiEventHandlers[cnt]^).Code) and
       (TMethod(Value).Data = 
        TMethod(fMultiEventHandlers[cnt]^).Data) then
    begins
      Dispose(fMultiEventHandlers[cnt]);
      fMultiEventHandlers.Delete(cnt);
      Break;
    end;
  end;
end;

//"fire" event (call all handlers)
procedure TMultiEventClass.FireMultiEvent;
var
  cnt: Integer;
  msg : string;
begin
  for cnt := 0 to -1 + fMultiEventHandlers.Count do
  begin
    msg := Format('%d/%d %s',
                  [1 + cnt, 
                   fMultiEventHandlers.Count, 
                   'fired!']);
    TMutliEvent(fMultiEventHandlers[cnt]^)(msg);
  end;
end;

In the above code, the FireMultiEvent procedure is used to fake raising an event (with more event handlers). In normal scenarios this would be a private method initiated by an action inside the TMultiEventClass's code.

For a better understanding of the code, we'll use a simple test example. Drop a TButton on a Delphi form, and assign the next code for the OnClick event:

{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
var
  test : TMultiEventClass;
begin
  test := TMultiEventClass.Create;
  try
    test.AddMultiEvent(Handler1);
    test.AddMultiEvent(Handler2);
    test.RemoveMultiEvent(Handler1);
    test.AddMultiEvent(Handler3);

    test.FireMultiEvent;
  finally
    test.Free;
  end;
end;

A test object is created, AddMultiEvent is used to store a reference to 2 methods Handler1 and Handler2, Handler1 is then removed using the RemoveMultiEvent procedure, one additional method is added to the event handler list: Handler3, and finally FireMultiEvent procedure is called.

The three Handler1, Handler2 and Handler3 methods are defined as:

procedure TForm1.Handler1(const value: string);
begin
  ShowMessage('h1: ' + value);
end;

procedure TForm1.Handler2(const value: string);
begin
  ShowMessage('h2: ' + value);
end;

procedure TForm1.Handler3(const value: string);
begin
  ShowMessage('h3: ' + value);
end;

What will happen when you run this code? What methods will be called by FireMultiEvent? "Handler2" and "handler3" is the answer!

Multicast events in Win32 Delphi

That's it. Multicast events in Win32 Delphi! If you do not believe me, download the code and see for yourself. Questions, comments? You already know: Delphi Programming Forum!

Note: Looking for "Simulating class properties in (Win32) Delphi"?

From Zarko Gajic,
Your Guide to Delphi Programming.
FREE Newsletter. Sign Up Now!
Newsletters & RSSEmail to a friendSubmit to Digg
 All Topics | Email Article | | |
Advertising Info | News & Events | Work at About | SiteMap | Reprints | HelpOur Story | Be a Guide
User Agreement | Ethics Policy | Patent Info. | Privacy Policy©2008 About, Inc., A part of The New York Times Company. All rights reserved.