Search code examples
delphivariable-assignmentlazaruseventhandleraddress-operator

Assigning a procedure to dynamically created object


I want to dynamically create TImage controls and then drag and drop them. But if I want to assign the procedure used for the dragging to an event of this Image, it gives me:

Error: Wrong number of parameters specified for call to "ClickEvent"

This is my code for the dragging:

procedure ClickEvent(Sender:TObject; Button:TMouseButton; Shift:TShiftstate; X,Y:Integer);
begin
  if Button = mbLeft then TControl(Sender).BeginDrag(False);
end; 

And here I create the Image and add the properties:

procedure SpawnCard(Ort:TWinControl; sKarte:TKarteClass; Liste: Array of TKarte; BilderListe:Array of TCustomImage);
var
  Bild:TImage;
begin
  Liste[High(Liste)]:=sKarte.Create();

  Bild:=TImage.Create(Combat);
  with Bild do
  begin
    OnMouseDown:=ClickEvent;
    Parent:=Ort;
    Top:=1;
    Left:=200*length(BilderListe);
    width:=200;
    height:=300;
    Proportional:=True;
    Stretch:=True;
    Picture.LoadFromFile(Liste[High(Liste)].PicPath);
  end;

  BilderListe[High(BilderListe)]:=Bild;

end; 

I don't want to call ClickEvent, I just want to assign it to the event.


Solution

  • TImage.OnMouseDown (inherited from its TControl parent class) is a TMouseEvent property.

      TMouseEvent = procedure(Sender: TObject; Button: TMouseButton;
        Shift: TShiftState; X, Y: Integer) of object;
    

    As you can see, it's declared as "of object", which means it expects a method pointer (See the Method Pointers section).


    Example 1:

    Declare the ClickEvent on the form (or any other object):

      TForm1 = class(TForm)
        Image1: TImage;
      public
        procedure ClickEvent(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
      end;
    
    ...
    
    procedure TForm1.ClickEvent(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    begin
      if Button = mbLeft then TControl(Sender).BeginDrag(False);
    end;
    

    Then you can assign it as follows:

      Image1.OnMouseDown := Form1.ClickEvent;
    

    Example 2:

    Declare the ClickEvent as a class method:

      TMyEventHandlers = class
        class procedure ClickEvent(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
      end;
    
    ...
    
    class procedure TMyEventHandlers.ClickEvent(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    begin
      if Button = mbLeft then TControl(Sender).BeginDrag(False);
    end;
    

    Then you can assign it as follows:

    Image1.OnMouseDown := TMyEventHandlers.ClickEvent;