Delphi:当我点击一个控件时如何调用方法?

时间:2010-05-13 19:53:39

标签: delphi events event-handling interface

我有一个方法:

procedure Frob(Sender: TObject);
当我点击一个菜单项时,我想打电话。

通过界面来找我方法:

animal: IAnimal;

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

问题围绕分配给菜单项(即控件)的OnClick事件处理程序的内容:

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

显而易见的选择,my first attempt, and the wrong answer is

   menuItem.OnClick := animal.Frob;

那么当用户点击某个控件时, 如何调用方法?

另见

3 个答案:

答案 0 :(得分:4)

在私人领域中拥有你所拥有的任何物体,然后设置一个调用它的方法。像这样:

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

然后解决方案变得简单:

menuItem.OnClick := self.AnimalFrob;

答案 1 :(得分:1)

另一种稍微粗暴的方法是在TMenuItem的IAnimal属性中存储对Tag的引用。

这可能是你建议的TList中IAnimal的索引:

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

或者您可以将界面强制转换为Integer。

MenuItem.Tag := Integer(AnAnimal);

然后在事件处理程序中强制转换回IAnimal:

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

这适用于Object引用,由于引用计数,接口可能需要注意。

请注意,Delphi 7在Classes.pas中也有一个TInterfaceList

答案 2 :(得分:1)

我知道您已将问题标记为已回答,但此处还有其他一些建议:

  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;

当然,您必须小心“clicker”对象的生命周期......

如果您可以将对象操作为对象(而不仅仅是作为接口),请尝试添加公共子类:

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

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

我也会选择Cosmin Prund的评论:制作一个专门的TMenuItem子类。