Utiliser l'OTA (Open Tools API) de Borland Developer Studio 2006

Dans ce tutoriel, je vais vous montrer comment démarrer simplement un projet vous permettant de créer vos propres extensions à l'environnement de développement BDS.

L'architecture permettant de le faire s'appelle OTA (Open Tools API). BDS 2006 fournit deux OTA. Autourd'hui, nous n'utiliserons que l'OTA accessible en .NET. On pourrait par conséquent écrire ces extensions aussi bien en Delphi pour .NET qu'en C#. Nous ne ferons que du langage Delphi pour .NET dans ce tutoriel.

Ce document regroupe un ensemble d'informations que j'ai collectées à travers de nombreux sites web et j'essaye d'être le plus didactique possible en expliquant chacune des étapes à effectuer pour ne pas rencontrer de problème.

Article lu   fois.

Les deux auteurs

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Affichage d'une boite de dialogue de message au démarrage de l'EDI

Lancer BDS 2006, Delphi pour Microsoft .NET Framework.

Créer une nouvelle bibliothèque, en cliquant sur :

  • Menu Fichier/Nouveau/Autre...
  • Projets Delphi pour .NET
  • Bibliothèque
Création d'une bibliothèque

Sauvegarder le projet (pas de parenthèse dans le chemin)

Ajouter l'assemblage (assembly) pour accéder à l'OTA :

  • Menu Projet/Ajouter une référence...
  • Choisir l'assemblage : Borland.Studio.ToolsAPI
    • Si vous ne le trouvez pas, cliquez sur le bouton Parcourir...
    • Choisissez le fichier Borland.Studio.ToolsAPI.dll du répertoire bin de votre installation de BDS.
  • Cliquez sur le bouton OK.
Ajout d'une référence

Modifions le code pour que l'extension que nous avons créée fasse quelque chose :

  • Ajoutons une nouvelle classe avec une procédure bien spécifique :
     
    Sélectionnez
    
    [assembly: ComVisible(False)]
    //[assembly: Guid('')]
    //[assembly: TypeLibVersion(1, 0)]
    
    type
      TMyFirstAddIn = class
      public
        class procedure IDERegister; static;
      end;
    
    { TMyFirstAddIn }
    
    class procedure TMyFirstAddIn.IDERegister;
    begin
      MessageBox.Show('Hello World !');
    end;
    
    begin
    end.
    
  • Les assemblages .NET publient leur structure ce qui permet aux autres applications de facilement découvrir les fonctions et procédures qu'ils contiennent. BDS va se livrer à l'introspection de ses extensions pour en rechercher une procédure IDERegister, puis l'exécuter lorsqu'il l'aura trouvée.
  • La classe MessageBox utilisée est contenue dans l'espace de noms : System.Windows.Forms (que l'on doit donc ajouter au uses de la bibliothèque).
  • On peut ensuite sauvegarder son code et compiler son projet.

Maintenant, il faut que BDS charge cette nouvelle extension lorsqu'il se lance. Pour cela, il faut ajouter une nouvelle clé dans la base de registre :

  • Lancez l'Editeur du Registre :
    • Menu Démarrer/Exécuter... (ou touche Windows + R)
    • Tapez regedit puis cliquez sur OK
  • Parcourez l'arborescence pour aller sur la clé : HKEY_CURRENT_USER\Software\Borland\BDS\4.0\Known IDE Assemblies (4.0 correspond à BDS 2006, 3.0 pour 2005, ...)
  • Créez une nouvelle valeur chaîne et donnez-lui comme nom le chemin complet pour accéder à la DLL que nous venons de compiler. La valeur de la donnée par elle-même est sans importance mais ne doit pas être vide.
    Ajout d'une clé de registre
  • Quittez BDS et relancez-le : Lors du chargement, le message Hello World ! apparaît...
Le message Hello World apparaît
Si vous souhaitez télécharger les fichiers du projet
Télécharger
miroir
 
Pour visualiser en ligne la vidéo de la création de ce projet
Visualiser
 

Nous avons ainsi réussi à créer notre première extension. Maintenant, nous allons essayer d'en faire une à peine plus complexe : La même mais où le Hello World sera affiché à partir d'un menu.

II. Créer un nouvel élément de menu dans l'EDI

