Обработка событий Delphi, как создать собственное событие - PullRequest
17 голосов
/ 26 апреля 2011

Я новичок в разработке Delphi. Я должен создать событие и передать некоторые свойства в качестве параметров. Может кто-нибудь поделиться какой-нибудь демонстрационной программой, которая показывает, как это сделать с нуля. Я погуглил почти каждый сайт, все они дали кусок кода, но мне нужна полноценная программа, которая проста и понятна.

Ответы [ 4 ]

49 голосов
/ 26 апреля 2011

Вот краткое, но полное консольное приложение, которое показывает, как создать собственное событие в Delphi.Включает в себя все, от объявления типа до вызова события.Прочитайте комментарии в коде, чтобы понять, что происходит.

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.
18 голосов
/ 26 апреля 2011

Полный ответ на проект хороший.Но это альтернативный ответ, показывающий, как делать то, что вы хотите, в уже имеющейся форме.

Перейдите в форму и перейдите в раздел интерфейса, в области типов, вне определения класса вашей формы идобавьте тип:

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

  TMyForm = class(TForm)
            ....

Традиционно, но не обязательно, чтобы первым элементом в вашем событии был объект, отправляющий его, но использовался базовый класс TObject вместо фактического типа класса вашей формы.
Другие параметры, приведенные выше, совсем не обязательны, но показывают, как вы можете объявить свои собственные дополнительные данные.если они вам не нужны, просто используйте Sender: TObject.И в этом случае вам вообще не нужно определять TMyEvent, просто используйте тип TNotifyEvent.

Теперь объявите поле, которое использует этот тип, в вашей форме:

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

Теперь объявите свойство, которое обращается к этому полю, в разделе свойств вашей формы:

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

Теперь перейдите туда, где вы хотите, чтобы это событие «сработало» (вызывалось, если оно установлено), и напишите это:

// 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;
14 голосов
/ 26 апреля 2011

Вы используете обработчик событий, чтобы реагировать, когда происходит что-то еще (например, AfterCreation и перед закрытием).

Чтобы использовать события для своего собственного класса, вам нужно определить тип события. Измените тип и количество необходимых параметров.

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

В классе вы можете добавить DoEvent (переименовать для соответствующего события). Так что вы можете вызвать DoEvent внутри страны. DoEvent обрабатывает возможность того, что событие не назначено.

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 голосов
/ 02 ноября 2014

в контексте размещения «событий» в DLL. Я описал концепцию с использованием интерфейсов, шаг за шагом ... может быть, это помогает по-другому: Использование прослушивателей событий в среде без графического интерфейса (DLL) (Delphi)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...