使用 ToolsAPI 将菜单项添加到 Delphi IDE 中单元的选项卡上下文菜单

Posted

技术标签:

【中文标题】使用 ToolsAPI 将菜单项添加到 Delphi IDE 中单元的选项卡上下文菜单【英文标题】:Add menu item to unit's tab context menu in Delphi IDE using ToolsAPI 【发布时间】:2017-04-23 05:32:17 【问题描述】:

我正在寻找需要使用哪些服务/接口来将项目添加到 Delphi IDE 中源文件的右键菜单。

例如,如果我右键单击一个单元的选项卡,它有“关闭页面”、“关闭所有其他页面”、“属性”等项目。如果可能,我想向该菜单添加自定义项目.

我查看了 ToolsAPI 单元,但不知道从哪里开始。我假设有一个接口可以用来枚举项目和添加项目,但我不知道从哪里开始寻找。

如果不可能,我会选择代码编辑器的上下文菜单。

也许网上有一些示例,但我仍在寻找,但没有找到。

任何帮助表示赞赏。

【问题讨论】:

How can I add menu items to the code editor’s popup menu? 【参考方案1】:

Remy Lebeau 的链接为您指明了正确的方向 GExperts 指南。

如果你以前没有做过这种事情,它仍然可以 开始编写自己的 IDE 加载项需要一点表现,所以 我在下面列出了如何将项目添加到代码编辑器的最小示例 弹出菜单。

显然,你要做的是创建一个新包,将下面的单元添加到它, 然后在IDE中安装包。单位内拨打Register 执行在编辑器弹出菜单中安装新项目所必需的操作。

确保在安装软件包时代码编辑器处于打开状态。这 原因是,正如您将看到的,代码检查是否存在活动编辑器 当时。我已经离开了如何确保添加弹出项目,即使有 当时没有代码编辑器处于活动状态。提示:如果您查看 ToolsAPI.Pas 单元中的任何一个 你正在使用的 Delphi 版本,你会发现它包括各种通知器, 并且您可以使用其中至少一个的通知来推迟检查是否存在 是一个活跃的编辑器,直到有可能是。

顺便说一句,代码将菜单项添加到在编辑器窗口本身而不是活动选项卡上弹出的上下文菜单中。 IDE 插件的部分乐趣在于尝试看看是否能得到您想要的东西。我自己没有尝试过,但我怀疑将菜单项添加到编辑器选项卡之一的上下文菜单中会很困难 - 因为 Delphi IDE 是一个 Delphi 应用程序,正如您从下面的代码中看到的那样,你可以使用 FindComponent (或者只是遍历一个 Components 集合)来找到你想要的。但是,如果可以的话,最好通过 ToolsAPI 接口来定位。请参阅下面的更新

interface

uses
  Classes, Windows, Menus, Dialogs, ToolsAPI;

type

   TIDEMenuItem = class(TNotifierObject, IOTAWizard, IOTAMenuWizard)
     function GetName: string;
     function GetIDString: string;
     function GetMenuText: string;
     function GetState: TWizardState;
     procedure Execute;
   end;

   TIDEMenuHandler = class(TObject)
     procedure HandleClick(Sender: TObject);
   end;

procedure Register;

implementation

var
  MenuItem: TMenuItem;
  IDEMenuHandler: TIDEMenuHandler;
  EditorPopUpMenu : TPopUpMenu;

procedure TIDEMenuItem.Execute;
begin
  ShowMessage('Execute');
end;

function TIDEMenuItem.GetIDString: string;
begin
  Result := 'IDEMenuItemID';
end;

function TIDEMenuItem.GetMenuText: string;
begin
  Result := 'IDEMenuItemText';
end;

function TIDEMenuItem.GetName: string;
begin
  Result := 'IDEMenuItemName';
end;

function TIDEMenuItem.GetState: TWizardState;
begin
  Result := [wsEnabled];
end;

procedure TIDEMenuHandler.HandleClick(Sender: TObject);
begin
  ShowMessage(TIDEMenuItem(Sender).GetName + ' Clicked');
end;

procedure AddIDEMenu;
var
  NTAServices: INTAServices40;
  EditorServices: IOTAEditorServices;
  EditView: IOTAEditView;
