我有一个方法:
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;
那么当用户点击某个控件时, 如何调用方法?
答案 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子类。