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

发布于 2024-10-08 19:21:28 字数 571 浏览 1 评论 0原文

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

I need to loop through Components and assign an event handler (for example Dynamically assigning OnClick event for all TButton to

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

The problem is that in some cases I already assigned the TButton OnClick event.

Is there a way to solve the problem?

Let's imagine I have Button1 for which the harcoded onclick event handler is:

ShowMessage('This is Button1');

After my "parsing" I would like that the full event handler for Button1 becomes:

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

Note: I am looking for a soliution that allows me to use TButton as it is without inheriting from it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

离旧人 2024-10-15 19:21:28

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

像这样:

  var original : TNotifyEvent;

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

然后在您的 NewMethod 中:

  if assigned(original) then original(Sender);

您可能不需要单个原始变量,而是保存一个在组件上键入的集合。

you could look for an assignment of OnClick before overwriting it, persist this and use it in your new handler - basically chaining the events.

Something like this:

  var original : TNotifyEvent;

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

and then in your NewMethod:

  if assigned(original) then original(Sender);

you'll likely not want a single original variable but instead hold a collection keyed on the component.

怀中猫帐中妖 2024-10-15 19:21:28

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

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

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

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

If you are writing the replacement handlers yourself you could do the following:

  • Before assignment of the new handler, store a reference to the object and a reference to the original handler in a list or other structure.

  • In your replacement handler, included code to check the list to see if the current object has an entry. If it does, call the stored method before doing your own work.

This is fairly lightweight (a list where each entry is two pointers). With a little extra work (to support ordering) you could probably even chain more than one replaced handler.

╄→承喏 2024-10-15 19:21:28

你不能直接这样做,因为 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

并且它将自动与其余事件处理程序链接起来。

You can't do that directly as Delphi does not support chained events (I'm assuming VCL Delphi).

So anything that you want to do that involves directly assigning the OnClick event will not work. What you might do is create an interceptor component, that is, something with this signature:

type
   TButton = class(stdctrls.TButton)

You'll have to override the OnClick property so that the write event stores the event handler into an internal list, available to class.

property OnClick: TNotifyEvent read GetOnClick write SetOnClick;

then on the SetOnClick handler you'll be able to just store your event handler in the internal list.

Now, you will have to override the Click procedure so that it invokes every delegate (every event handler) in turn.

procedure Click; override;

And that will do it.

Note that after all you'll be kind of subclassing the TButton class, even if you're using the same name... Anyway that's the best solution I can think of. The cool thing about this is that you can still use assignments without having to know about chained events, you can just do:

MyButton.OnClick := MyHandler

and it will get automatically chained with the rest of event handlers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文