Nous allons donc créer une nouvelle bibliothèque comme nous l'avons précédemment fait.

Nous lui ajoutons également la référence à l'assemblage Borland.Studio.ToolsAPI.

Puis nous créons une nouvelle classe.

Création d'une nouvelle classe

Cette classe va contenir notre nouvelle extension. Elle hérite directement d'un TObject et implémente l'interface de l'OTA IOTAMenuWizard qui impose des propriétés permettant de récupérer le texte du menu, son nom, ...

Pour cela, on va modifier le code généré par BDS.

Pour commencer, on va utiliser les espaces de noms suivants :

 
Sélectionnez

uses
  Borland.Studio.ToolsAPI,
  System.Windows.Forms;

Puis faire la déclaration ainsi :

 
Sélectionnez

type
  TExtensionSimpleOTA = class(TObject, IOTAMenuWizard)
  strict private
    procedure CreateWizardService;
  private
    { Déclarations privées }
  public
    constructor Create;
    procedure   Execute;
    procedure   Destroyed;

    class procedure IDERegister; static;

    function FGetIDString : String;
    function FGetName     : String;
    function FGetMenuText : String;
    function FGetEnabled  : Boolean;
    function FGetChecked  : Boolean;

    property IDString     : String read FGetIDString;
    property Name         : String  read FGetName;
    property MenuText     : String  read FGetMenuText;
    property Enabled      : Boolean read FGetEnabled;
    property Checked      : Boolean read FGetChecked;
  end;

implementation

On remarque que l'on retrouve comme dans le premier exemple la procédure qui permet à BDS d'enregistrer l'extension, IDERegister. Celle-ci va créer une instance de l'extension.

Dans le constructor de l'extension, on va faire appel à la procédure qui permet d'ajouter un nouvel expert à l'environnement, qui dans notre cas, sera un menu supplémentaire.

La procédure Execute sera quant à elle appelée lorsque l'on cliquera sur le menu et devra donc afficher le message Hello World.

L'implémentation ressemblera donc à ceci :

 
Sélectionnez

implementation

class procedure TExtensionSimpleOTA.IDERegister;
begin
  TExtensionSimpleOTA.Create;
end;

constructor TExtensionSimpleOTA.Create;
begin
  inherited Create;
  // TODO: Ajouter ici le code du constructeur
  CreateWizardService;
end;

procedure TExtensionSimpleOTA.CreateWizardService;
var
  WizardService: IOTAWizardService;
begin
  WizardService := BorlandIDE.GetService(typeof(IOTAWizardService)) as IOTAWizardService;
  WizardService.AddWizard(Self);
end;

procedure TExtensionSimpleOTA.Execute;
begin
  MessageBox.Show('Hello World à partir du menu que l''on a créé !');
end;

procedure TExtensionSimpleOTA.Destroyed;
begin
  // Rien à faire : Le ramasse-miette s'en chargera...
end;

function TExtensionSimpleOTA.FGetChecked: Boolean;
begin
  Result := False;
end;

function TExtensionSimpleOTA.FGetEnabled: Boolean;
begin
  Result := True;
end;

function TExtensionSimpleOTA.FGetIDString: String;
begin
  Result := 'ExtensionSimpleOTA';
end;

function TExtensionSimpleOTA.FGetMenuText: String;
begin
  Result := 'Exécuter ma nouvelle extension !';
end;

function TExtensionSimpleOTA.FGetName: String;
begin
  Result := 'Extension simple via OTA';
end;

end.

Ensuite, il suffit de sauvegarder et de compiler son projet.

Puis on ajoute dans la base de registre l'appel à notre nouvelle extension (DLL).

On obtient ainsi un nouveau menu :

Nouveau menu

Ce menu nous affiche effectivement le message que nous avons codé :

affichage du menu
Si vous souhaitez télécharger les fichiers du projet
Télécharger
miroir

Maintenant, lors du chargement de BDS, vous avez remarqué que certaines extensions affichent un logo lorsqu'elles-mêmes sont chargées. Nous allons maintenant voir comment procéder pour faire la même chose.

III. Affichage de l'extension dans l'écran de démarrage de l'EDI (Splash screen)

