使用 ToolsAPI 在 Delphi IDE 中将菜单项添加到单元的选项卡上下文菜单
Add menu item to unit's tab context menu in Delphi IDE using ToolsAPI
我想知道我需要使用哪个 services/interface 来将项目添加到 Delphi IDE 中源文件的右键菜单。
例如,如果我右键单击一个单位的选项卡,它有 "Close page"、"Close all other pages"、"Properties" 等项目。我想向其中添加自定义项目菜单,如果可能的话。
我查看了 ToolsAPI 单元,但不知道从哪里开始。我假设有一个界面可以用来枚举项目和添加项目,但我不知道从哪里开始寻找。
如果那不可能,我会选择代码编辑器的上下文菜单。
也许网上有一些示例,但我仍在寻找并找到了 none。
感谢任何帮助。
Remy Lebeau 用他的 link 为您指明了正确的方向
GExperts 指南。
如果你以前没有做过这种东西,它仍然可以
开始编写您自己的 IDE 加载项有点性能,所以
我在下面列出了如何将项目添加到代码编辑器的最小示例
弹出式菜单。
显然,您要做的是创建一个新包,将下面的单元添加到其中,
然后在 IDE 中安装软件包。单元内对Register
的调用
执行在编辑器弹出菜单中安装新项目所需的操作。
确保在安装包时代码编辑器处于打开状态。这
原因是,如您所见,代码检查是否有活动的编辑器
当时。我已经离开了如何确保即使有弹出项也被添加
当时没有代码编辑器处于活动状态。提示:如果您查看 ToolsAPI.Pas 单位
您正在使用的 Delphi 版本,您会发现它包含各种通知程序,
并且您可以使用其中至少一个的通知来推迟检查是否存在
一位编辑是否活跃,直到有可能成为一位编辑。
顺便说一下,代码将菜单项添加到上下文菜单中,该菜单在编辑器 window 本身而不是活动选项卡上弹出。使用 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.
更新: 以下代码找到编辑器 window 的 TabControl 并将菜单项添加到其上下文菜单中。但是,请注意,它没有考虑到有第二个编辑器 window 打开。
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;
我想知道我需要使用哪个 services/interface 来将项目添加到 Delphi IDE 中源文件的右键菜单。
例如,如果我右键单击一个单位的选项卡,它有 "Close page"、"Close all other pages"、"Properties" 等项目。我想向其中添加自定义项目菜单,如果可能的话。
我查看了 ToolsAPI 单元,但不知道从哪里开始。我假设有一个界面可以用来枚举项目和添加项目,但我不知道从哪里开始寻找。
如果那不可能,我会选择代码编辑器的上下文菜单。
也许网上有一些示例,但我仍在寻找并找到了 none。
感谢任何帮助。
Remy Lebeau 用他的 link 为您指明了正确的方向 GExperts 指南。
如果你以前没有做过这种东西,它仍然可以 开始编写您自己的 IDE 加载项有点性能,所以 我在下面列出了如何将项目添加到代码编辑器的最小示例 弹出式菜单。
显然,您要做的是创建一个新包,将下面的单元添加到其中,
然后在 IDE 中安装软件包。单元内对Register
的调用
执行在编辑器弹出菜单中安装新项目所需的操作。
确保在安装包时代码编辑器处于打开状态。这 原因是,如您所见,代码检查是否有活动的编辑器 当时。我已经离开了如何确保即使有弹出项也被添加 当时没有代码编辑器处于活动状态。提示:如果您查看 ToolsAPI.Pas 单位 您正在使用的 Delphi 版本,您会发现它包含各种通知程序, 并且您可以使用其中至少一个的通知来推迟检查是否存在 一位编辑是否活跃,直到有可能成为一位编辑。
顺便说一下,代码将菜单项添加到上下文菜单中,该菜单在编辑器 window 本身而不是活动选项卡上弹出。使用 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.
更新: 以下代码找到编辑器 window 的 TabControl 并将菜单项添加到其上下文菜单中。但是,请注意,它没有考虑到有第二个编辑器 window 打开。
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;