Delphi: How to call a method when i click a control?

自古美人都是妖i 提交于 2019-12-11 05:05:10

问题


i have a method:

procedure Frob(Sender: TObject);

that i want to call when i click a menu item.

The method comes to me though an interface:

animal: IAnimal;

IAnimal = interface
   procedure Frob(Sender: TObject);
end;

The question revolves around what to assign to the OnClick event handler of a menu item (i.e. control):

var
   animal: IAnimal;
   ...
begin
   ...
   menuItem := TMenuItem.Create(FileMenu)
   menuItem.Caption := 'Click me!';
   menuItem.OnClick :=  <-------- what to do
   ...
end;

The obvious choice, my first attempt, and the wrong answer is:

   menuItem.OnClick := animal.Frob;

So how can i call a method when user clicks a control?

See also

  • Why doesn't it work?

回答1:


Have whatever object you're in hold the animal in a private field, then set up a method that calls it. Like so:

procedure TMyClass.AnimalFrob(Sender: TObject);
begin
   FAnimal.Frob(sender);
end;

Then the solution becomes easy:

menuItem.OnClick := self.AnimalFrob;




回答2:


Another, slightly hackier approach would be to store a reference to the IAnimal in the Tag property of the TMenuItem.

This could be the index of the IAnimal in a TList as you suggested:

if Sender is TMenuItem then
  IAnimal(FAnimals[TMenuItem(Sender).Tag]).Frob;

Or you could cast the interface to Integer.

MenuItem.Tag := Integer(AnAnimal);

Then cast back to IAnimal in the event handler:

if Sender is TMenuItem then
  IAnimal(TMenuItem(Sender)).Frob;

This works well with Object references, some care may be required with interfaces due to the reference counting.

Note that Delphi 7 also has a TInterfaceList in Classes.pas




回答3:


I know you tagged the question as answered, but here are some other suggestions :

  type
    IClicker = Interface
      function GetOnClickProc : TNotifyEvent;
    End;

  type
    TBlob = class( TInterfacedObject, IClicker )
      procedure OnClick( Sender : TObject );
      function GetOnClickProc : TNotifyEvent;
    end;

{ TBlob }

function TBlob.GetOnClickProc : TNotifyEvent;
begin
  Result := Self.OnClick;
end;

procedure TBlob.OnClick(Sender: TObject);
begin
  MessageDlg('Clicked !', mtWarning, [mbOK], 0);
end;

{ MyForm }
  var
    clicker : IClicker;

  begin
    ...
    menuItem.OnClick := clicker.GetOnClickProc;
  end;

Of course, you have to be careful about the lifetime of the "clicker" object...

If you can manipulate your objects as objects (and not only as interfaces), try adding a common subclass :

type
  TClicker = class
    procedure OnClick( Sender : TObject ); virtual;
  end;

var
  lClicker : TClicker;
...
menuItem.OnClick := lClicker.OnClick;

I would also go for Cosmin Prund's comment : make a specialized TMenuItem subclass.



来源:https://stackoverflow.com/questions/2829844/delphi-how-to-call-a-method-when-i-click-a-control

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!