Tout d'abord, nous allons avoir besoin d'une ressource image. Pour la créer, nous allons utiliser l'application Démo fournie avec BDS, ResXBuilder qui se trouve dans le répertoire : <BDS>\Demos\Delphi.Net\WinForms\ResXBuilder\

L'image doit faire une taille de 24x24.

Une fois le projet ResXBuilder ouvert, nous créons un nouveau fichier :

  • Menu File/New

Puis nous ajoutons une ressource de type Bitmap :

  • Menu Resources/Add/Bitmap...
  • Choisir le fichier voulu et cliquer sur Ouvrir

Puis nous sauvegardons notre fichier :

  • Menu File/Save

Ensuite, nous ouvrons notre projet précédent pour le modifier afin qu'il utilise notre logo fraîchement créé.

Nous ajoutons le logo à notre projet :

  • Menu Projet/Ajouter au projet... (ou Maj + F11)
  • Nous choisissons le type de fichier Ressources (*.resx)
  • Nous cliquons sur le fichier créé avec le projet ResXBuilder et sur le bouton Ouvrir.

Après, nous modifions notre code pour qu'il utilise cette nouvelle ressource, en ajoutant une nouvelle procédure qui va être appelée à partir du constructor. Comme cette procédure va utiliser des espaces de noms particuliers, nous allons tout d'abord les ajouter :

 
Sélectionnez

uses
  Borland.Studio.ToolsAPI,
  System.Windows.Forms,
  System.Drawing,
  System.Resources,
  System.Reflection;

Puis, nous ajoutons la déclaration de la nouvelle procédure :

 
Sélectionnez

strict private
  procedure CreateWizardService;
  procedure CreateSplashImage;
private

L'appel de cette procédure dans le constructor :

 
Sélectionnez

constructor TExtensionSimpleOTA.Create;
begin
  inherited Create;
  // TODO: Ajouter ici le code du constructeur
  CreateSplashImage;
  CreateWizardService;
end;

Et enfin, l'implémentation de la procédure :

 
Sélectionnez

procedure TExtensionSimpleOTA.CreateSplashImage;
var
  bmp                 : System.Drawing.Bitmap;
  SplashScreenService : IOTASplashScreenService;
  lAssembly           : System.Reflection.Assembly;
  leResourceManager   : System.Resources.ResourceManager;
begin
  // Récupération du service pour la splash
  SplashScreenService := BorlandIDE.GetService(typeof(IOTASplashScreenService)) as IOTASplashScreenService;

  // Récupération de l'assemblage courant
  lAssembly := GetType().Assembly;

  // Récupération du gestionnaire de ressources
  leResourceManager := System.Resources.ResourceManager.Create('whiler', lAssembly);

  // Récupération de l'image que nous avons créé (attention, sensible à la casse)
  bmp := System.Drawing.Bitmap(leResourceManager.GetObject('whiler.bmp'));

  // Ajout de l'image
  SplashScreenService.AddPluginBitmap('Simple extension via l''OTA', bmp.GetHbitmap, False, 'Free', '1.0');
end;

On remarque sur la capture ci-dessous l'emplacement des textes des différents paramètres :

Image non disponible
Splash screen
Si vous souhaitez télécharger les fichiers du projet
Télécharger
miroir

IV. Affichage de l'extension dans la fenêtre A propos de...

L'architecture ouverte que nous sommes en train d'utiliser a été conçue pour permettre à des éditeurs tiers de créer des extensions. De la même façon que nous avons ajouté des informations sur l'écran de démarrage (splash screen), nous allons maintenant ajouter des informations dans la fenêtre A propos de... de BDS.

Pour cela nous allons faire presque la même chose que pour la splash. L'image utilisée peut faire une taille de 32x32.

Nous créons une nouvelle procédure CreateAboutInfos que nous appelons à partir du constructor et que nous implémentons :

Déclaration de la nouvelle procédure :

 
Sélectionnez

strict private
  procedure CreateWizardService;
  procedure CreateSplashImage;
  procedure CreateAboutInfos;
private

L'appel de cette procédure dans le constructor :

 
Sélectionnez

constructor TExtensionSimpleOTA.Create;
begin
  inherited Create;
  // TODO: Ajouter ici le code du constructeur
  CreateSplashImage;
  CreateAboutInfos;
  CreateWizardService;
end;

