【问题标题】:Delphi: How to assign dynamically an event handler without overwriting the existing event handler?Delphi:如何在不覆盖现有事件处理程序的情况下动态分配事件处理程序?
【发布时间】:2010-12-21 16:38:55
【问题描述】:

我需要遍历组件并分配一个事件处理程序(例如为所有 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 而无需从它继承。

【问题讨论】:

  • 类似问题(以完整代码为答案):stackoverflow.com/questions/2441672/…
  • 窥视 TApplicationEvents 源,有你想要的相同事件接收器。
  • 你想要的总称是multicast events,但是Delphi没有这个功能。

标签: delphi event-handling


【解决方案1】:

您可以在覆盖之前查找 OnClick 的分配,将其保留并在您的新处理程序中使用它 - 基本上是链接事件。

类似这样的:

  var original : TNotifyEvent;

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

然后在你的 NewMethod 中:

  if assigned(original) then original(Sender);

您可能不想要一个原始变量,而是持有一个以组件为键的集合。

【讨论】:

  • 感谢您的想法,它应该可以工作。集合的想法(例如泛型 TDictionary)也非常好。
【解决方案2】:

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

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

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

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

【讨论】:

    【解决方案3】:

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

    因此,您想要执行的任何涉及直接分配 OnClick 事件的操作都将不起作用。您可能会做的是创建一个拦截器组件,即具有此签名的东西:

    type
       TButton = class(stdctrls.TButton)
    

    您必须重写 OnClick 属性,以便写入事件将事件处理程序存储到一个内部列表中,可供类使用。

    property OnClick: TNotifyEvent read GetOnClick write SetOnClick;
    

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

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

    procedure Click; override;
    

    这样就可以了。

    请注意,即使您使用相同的名称,毕竟您将成为 TButton 类的子类……无论如何,这是我能想到的最佳解决方案。很酷的一点是,您仍然可以使用分配,而无需了解链式事件,您可以这样做:

    MyButton.OnClick := MyHandler
    

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

    【讨论】:

      猜你喜欢
      • 2010-10-09
      • 2019-02-15
      • 2010-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多