Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi event handling, how to create own event

Tags:

events

delphi

I am new to delphi development. I have to create an event and pass some properties as parameters. Could someone share some demo program that shows how to do this from scratch. I googled nearly every site, they all gave a piece of code, but what I need is a full fledged program that is simple and understandable.

like image 568
mac Avatar asked Apr 26 '11 06:04

mac


People also ask

What is event in Delphi?

In Delphi, almost all the code you write is executed, directly or indirectly, in response to events. An event is a special kind of property that represents a run-time occurrence, often a user action. The code that responds directly to an event - called an event handler - is a Delphi procedure.

What is an event how event handler is added?

In programming, an event handler is a callback routine that operates asynchronously once an event takes place. It dictates the action that follows the event. The programmer writes a code for this action to take place. An event is an action that takes place when a user interacts with a program.


2 Answers

Here's a short-but-complete console application that shows how to create your own event in Delphi. Includes everything from type declaration to calling the event. Read the comments in the code to understand what's going on.

program Project23;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  // Declare an event type. It looks allot like a normal method declaration except
  // it suffixed by "of object". That "of object" tells Delphi the variable of this
  // type needs to be assigned a method of an object, not just any global function
  // with the correct signature.
  TMyEventTakingAStringParameter = procedure(const aStrParam:string) of object;

  // A class that uses the actual event
  TMyDummyLoggingClass = class
  public
    OnLogMsg: TMyEventTakingAStringParameter; // This will hold the "closure", a pointer to
                                              // the method function itself + a pointer to the
                                              // object instance it's supposed to work on.
    procedure LogMsg(const msg:string);
  end;

  // A class that provides the required string method to be used as a parameter
  TMyClassImplementingTheStringMethod = class
  public
    procedure WriteLine(const Something:string); // Intentionally using different names for
                                                 // method and params; Names don't matter, only the
                                                 // signature matters.
  end;

  procedure TMyDummyLoggingClass.LogMsg(const msg: string);
  begin
    if Assigned(OnLogMsg) then // tests if the event is assigned
      OnLogMsg(msg); // calls the event.
  end;

  procedure TMyClassImplementingTheStringMethod.WriteLine(const Something: string);
  begin
    // Simple implementation, writing the string to console
    Writeln(Something);
  end;

var Logging: TMyDummyLoggingClass; // This has the OnLogMsg variable
    LoggingProvider: TMyClassImplementingTheStringMethod; // This provides the method we'll assign to OnLogMsg

begin
  try
    Logging := TMyDummyLoggingClass.Create;
    try

      // This does nothing, because there's no OnLogMsg assigned.
      Logging.LogMsg('Test 1');

      LoggingProvider := TMyClassImplementingTheStringMethod.Create;
      try
        Logging.OnLogMsg := LoggingProvider.WriteLine; // Assign the event
        try

          // This will indirectly call LoggingProvider.WriteLine, because that's what's
          // assigned to Logging.OnLogMsg
          Logging.LogMsg('Test 2');

        finally Logging.OnLogMsg := nil; // Since the assigned event includes a pointer to both
                                         // the method itself and to the instance of LoggingProvider,
                                         // need to make sure the event doesn't out-live the LoggingProvider                                             
        end;
      finally LoggingProvider.Free;
      end;
    finally Logging.Free;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
like image 158
Cosmin Prund Avatar answered Oct 13 '22 00:10

Cosmin Prund


The complete project answer is good. But this is an alternate answer showing how to do what you want, in a form you already have.

Go into your form, and go to the interface section, in the types area, outside your form's class definition and add a type:

 interface
 type
  TMyEvent = procedure(Sender:TObject;Param1,Param2,Param3:Integer) of object;

  TMyForm = class(TForm)
            ....

It is traditional, but not required, that the first item in your event be the object sending it, but to use base class TObject instead of your form's actual class type.
The other parameters above are not required at all, but are showing you how you would declare your own additional data. if you don't need them, then just use Sender:TObject. And in that case, you don't have to define TMyEvent at all, just use the TNotifyEvent type.

Now declare a field that uses that type, in your form:

TMyForm = class(TForm)
 private
   FMyEvent : TMyEvent;
  ...

Now declare a property that accesses that field, in your form's properties section:

  // this goes inside the class definition just before the final closing end 
 property MyEvent:TMyEvent read FMyEvent write FMyEvent

Now go to where you want that event to 'fire' (get called if it is set) and write this:

// this goes inside a procedure or function, where you need to "fire" the event.
procedure TMyForm.DoSomething;
begin
  ...
  if Assigned(FMyEvent) then FMyEvent(Self,Param1,Param2,Param3);
end;
like image 35
Warren P Avatar answered Oct 13 '22 00:10

Warren P