Добавить пункт меню в контекстное меню вкладки устройства в Delphi IDE с помощью ToolsAPI

Я ищу, чтобы выяснить, какие сервисы / интерфейс мне нужно использовать для добавления элемента в контекстное меню исходного файла в Delphi IDE.

Например, если я щелкну правой кнопкой мыши на вкладке устройства, у него есть пункты "Закрыть страницу", "Закрыть все другие страницы", "Свойства" и т. Д. Я хочу добавить пользовательские элементы в это меню, если это возможно.

Я просмотрел блок ToolsAPI, но понятия не имею, с чего начать. Я предполагаю, что есть интерфейс, который я могу использовать для перечисления элементов и добавления элементов, но я не знаю, с чего начать.

Если это невозможно, я бы согласился на контекстное меню редактора кода.

Может быть, есть несколько примеров в Интернете для этого, но я все еще ищу и не нашел ни одного.

Любая помощь приветствуется.

1 ответ

Решение

Реми Лебо указал вам в правильных направлениях своей ссылкой на руководство GExperts.

Если вы еще не делали такого рода вещи раньше, то, возможно, начнете писать собственную надстройку для IDE, и это может быть чем-то вроде производительности, поэтому ниже я приведу минимальный пример того, как добавить элемент в всплывающее меню редактора кода.

Очевидно, что вы делаете, чтобы создать новый пакет, добавить нижеприведенный модуль и затем установить пакет в IDE. Призыв к Register в модуле делает все необходимое для установки нового пункта во всплывающем меню редактора.

Убедитесь, что редактор кода открыт во время установки пакета. Причина в том, что, как вы увидите, код проверяет, есть ли активный редактор в данный момент. Я оставил, как обеспечить добавление всплывающего элемента, даже если в данный момент нет активного редактора кода. Подсказка: если вы посмотрите на модуль ToolsAPI.Pas для какой-либо версии Delphi, которую вы используете, вы обнаружите, что он включает в себя различные виды уведомлений, и вы можете использовать уведомление хотя бы от одного из них, чтобы отложить проверку, если есть Является ли редактор активным до тех пор, пока он, вероятно, не будет.

Кстати, код добавляет пункт меню в контекстное меню, которое всплывает над окном редактора, а не на активной вкладке. Часть удовольствия с надстройками IDE - это удовольствие от экспериментов, чтобы увидеть, сможете ли вы получить именно то, что вы хотите. Я сам не пробовал, но сомневаюсь, что добавить пункт меню в контекстное меню одной из вкладок редактора было бы очень сложно - поскольку Delphi IDE является приложением Delphi, как вы можете видеть из приведенного ниже кода, Вы можете использовать FindComponent (или просто перебрать коллекцию компонентов), чтобы найти то, что вы хотите. Тем не менее, лучше, если вы можете найти вещи через интерфейсы 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;
Другие вопросы по тегам