Et enfin, l'implémentation de la procédure :

 
Sélectionnez

procedure TExtensionSimpleOTA.CreateAboutInfos;
var
  bmp                 : System.Drawing.Bitmap;
  AboutBoxService     : IOTAAboutBoxService;
  lAssembly           : System.Reflection.Assembly;
  leResourceManager   : System.Resources.ResourceManager;
begin
  // Récupération du service pour le About
  AboutBoxService:= BorlandIDE.GetService(typeof(IOTAAboutBoxService)) as IOTAAboutBoxService;

  // Récupération de l'assemblage courant
  lAssembly := GetType().Assembly;

  // Récupération du gestionnaire de ressources
  leResourceManager := System.Resources.ResourceManager.Create('whiler', lAssembly);

  // Récupération de l'image que nous avons créé (attention, sensible à la casse)
  bmp := System.Drawing.Bitmap(leResourceManager.GetObject('about.bmp'));
  // On met le fond de l'image transparent
  bmp.MakeTransparent;

  // Ajout de l'image
  AboutBoxService.AddPluginInfo('Extension via l''OTA', 'Un exemple simple', bmp.GetHbitmap, False, 'Free', '1.0');
end;

On obtient ainsi :

A propos de...
Si vous souhaitez télécharger les fichiers du projet
Télécharger
miroir

V. Création d'un élément de menu totalement personnalisé

Précédemment, nous avons vu comment ajouter un nouvel élément au menu d'Aide. Or, lorsque l'on crée une extension, on peut vouloir la voir apparaître dans un autre élément de la barre de menu. Nous allons maintenant voir comment placer notre menu ailleurs.

Pour cela, nous n'allons plus utiliser l'interface IOTAMenuWizard, mais l'interface IOTAMainMenuService.

Pour cela nous allons encore créer un nouveau projet de type bibliothèque.

Ajouter la référence sur l'API : Borland.Studio.ToolsAPI.dll

Ajouter au projet la ressource qui contient les images à afficher (logo, icône, ...)

Créer une nouvelle classe et sauvegarder tout le projet.

Dans la nouvelle unité que j'ai nommée ExtensionBody, nous allons remettre le code nécessaire que nous avons vu dans les exemples précédents (Attention aux retours à la ligne si vous copiez/collez tout le bloc) :

 
Sélectionnez

unit ExtensionBody;

interface

uses
  Borland.Studio.ToolsAPI,
  System.Windows.Forms,
  System.Drawing,
  System.Resources,
  System.Reflection;
type
  TExtensionOTA = class
  strict private
    procedure CreateSplashImage;
    procedure CreateAboutInfos;
  private
  public
    constructor Create;
    procedure Destroyed;
    class procedure IDERegister; static;
  end;

implementation

class procedure TExtensionOTA.IDERegister;
begin
  TExtensionOTA.Create;
end;

constructor TExtensionOTA.Create;
begin
  inherited Create;
  CreateSplashImage;
  CreateAboutInfos;
end;

procedure TExtensionOTA.CreateAboutInfos;
var
  bmp               : System.Drawing.Bitmap;
  AboutBoxService   : IOTAAboutBoxService;
  lAssembly         : System.Reflection.Assembly;
  leResourceManager : System.Resources.ResourceManager;
begin
  // Récupération de l'assemblage courant
  lAssembly := GetType().Assembly;

  // Récupération du gestionnaire de ressources {$R 'whiler.resources' 'whiler.resx'} le nom situé avant .resources
  leResourceManager := System.Resources.ResourceManager.Create('whiler', lAssembly);

  // Récupération de l'image que nous avons créé (attention, sensible à la casse)
  bmp := System.Drawing.Bitmap(leResourceManager.GetObject('about.bmp'));
  bmp.MakeTransparent;

  // Récupération du service pour la fenêtre A propos de...
  AboutBoxService := BorlandIDE.GetService(typeof(IOTAAboutBoxService)) as IOTAAboutBoxService;

  // Ajout de l'image
  AboutBoxService.AddPluginInfo('Autre extension via l''OTA', 'Un autre exemple', bmp.GetHbitmap, True, 'Free', '1.0');
end;

