Adding an Item to the Main Menu of the IDE

From RAD Studio
Jump to: navigation, search

Go Up to Using Native IDE Objects


You can use the INTAServices Native Tools API interface to extend the main menu of the IDE with your own menu entries.

Adding an Item to the Main Menu

To add an instance of TMenuItem to the main menu of the IDE:

  1. Create your instance of TMenuItem with the main menu object as parent. The main menu object is the MainMenu property of the BorlandIDEServices variable casted as INTAServices.
  2. Configure your menu item. For example:
  3. Call AddActionMenu on the BorlandIDEServices variable casted as INTAServices, and provide the following parameters:
    1. A string with the name of an existing menu item of the main menu of the IDE, such as "ToolsMenu" or "HelpMenu".
    2. This parameter adds the specified action to the action list of the IDE. If your menu item has an action, you may provide it here to add it to the action list of the IDE. Otherwise, provide a nil value.
    3. Your menu item object.

Delphi:

if Supports(BorlandIDEServices, INTAServices, NTAServices) then
begin
  MyMenuItem := TMenuItem.Create(nil);
  MyMenuItem.Caption := 'My Menu Item';
  NTAServices.AddActionMenu('ToolsMenu', nil, MyMenuItem);
end;

C++:

_di_INTAServices NTAServices;
if (BorlandIDEServices->Supports(NTAServices)) {
  MyMenuItem = new TMenuItem(NULL);
  MyMenuItem->Caption = "My Menu Item";
  NTAServices->AddActionMenu("ToolsMenu", NULL, MyMenuItem);
}

AddActionMenu adds your menu item after the existing menu item that has the specified name. You can also place your menu in a different location relative to the specified existing menu item, either to the left-hand side of the menu item or as a child of the menu item.

You must also remember to release your menu item object when your package is unloaded.

Finding the Name of an Existing Main Menu Item

In order to be able to add a menu item to the main menu of the IDE, you need to know the name of an existing menu item.

To find the name of an existing menu item, you can implement the following procedure in your package:

Delphi:

type
  TMenuBreadcrumbs = array of String;

procedure FindMenuItem(AMenuBreadcrumbs: TMenuBreadcrumbs);

  procedure IterateMenuItems(MenuItems: TMenuItem);
  var
    I, J: Integer;
    ArrayLength: Cardinal;
    Caption: String;
  begin
    for I := 0 To MenuItems.Count - 1 do
    begin
      Caption := StringReplace(MenuItems[I].Caption, '&', '', []);
      if Uppercase(AMenuBreadcrumbs[0]) = Uppercase(Caption) then
      begin
        ArrayLength := Length(AMenuBreadcrumbs);
        if ArrayLength = 1 then
          ShowMessage(MenuItems[I].Name)
        else
        begin
          for J := 1 to ArrayLength - 1 do
            AMenuBreadcrumbs[J - 1] := AMenuBreadcrumbs[J];
          SetLength(AMenuBreadcrumbs, ArrayLength - 1);
          IterateMenuItems(MenuItems.Items[I]);
        end;
        break;
      end;
    end;
  end;

var
  NTAServices: INTAServices;
begin
  if Supports(BorlandIDEServices, INTAServices, NTAServices) then
    IterateMenuItems(NTAServices.MainMenu.Items);
end;

C++:

void IterateMenuItems(TMenuItem* MenuItems,
                      DynamicArray<UnicodeString> &AMenuBreadcrumbs) {
  for (int i = 0; i < MenuItems->Count; i++) {
    UnicodeString Caption = StringReplace(
      MenuItems->Items[i]->Caption, "&", "", TReplaceFlags());
    if (AMenuBreadcrumbs[0].UpperCase() == Caption.UpperCase()) {
      int ArrayLength = AMenuBreadcrumbs.Length;
      if (ArrayLength == 1)
        ShowMessage(MenuItems->Items[i]->Name);
      else {
        for (int j = 1; j < ArrayLength; j++)
          AMenuBreadcrumbs[j - 1] = AMenuBreadcrumbs[j];
        AMenuBreadcrumbs.Length = ArrayLength - 1;
        IterateMenuItems(MenuItems->Items[i], AMenuBreadcrumbs);
      }
      break;
    }
  }
}

void FindMenuItems(DynamicArray<UnicodeString> AMenuBreadcrumbs) {
  _di_INTAServices NTAServices;
  if (BorlandIDEServices->Supports(NTAServices)) {
      IterateMenuItems(NTAServices->MainMenu->Items, AMenuBreadcrumbs);
  }
}

Then call FindMenuItem in the initialization of your package, passing to it an array with the captions that lead to the target menu entry.

For example, to find the name of the File > Open From Version Control... menu item, call FindMenuItem as follows:

Delphi:

FindMenuItem(['File', 'Open From Version Control...']);

C++:

FindMenuItems(DynamicArray<UnicodeString>(
  "File", "Open From Version Control..."););

When you install a package with this call in the IDE, a dialog box shows the name of the specified menu, such as "OpenFromRepository1".

You should only use this function during the development of your IDE extension to find out specific menu item names. Because your users may run the IDE in a language other than English, your final package should not rely on this function, but instead specify the actual name of the target menu item that you found during development:

Delphi:

NTAServices.AddActionMenu('OpenFromRepository1', nil, MyMenuItem);

C++:

NTAServices->AddActionMenu("OpenFromRepository1", NULL, MyMenuItem);

Specifying a Different Relative Location for Your Menu Item

By default, AddActionMenu adds your menu item on the right-hand side of the specified existing menu item, but you can use some optional parameters to change this behavior.

To place your menu item on the left-hand side of the specified existing menu item, pass False as the fourth parameter:

Delphi:

NTAServices.AddActionMenu('OpenFromRepository1', nil, MyMenuItem, False);

C++:

NTAServices->AddActionMenu("OpenFromRepository1", NULL, MyMenuItem, false);

To place your menu item within the specified existing menu item, as a child menu item, pass True as the fifth parameter (the value of the fourth parameter does not matter):

Delphi:

NTAServices.AddActionMenu('OpenFromRepository1', nil, MyMenuItem, False, True);

C++:

NTAServices->AddActionMenu("OpenFromRepository1", NULL, MyMenuItem, false, true);

See Also