How To: Delphi 2.0 Open Tools API Intro

Posted: (EET/GMT+2)

 

How To: Delphi 2.0 Open Tools API Programming Intro

Level: Beginner/Intermediate


Ever wondered where was the documentation for the promised Open Tools API? Well, there isn't any, except in the source code of the eight interface code files, which you can find from your \Delphi 2.0\Source\ToolsAPI\ directory. Note that for these files to be available, you must have Developer or Client/Server edition of Delphi.

Well then, what can you do with Tools API? To give you some idea, let's first look at what's available:

  • ToolIntf: base Tools API plus menu interfaces
  • ExptIntf: interfaces for writing custom experts
  • EditIntf: IDE editor, form design, resource file and notification interfaces
  • DsgnIntf: interfaces for custom property and form editors
  • VcsIntf: Version Control Software interfaces
  • VirtIntf: general class definitions
  • IStreams: interface streams used with for example editor interfaces
  • FileIntf: virtual file system interfaces

Of those eight, I've found the four topmost units to be the most important ones (depends on what you want to do, of course). For example, I often find myself writing simple add-ons using the expert interfaces, so I only need to use the two or three topmost units.

For this text to have something to do with the "How To" title, let's get right down to a hands on example: writing a simple yet easy-to-extend custom "expert".

To write experts which hook into Delphi IDE, you need to know how to write Windows DLLs. This is because Delphi dynamically loads your DLLs, initializes them and then runs your code. If you haven't written a DLL before, you should learn the basics before going futher with this How To.

If Delphi isn't running, start it up. From the File choose New and select "DLL". You get a basic framework of a DLL. For your expert to work, you must at least write a single "event handler". This callback function is actually an normally exported function, which is given a special name so that Delphi can find it when it loads your expert.

In this example, we call the function InitToolsAPI, but you can call it whatever you want. Add the following code to the Delphi generated DLL framework:

    uses
      ShareMem,
      ...,
      ToolIntf,  { add these }
      ExptIntf,
      Dialogs;
    
    Type
      TMyEventHandler = Class { object to handle menu item click }
        Procedure HandleClick(Sender: TIMenuItemIntf);
      End;
    
    Var
      MainMenu   : TIMainMenuIntf;  { Delphi main menu }
      Handler    : TMyEventHandler; { our event handler }
      MyMenuItem : TIMenuItemIntf;  { our menu item }
    
    Procedure TMyEventHandler.HandleClick(Sender: TIMenuItemIntf);
    Begin
      ShowMessage(My Own Item has been clicked!');
    End;
    
    Procedure WorkWithMenus; { edit Delphi Search menu }
    Var MenuItem : TIMenuItemIntf;
    Begin
      MenuItem := MainMenu.GetMenuItems;
      MenuItem := MenuItem.GetItem(2); { 2 = Search menu in Delphi IDE }
      MyMenuItem := MenuItem.InsertItem(-1,
                                        '&My Own Item!','SearchMyItem',
                                        '',0,0,0,[mfVisible,mfEnabled],
                                        Handler.HandleClick);
    End;
    
    Procedure DoneToolsAPI; Export; StdCall;
    Begin
      ShowMessage('In DoneToolsAPI!'); { just to test }
      MyMenuItem.DestroyMenuItem;      { delete our menu item }
      Handler.Free;                    { free handler }
    End;
    
    
    Function InitToolsAPI(ToolServices : TIToolServices;
                          RegisterProc : TExpertRegisterProc;
                          Var Terminate : TExpertTerminateProc) :
                          Boolean; Export; StdCall;
    Begin
      ShowMessage('In InitToolsAPI!');      { just to test }
      ExptIntf.ToolServices := ToolServices;
      MainMenu := ToolServices.GetMainMenu; { get Delphi menu }
      Handler := TMyEventHandler.Create;    { create own event handler }
      Terminate := DoneToolsAPI;            { customized exit procedure }
      WorkWithMenus;
      Result := True;
    End;
    


Also, don't forget to export your newly defined call back function by name:

    Exports
      InitToolsAPI Name ExpertEntryPoint Resident;
    


The ExpertEntryPoint is a string definied in the ExptIntf unit. Now, if you did everything correctly, it is time to test your expert. First, compile the DLL, and fix any possible errors. When compilation is successfull, you are ready to proceed to the interesting parts.

Before you can register the expert with Delphi, it is best to create a copy of it. This is because when Delphi load your expert, it locks the DLL so that you cannot recompile it. I personally like doing file operations on the "black screen" ie. in the DOS prompt (I'm not very good with the mouse... ;-) but the most important thing is to make the copy in some way.

When you have created a "backup" copy, you can register the expert with Delphi. Fire up the Registry (Start Menu/Programs/Accessories/System Tools/Registeration Editor) and browse to the HKEY_CURRENT_USER\Software\Borland\Delphi\2.0\Experts key. Add a string value. You can call the value whatever you want. The data for the value is more important: it must be a full path to your backup copy of the expert.

windows registry

After you have added the key, minimize RE, and exit Delphi. Now relaunch Delphi, and if everything went corrently (you should see one message box before Delphi is up) your Search menu should contain a new menu item. Choose it and you can be sure that your first Open Tools Expert is working OK!

Oh, if you want to get rid of the new expert, simply remove the key from the registry and reload Delphi.


Questions? Comments? Give feedback. Or just fill in a form.