procedure TExtensionOTA.CreateSplashImage;
var
  bmp                 : System.Drawing.Bitmap;
  SplashScreenService : IOTASplashScreenService;
  lAssembly           : System.Reflection.Assembly;
  leResourceManager   : System.Resources.ResourceManager;
begin
  // Récupération de l'assemblage courant
  lAssembly := GetType().Assembly;

  // Récupération du gestionnaire de ressources {$R 'whiler.resources' 'whiler.resx'} le nom situé avant .resources
  leResourceManager := System.Resources.ResourceManager.Create('whiler', lAssembly);

  // Récupération de l'image que nous avons créé (attention, sensible à la casse)
  bmp := System.Drawing.Bitmap(leResourceManager.GetObject('whiler.bmp'));

  // Récupération du service pour la splash
  SplashScreenService := BorlandIDE.GetService(typeof(IOTASplashScreenService)) as IOTASplashScreenService;

  // Ajout de l'image
  SplashScreenService.AddPluginBitmap('Autre extension via l''OTA', bmp.GetHbitmap, True, 'Free', '1.0');
end;

procedure TExtensionOTA.Destroyed;
begin
  // Rien à faire : Le ramasse-miette s'en chargera...
end;

end.

Nous pouvons normalement compiler le projet, sauf si des fautes de frappe se sont immiscées dans notre code.

Dans l'état actuel, cette nouvelle extension s'affiche lors du chargement de BDS et est également présente dans la fenêtre A Propos De... Mais elle ne fait rien de plus.

Nous allons donc créer une procédure permettant d'ajouter un menu qui lui-même permettra d'appeler une autre procédure qui exécutera le code que l'on souhaite.

Donc, nous déclarons une procédure CreateMainMenuItem ainsi :

 
Sélectionnez

  strict private
    procedure CreateSplashImage;
    procedure CreateAboutInfos;
    procedure CreateMainMenuItem;
  private

Dans son implémentation, nous allons récupérer l'icône à afficher (16x16), ajouter le nouvel élément de menu en spécifiant son emplacement par rapport à l'emplacement d'un élément de menu déjà existant.

 
Sélectionnez

procedure TExtensionOTA.CreateMainMenuItem;
var
  MainMenuService   : IOTAMainMenuService;
  menuItem          : IOTAMenuItem;
  bmp               : System.Drawing.Bitmap;
  lAssembly         : System.Reflection.Assembly;
  leResourceManager : System.Resources.ResourceManager;
begin
  // Récupération de l'assemblage courant
  lAssembly := GetType().Assembly;

  // Récupération du gestionnaire de ressources {$R 'whiler.resources' 'whiler.resx'} le nom situé avant .resources
  leResourceManager := System.Resources.ResourceManager.Create('whiler', lAssembly);

  // Récupération de l'image que nous avons créé (attention, sensible à la casse)
  bmp := System.Drawing.Bitmap(leResourceManager.GetObject('menu.bmp'));
  bmp.MakeTransparent;

  // Récupération du service pour la barre de menu
  MainMenuService := BorlandIDE.GetService(typeof(IOTAMainMenuService)) as IOTAMainMenuService;

  // Ajout de l'élément de menu
  menuItem := MainMenuService.AddMenuItem(
                MainMenuService.GetFirstMenuItem.Name,
                OTAMenuItemLocation.otamlBefore, 
                'Autre ExtensionOTA', 
                'Extension via l''OTA', 
                bmp.GetHbitmap
              );
end;

Il faut juste faire appel à cette procédure dans le constructor, et nous aurons un nouvel élément de menu.

 
Sélectionnez

constructor TExtensionOTA.Create;
begin
  inherited Create;
  CreateSplashImage;
  CreateAboutInfos;
  CreateMainMenuItem;
end;

Par contre, nous n'avons pas encore spécifié ce que cet élément devait faire lorsque l'on clique dessus.

Pour cela, on crée une nouvelle procédure qui sera appelée lorsque l'on cliquera sur l'élément de menu :

Sa déclaration :

 
Sélectionnez

  public
    constructor Create;
    procedure Destroyed;
    class procedure IDERegister; static;
    procedure MenuItemExecuted(sender: TObject ; e: EventArgs);
  end;

Son implémentation :

 
Sélectionnez

procedure TExtensionOTA. MenuItemExecuted(sender: TObject ; e: EventArgs);
begin
  MessageBox.Show('Hello World !');
