Delphi event handling, how to create own event
Asked Answered
B

4

19

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.

Bernardinabernardine answered 26/4, 2011 at 6:6 Comment(7)
Please explain what you're actually trying to do, providing enough information so we can suggest alternative routes; Because I suspect an answer to the actual question you asked is not going to help you.Godship
<joke>To get a full-fledged program using events do: File -> New -> VCL Forms Application. There you have it, it's a full-fledged working example of how to use events, with full source.</joke>. But as I mentioned in my previous comment, I doubt that's what you actually need. Generally speaking it's difficult to learn from full fledged programs.Godship
Thanks, I actually a want a small program in which elaborate event creation in delphi. How can I create my own events in delphi.Bernardinabernardine
you re-iterated the question, didn't say what you're trying to do. There are possible alternative implementations, using anonymous methods or passing interfaces, event's are not the only way, no matter what you're actually trying to do. I provided a short-but-complete working program using events, hope it helps.Godship
You are asking for a complete demo, and Cosmin gives you one, and then you say, but how do I add it to my program. If I could flag this question with some kind of "annoying user" flag, I would be tempted to do so here. Mac, you need to learn to ask direct, precise questions, and then when you get exactly what you asked for, not say the opposite thing.Walleyed
Cosmin gives very complete and understandable answer.Legged
You can see from this example : Thanks to Norrit I think it is useful and easy to follow.Doubleminded
G
54

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 a lot like a normal method declaration except
  // it is 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, plus a pointer to the
                                              // object instance it is intended 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,
                                         // we 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.
Godship answered 26/4, 2011 at 6:52 Comment(2)
Thanks a lot , Good example , do you also provide a form based example as it is console based. I need to create my own events on form and get some thing as out put. Thanks for kind example.Bernardinabernardine
@Bernardinabernardine no, I can't. This is a complete example, doing the same on a form doesn't require anything special; A form is just a class like any other class. Doing a form-based example requires a minimum of 3 files (dpr, dfm + pas) and doesn't add anything new. I still suspect this is not what you need, but since you don't want to answer the "what for" question, I can't do any better.Godship
W
21

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;
Walleyed answered 26/4, 2011 at 15:9 Comment(2)
Thanks Warren; I shall try to do something with delphi, actually the problem is , flow of program, either I need to define and call the event in a single unit or it takes an other unit to define the Event and Assign properties and then call this event with a button click event. Like progressbar and percentage counter.Bernardinabernardine
I have no idea what you mean. It's best if you ask a different question, if you are still not clear.Walleyed
S
15

You use an event handler to react when something else happens (for example AfterCreation and before closing).

In order to use events for your own class, you need to define the event type. Change the type and number of parameters needed.

type
  TMyProcEvent = procedure(const AIdent: string; const AValue: Integer) of object;
  TMyFuncEvent = function(const ANumber: Integer): Integer of object;

In the class, you can add a DoEvent (rename for the proper event). SO you can call the DoEvent internally. The DoEvent handles the possibility that an event is not assigned.

type
  TMyClass = class
  private
    FMyProcEvent : TMyProcEvent;
    FMyFuncEvent : TMyFuncEvent;
  protected
    procedure DoMyProcEvent(const AIdent: string; const AValue: Integer);
    function DoMyFuncEvent(const ANumber: Integer): Integer;

  public
    property MyProcEvent: TMyProcEvent read FMyProcEvent write FMyProcEvent;
    property MyFuncEvent: TMyFuncEvent read FMyFuncEvent write FMyFuncEvent;
  end;

procedure TMyClass.DoMyProcEvent(const AIdent: string; const AValue: Integer);
begin
  if Assigned(FMyProcEvent) then
    FMyProcEvent(AIdent, AValue);
  // Possibly add more general or default code.
end;


function TMyClass.DoMyFuncEvent(const ANumber: Integer): Integer;
begin
  if Assigned(FMyFuncEvent) then
    Result := FMyFuncEvent(ANumber)
  else
    Result := cNotAssignedValue;
end;
Sportsmanship answered 26/4, 2011 at 6:39 Comment(3)
Thanks dear, very helpful. but still not as to be copy paste and then just changing the property can achieve different results.Bernardinabernardine
@mac, if the code is not copy-paste friendly for you, make it copy-paste friendly yourself. If you don't understand a bit of the code, ask for clarifications. Simply asking for more copy-paste friendly code makes you look like a lazy Do you haz teh codez type.Godship
Thanks ! After a lot of googleing, this is by far the best explanation I found. Wish I could upvote you ten times !Commination
H
0

in the context of placing "events" into a DLL I described a concept using interfaces, step by step... maybe this helps in a different way: Using event listeners in a non-gui environment (DLL) (Delphi)

Harve answered 2/11, 2014 at 12:55 Comment(1)
This would make a nice comment.House

© 2022 - 2024 — McMap. All rights reserved.