简体   繁体   English

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

[英]Add menu item to unit's tab context menu in Delphi IDE using ToolsAPI

I am looking to find out which services/interface I need to use to add an item to the right-click menu of a source file in the Delphi IDE. 我正在寻找要在Delphi IDE中将项目添加到源文件的右键菜单中所需的服务/接口。

For example, if I right-click on a unit's tab, it has items to "Close page", "Close all other pages", "Properties", etc. I want to add custom items to that menu, if possible. 例如,如果我右键单击某个设备的选项卡,则其中包含“关闭页面”,“关闭所有其他页面”,“属性”等项目。如果可能,我想向该菜单添加自定义项目。

I looked over the ToolsAPI unit but I have no clue where to begin. 我查看了ToolsAPI单元,但不知道从哪里开始。 I assume there's an interface I can use to enumerate items and add items, but I dont know where to start looking. 我假设有一个可以用来枚举项目和添加项目的界面,但是我不知道从哪里开始寻找。

If that's not possible, I'd settle for the code editor's context menu. 如果那不可能,我将选择代码编辑器的上下文菜单。

Maybe there's some samples online for this, but I'm still looking and have found none. 也许网上有一些样品,但是我还在寻找,没有发现。

Any help appreciated. 任何帮助表示赞赏。

Remy Lebeau has pointed you in exactly the right directions with his link to the GExperts guide. 雷米·勒博(Remy Lebeau)指向GExperts指南的链接为您指明了正确的方向。

If you've not done this sort of stuff before, it can still be a bit of a performance to get started on writing your own IDE add-in, so I've set out below a minimal example of how to add an item to the code editor's pop-up menu. 如果您以前没有做过这种事情,那么开始编写自己的IDE加载项仍然会有一些性能,因此,我在下面提供了一个如何向其中添加项的最小示例。代码编辑器的弹出菜单。

What you do, obviously, is to create a new package, add the unit below to it, and then install the package in the IDE. 显然,您要做的是创建一个新程序包,向其添加下面的单元,然后在IDE中安装该程序包。 The call to Register in the unit does what's necessary to install the new item in the editor pop-up menu. 在单元中调用Register可以完成将新项目安装到编辑器弹出菜单中所需的操作。

Make sure that the code editor is open at the time you install the package. 在安装软件包时,请确保代码编辑器已打开。 The reason is that, as you'll see, the code checks whether there is an active editor at the time. 如您所见,原因是该代码检查当时是否有活动的编辑器。 I've left how to ensure that the pop-up item gets added even if there is no code editor active at the time. 我留下了如何确保即使当前没有活动的代码编辑器,也要添加弹出项的方法。 Hint: if you look at the ToolsAPI.Pas unit for whichever version of Delphi you're using, you'll find that it includes various kinds of notifier, and you can use a notification from at least one of them to defer checking if there is an editor active until one is likely to be. 提示:如果查看所使用的任何版本的Delphi的ToolsAPI.Pas单元,您会发现它包含各种通知程序,并且您可以使用至少其中之一的通知来推迟检查是否存在是活跃的编辑器,直到有可能成为可能为止。

Btw, the code adds the menu item to the context menu which pops up over the editor window itself rather than the active tab. 顺便说一句,该代码将菜单项添加到上下文菜单,该上下文菜单弹出编辑器窗口本身而不是活动选项卡。 Part of the fun with IDE add-ins is the fun of experimenting to see if you can get exactly what you want. IDE加载项的乐趣之一是尝试查看是否可以完全获得所需的乐趣。 I haven't tried it myself, but I doubt that adding the menu item to the context menu of one of the editor tabs would be that difficult - seeing as the Delphi IDE is a Delphi app, as you can see from the code below, you can use FindComponent (or just iterate over a Components collection) to find what you want. 我自己还没有尝试过,但是我怀疑将菜单项添加到一个编辑器选项卡的上下文菜单中会很困难-鉴于Delphi IDE是Delphi应用程序,如下面的代码所示,您可以使用FindComponent(或仅遍历Components集合)来查找所需的内容。 However, it is better, if you can, to locate things via the ToolsAPI interfaces. 但是,如果可以,最好通过ToolsAPI接口定位。 See Update below. 请参阅下面的更新

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.

Update: The following code finds the TabControl of the editor window and adds the menu item to its context menu. 更新:以下代码查找编辑器窗口的TabControl,并将菜单项添加到其上下文菜单。 However, note that it does not account for there being a second editor window open. 但是,请注意,这并不意味着打开了第二个编辑器窗口。

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM