首页 > 解决方案 > 扩展屏幕中所有 MenuItem 的事件 OnClick 以执行另一段代码

问题描述

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

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

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

我也有以下程序:

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

而且我希望每次单击 TMenuItem 时,程序都会显示 TMenuItem 的名称以及“额外”消息。

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

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

标签: delphidelphi-5

解决方案


只要您的所有事件处理程序都在某个时刻(在设计时或运行时)分配并且之后不更改,您就可以执行以下操作:

  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 继承这个类使得表单在被销毁时会自动释放它。
  • HandleOnClick 应该在调用它之前检查是否分配了 FORigEvent。

推荐阅读