begin
  NTAServices := BorlandIDEServices as INTAServices40;

  EditorServices := BorlandIDEServices as IOTAEditorServices;
  EditView := EditorServices.TopView;

  if Assigned(EditView) then begin
    EditorPopUpMenu := TPopUpMenu(EditView.GetEditWindow.Form.FindComponent('EditorLocalMenu'));
    Assert(EditorPopUpMenu <>Nil);

    IDEMenuHandler := TIDEMenuHandler.Create;
    MenuItem := TMenuItem.Create(Nil);
    MenuItem.Caption := 'Added IDE editor menu item';
    MenuItem.OnClick := IDEMenuHandler.HandleClick;
    EditorPopUpMenu.Items.Add(MenuItem)
  end
  else
    ShowMessage('Code editor not active');
end;

procedure RemoveIDEMenu;
begin
  if MenuItem <> Nil then begin
    EditorPopUpMenu.Items.Remove(MenuItem);
    FreeAndNil(MenuItem);
    IDEMenuHandler.Free;
  end;
end;

procedure Register;
begin
  RegisterPackageWizard(TIDEMenuItem.Create);
  AddIDEMenu;
end;

initialization

finalization
  RemoveIDEMenu;
end.

更新:以下代码找到编辑器窗口的 TabControl 并将菜单项添加到其上下文菜单中。但是请注意,这并不能说明打开了第二个编辑器窗口。

procedure AddIDEMenu;
var
  NTAServices: INTAServices40;
  EditorServices: IOTAEditorServices;
  EditView: IOTAEditView;
  TabControl : TTabControl;

  function FindTabControl(AComponent : TComponent) : TTabControl;
  var
    i : Integer;
  begin
    Result := Nil;
    if CompareText(AComponent.ClassName, 'TXTabControl') = 0 then begin
      Result := TTabControl(AComponent);
      exit;
    end
    else begin
      for i := 0 to AComponent.ComponentCount - 1 do begin
        if CompareText(AComponent.Components[i].ClassName, 'TXTabControl') = 0 then begin
          Result := TTabControl(AComponent.Components[i]);
          exit;
        end
        else begin
          Result := FindTabControl(AComponent.Components[i]);
          if Result <> Nil then
            exit;
        end;              
      end;
    end;
  end;

begin
  NTAServices := BorlandIDEServices as INTAServices40;

  EditorServices := BorlandIDEServices as IOTAEditorServices;
  EditView := EditorServices.TopView;

  if Assigned(EditView) then begin
    TabControl := FindTabControl(EditView.GetEditWindow.Form);
    Assert(TabControl <> Nil, 'TabControl not found');
    EditorPopUpMenu := TabControl.PopupMenu;
    Assert(EditorPopUpMenu <> Nil, 'PopUP menu not found');
    //EditorPopUpMenu := TPopUpMenu(EditView.GetEditWindow.Form.FindComponent('EditorLocalMenu'));
    Assert(EditorPopUpMenu <>Nil);

    IDEMenuHandler := TIDEMenuHandler.Create;
    MenuItem := TMenuItem.Create(Nil);
    MenuItem.Caption := 'Added IDE editor menu item';
    MenuItem.OnClick := IDEMenuHandler.HandleClick;
    EditorPopUpMenu.Items.Add(MenuItem)
  end
  else
    ShowMessage('No editor active');
end;

【讨论】:

感谢你们,我现在一切正常。选项卡的上下文菜单的名称实际上是“ModuleMenu”,以防有人想按名称搜索组件。

以上是关于使用 ToolsAPI 将菜单项添加到 Delphi IDE 中单元的选项卡上下文菜单的主要内容,如果未能解决你的问题,请参考以下文章

php 使用类菜单 - 拇指将特色图像缩略图添加到菜单项的子项

仅针对特定文件类型将菜单项添加到 Windows 上下文菜单

将菜单添加到加载项中的 Visual Studio 菜单栏

将图标添加到引导下拉菜单项

需要将“活动”类添加到自定义 WordPress 导航菜单

如何将上下文菜单项添加到FlowDocumentScrollViewer内的textBox