end;

Et on modifie la procédure CreateMainMenuItem pour que celle-ci spécifie l'utilisation de cette procédure :

 
Sélectionnez

  // Ajout de l'élément de menu
  menuItem := MainMenuService.AddMenuItem('ViewDebugItem', OTAMenuItemLocation.otamlBefore, 'Simple ExtensionOTA', 'Extension via l''OTA', bmp.GetHbitmap);

  // Procédure à exécuter lorsque l'élément est cliqué
  Include(menuItem.Executed, MenuItemExecuted);
end;

Et puisque l'extension que vous allez créer sera très utile, vous allez vouloir lui affecter un raccourci clavier. Pour l'ajouter, il suffit simplement de modifier une nouvelle fois la procédure CreateMainMenuItem pour lui ajouter le raccourci choisi :

 
Sélectionnez

  // Ajout de l'élément de menu
  menuItem := MainMenuService.AddMenuItem('ViewDebugItem', OTAMenuItemLocation.otamlBefore, 'Simple ExtensionOTA', 'Extension via l''OTA', bmp.GetHbitmap);

  // Ajout du raccourci clavier
  menuItem.Shortcut := Shift or Control or Alt or ord('W');

  // Procédure à exécuter lorsque l'élément est cliqué
  Include(menuItem.Executed, MenuItemExecuted);
end;

Où, shift, control et alt sont des constantes avec les valeurs suivantes :

 
Sélectionnez

const
  Shift   = $2000;
  Control = $4000;
  Alt     = $8000;

On peut ensuite compiler son projet, ajouter le chemin de la DLL dans la base de registre et relancer son BDS pour voir et tester son nouveau menu :

Menu
Hello Word
Si vous souhaitez télécharger les fichiers du projet
Télécharger
miroir

VI. Utilisation de la fenêtre de messages de BDS

Dans notre exemple, nous avons inséré notre menu en première position. Pour le placer ailleurs, il faut connaître le nom des autres éléments déjà existant.

Nous allons modifier notre code pour avoir ces noms et non plus un simple Hello World !

Nous commençons par ajouter trois unités que nous allons utiliser :

 
Sélectionnez

uses
  Borland.Studio.ToolsAPI,
  System.Windows.Forms,
  System.Drawing,
  System.Resources,
  System.Reflection,
  Borland.Vcl.Classes,
  Borland.Vcl.StrUtils,
  Borland.Vcl.Clipbrd;

Classes pour stocker les différents menus dans un TStringList, StrUtils pour gérer mon indentation par niveau et Clipbrd pour stocker le résultat dans le presse-papier.

Ensuite, nous créons une fonction qui parcourra récursivement les différents niveaux.

Sa déclaration :

 
Sélectionnez

type
  TExtensionOTA = class
  strict private
    procedure CreateSplashImage;
    procedure CreateAboutInfos;
  private
    function GetItems(root: IOTAMenuItem; level: Integer): TStringList;
  public

Son implémentation :

 
Sélectionnez

function TExtensionOTA.GetItems(root: IOTAMenuItem; level: Integer): TStringList;
var
  nextMenuItem : IOTAMenuItem;
  loop, max    : Integer;
begin
  Result := TStringList.Create;

  Result.Add(DupeString('- - ', level) + root.Name + ' | ' + root.Text);

  // Parcours des sous-menus...
  max := root.ChildCount - 1;
  for loop := 0 to max do
  begin
    result.AddStrings(GetItems(root.ChildMenuItem(loop), level+1));
  end;

  // Menu suivant...
  nextMenuItem := root.NextMenuItem;
  if (nextMenuItem <> nil) then
  begin
    result.AddStrings(GetItems(nextMenuItem, level));
  end;
end;

Puis nous modifions la procédure MenuItemExecuted pour récupérer la liste des menus :

 
Sélectionnez

procedure TExtensionOTA.MenuItemExecuted(sender: TObject; e: EventArgs);
var
  MainMenuService : IOTAMainMenuService;
  menuItems       : TStringList;
begin
  // Récupération du service pour la barre de menu
  MainMenuService := BorlandIDE.GetService(typeof(IOTAMainMenuService)) as IOTAMainMenuService;

  menuItems := GetItems(MainMenuService.GetFirstMenuItem, 0);

  Clipboard.AsText := menuItems.Text;
  MessageBox.Show('Menus copiés dans le presse-papier !');
