Delphi:如何在不覆盖现有事件处理程序的情况下动态分配事件处理程序?

时间:2010-12-21 16:38:56

标签: delphi event-handling

我需要遍历组件并分配一个事件处理程序(例如,为所有TButton动态分配OnClick事件

ShowMessage('You clicked on ' + (Sender as TButton).Name);

问题是在某些情况下我已经分配了TButton OnClick事件。

有没有办法解决问题?

让我们假设我有一个Button1,其中带有编码的onclick事件处理程序:

ShowMessage('This is Button1');

在我的“解析”后,我希望Button1的完整事件处理程序变为:

ShowMessage('This is Button1'); // design time event handler code
ShowMessage('You clicked on ' + (Sender as TButton).Name); // runtime added

注意:我正在寻找一种允许我使用TButton而不继承它的解决方案。

3 个答案:

答案 0 :(得分:16)

你可以在覆盖它之前寻找OnClick的任务,坚持下去并在你的新处理程序中使用它 - 基本上链接事件。

这样的事情:

  var original : TNotifyEvent;

  original := Component.OnClick;
  Component.OnClick := NewMethod;

然后在你的NewMethod中:

  if assigned(original) then original(Sender);

你可能不想要一个原始变量,而是拥有一个键入该组件的集合。

答案 1 :(得分:2)

如果您自己编写替换处理程序,则可以执行以下操作:

  • 在分配新处理程序之前,存储对象的引用以及对列表或其他结构中原始处理程序的引用。

  • 在替换处理程序中,包含用于检查列表以查看当前对象是否具有条目的代码。如果是,请在完成自己的工作之前调用存储的方法。

这是相当轻量级的(每个条目都是两个指针的列表)。通过一些额外的工作(以支持订购),您甚至可以链接多个替换处理程序。

答案 2 :(得分:1)

你不能直接这样做,因为Delphi不支持链式事件(我假设是VCL Delphi)。

因此,您想要做的任何事情都涉及直接分配OnClick事件将无法正常工作。你可能会做的是创建一个拦截器组件,即具有此签名的东西:

type
   TButton = class(stdctrls.TButton)

您必须覆盖OnClick属性,以便write事件将事件处理程序存储到可供类使用的内部列表中。

property OnClick: TNotifyEvent read GetOnClick write SetOnClick;

然后在SetOnClick处理程序中,您将能够将事件处理程序存储在内部列表中。

现在,您必须覆盖Click过程,以便它依次调用每个委托(每个事件处理程序)。

procedure Click; override;

这样就可以了。

请注意,毕竟你将成为TButton类的子类,即使你使用相同的名称......无论如何,这是我能想到的最佳解决方案。关于这个很酷的事情是你仍然可以使用作业而不必了解链式事件,你可以这样做:

MyButton.OnClick := MyHandler

它会自动与其他事件处理程序链接。