扩展屏幕中所有MenuItem的OnClick事件,执行另一段代码

Extend the event OnClick of all MenuItems in the screen to execute another block of code

我想给屏幕上的所有TMenuItems设置一个事件OnClick来做事件当前做的事情,另外几行代码。我目前正在使用 Delphi 5

例如,假设我有一个 TMenuItem,代码为:

procedure TdesktopForm.MenuFoo1Click(Sender: TObject);
begin
  ShowMessage(TComponent(Sender).Name)
end;

我还有以下程序:

procedure TdesktopForm.bar;
begin
  ShowMessage('extra')
end;

我希望每次单击 TMenuItem 时程序都显示 TMenuItem 的名称以及 'extra' 消息。

显示的示例只是我的问题的演示,因为在真正的软件中我有超过 300 个菜单项,我想通用地执行此操作,因此我不必在所有当前的菜单项中添加额外的代码行菜单点击,也不会在我添加新菜单项时添加它们。执行顺序(在菜单点击和额外代码块之间)无关紧要。

我尝试使用 TActionList 但我无法检索触发该操作的对象,因此,我无法打印它的名称。我尝试使用 ActiveControl 但它总是 return 当前聚焦的对象,而不是我单击的实际菜单。而且,TAction 执行事件会覆盖我的 TMainMenu.OnClick 事件

只要您的所有事件处理程序都在某个时间点(在设计时或 运行 时)分配并且之后不更改,您可以这样做:

  1. 枚举菜单中的所有菜单项
  2. 为每个对象创建一个如下所述的对象

    type
      TEventInterceptor = class(TComponent)
      private
        FOrigEvent: TNotifyEvent;
        FAdditionalEvent: TNotifyEvent;
        procedure HandleOnClick(_Sender: TObject);
      public
        constructor Create(_MenuItem: TMenuItem; _AdditionalEvent: TNotifyEvent);
      end;
    
    constructor TEventInterceptor.Create(_MenuItem: TMenuItem; _AdditionalEvent: TNotifyEvent);
    begin
      inherited Create(_MenuItem);
      FOrigEvent := _MenuItem.OnClick;
      FAdditionalEvent := _AdditionalEvent;
      _MenuItem.OnClick := HandleOnClick;
    end;
    
    procedure TEventInterceptor.HandleOnClick(_Sender: TObject);
    begin
      FOrigEvent(_Sender);
      FAdditinalEvent(_Sender);
    end;
    

请注意,此代码完全未经测试,甚至可能无法编译。 我也不确定这是否适用于 Delphi 5。它确实适用于 Delphi 6,所以机会很好。

编辑: 一些补充说明(感谢评论):

  • 从 TComponent 继承此 class 使表单在销毁时自动释放它。
  • HandleOnClick 应该在调用之前检查 FORigEvent 是否已分配。