end;

On peut ensuite compiler son projet, et tester son extension. Après avoir cliqué sur notre menu, on obtient la liste exhaustive des menus de BDS.

On peut donc déplacer son menu à un endroit plus approprié.

 
Sélectionnez

  // Ajout de l'élément de menu
  menuItem := MainMenuService.AddMenuItem('IDEToolsItem', OTAMenuItemLocation.otamlAfter, 'MenusExtensionOTA', 'Menus de BDS', bmp.GetHbitmap);
Menu

La dernière étape que je vous propose dans ce document, est de ne plus utilisé le presse-papier pour stocker les menus mais de les afficher dans la fenêtre des messages.

Je vais supprimer l'unité qui gère le presse-papier, et mettre à la place SysUtils pour pouvoir facilement transformer mes chaînes de caractères en nombre et réciproquement :

 
Sélectionnez

uses
  Borland.Studio.ToolsAPI,
  System.Windows.Forms,
  System.Drawing,
  System.Resources,
  System.Reflection,
  Borland.Vcl.Classes,
  Borland.Vcl.StrUtils,
  Borland.Vcl.SysUtils;

Pour cela, je vais modifier la fonction qui récupère les éléments de menu pour que je puisse avoir facilement le niveau et non pas une indentation :

 
Sélectionnez

  Result.Add(IntToStr(level) + root.Name + ' | ' + root.Text);

Puis nous allons modifier la procédure MenuItemExecuted pour qu'elle utilise la fenêtre de messages de BDS et non plus le presse-papier :

 
Sélectionnez

procedure TExtensionOTA.MenuItemExecuted(sender: TObject; e: EventArgs);
var
  MainMenuService   : IOTAMainMenuService;
  menuItems         : TStringList;
  MessageService    : IOTAMessageService;
  oneMenu, display  : String;
  level             : Integer;
  mainTitleMenuName : String;
begin
  // Récupération du service pour la barre de menu
  MainMenuService := BorlandIDE.GetService(typeof(IOTAMainMenuService)) as IOTAMainMenuService;
  menuItems := GetItems(MainMenuService.GetFirstMenuItem, 0);

  // Récupère le service de message
  MessageService := BorlandIDE.GetService(typeof(IOTAMessageService)) as IOTAMessageService;

  // Supprime les messages précédents
  MessageService.ClearToolMessages;
  mainTitleMenuName := '';

  for oneMenu in menuItems do
  begin
    level   := StrToIntDef(oneMenu[1], 0);
    display := RightStr(oneMenu, Length(oneMenu) - 1);
    if (level = 0) then
    begin
      // Texte en caractères gras
      MessageService.AddTitleMessage(display);
mainTitleMenuName := LeftStr(display, Pos(' |', display));
    end
    else
    begin
      // Texte standard
      MessageService.AddToolMessage('', DupeString(' ', level) + display, mainTitleMenuName, 0, 0);
    end;
  end;

  // Affiche la vue des messages
  MessageService.ShowMessageView(nil);
end;

Il suffit ensuite de recompiler, et nous obtenons ainsi la liste exhaustive des éléments du menu de BDS dans notre fenêtre de message.

Liste exhaustive des éléments du menu de BDS dans notre fenêtre de message
Si vous souhaitez télécharger les fichiers du projet
Télécharger
miroir

VII. Conclusion

J'espère avoir été suffisamment clair dans ce tutoriel et qu'il vous aura permis de plus facilement aborder l'architecture qui vous permettra ainsi de créer vos propres extensions.

Si vous obtenez cette erreur lors de la compilation de votre projet, Erreur du Linker pendant l'émission des métadonnées (E2328), c'est que votre extension a été montée dans BDS et que celui-ci ne peut par conséquent pas recréer la DLL lors de la compilation.

Voici quelques liens qui m'ont été particulièrement utiles lors de la rédaction de cet article :

Articles
Générer des jeux de tests pour les développeurs à partir des bases de production
Utiliser l'OTA (Open Tools API) de Borland Developer Studio 2006
Défi
Puissance 4
  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2007 Whiler. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.