Delphi event handling, how to create own event

后端 未结 4 1049
孤独总比滥情好
孤独总比滥情好 2020-12-02 11:08

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 scratc

相关标签:
4条回答
  • 2020-12-02 11:18

    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;
    
    0 讨论(0)
  • 2020-12-02 11:26

    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;
    
    0 讨论(0)
  • 2020-12-02 11:28

    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.
    
    0 讨论(0)
  • 2020-12-02 11:31

    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)

    0 讨论(0)
提交回复
热议问题