Delphi tools: Ide menu expert
Erik Stok (aka Baldo)
In de vorige twee artikelen over Delphis Open Tools Api (OTA)
behandelde ik al praktische toepassingen van de property
editor en de component editor.
Dit derde artikel beschrijft het bouwen van een uitbreiding van
het Delphi IDE menu door gebruik te maken van een expert.
Het idee
De uitbreidingen op de Delphi IDE die in eerdere delen van deze
serie artikelen gemaakt zijn, waren te benaderen via de object inspector
en de form designer. Dit was mogelijk omdat deze uitbreidingen in
een bepaalde context vielen, bijvoorbeeld een specifieke property
van een component (de name property
editor) of een component op zich (de align
component editor). Er zijn echter uitbreidingen die moeten kunnen
worden opgestart zonder deze contextgevoelige IDE onderdelen, bijvoorbeeld
een speciale compile opdracht of het tonen van een about box. Het
uitbreiden van Delphis menu is dan de ideale oplossing.
Het mooiste is een oplossing die eenvoudig uit te breiden is. Het
toevoegen van functionaliteit in het menu moet gemakkelijk zijn,
want er staan natuurlijk nog heel wat uitbreidingen van de Delphi
IDE in de planning.
Experts
Een uitbreiding op de Delphi IDE zal in ieder geval in een designtime
package geplaatst moeten worden. De vraag is alleen hoe er zorg
voor gedragen kan worden dat tijdens het builden van dit design
time package ook de menu items tijdelijk worden uitgeschakeld en
dat er na de build bijgewerkte menu items verschijnen. Een expert
is dan een uitkomst, want als een expert geregistreerd is bij Delphi
en de unload van het package met de implementatie vindt plaats,
dan zorgt Delphi voor het opruimen van de instance van de expert.
Er zijn natuurlijk meerdere constructies denkbaar die een soortgelijk
effect hebben, maar de optie voor een expert is naar mijn mening
de meeste elegante.
Delphis main menu
De expert zal dus menu items moeten gaan toevoegen aan Delphis
main menu. Maar hoe komt een expert bij Delphis main menu?
De open tools api verschaft toegang tot het main menu (en diens
actionlist) via het INTAServices interface uit de ToolsAPI unit
(terug te vinden in de Delphi map onder Source\ToolsAPI). Door dit
interface op te vragen van de BorlandIDEServices (tevens uit de
ToolsAPI unit) kan een directe referentie worden verkregen naar
zowel het menu als de bijbehorende actionlist.
Een menuitem aanmaken
Het mooiste is om een action toe te voegen in de Delphi action
list en een menu item aan te maken dat aan deze action gekoppeld
is. Het is dan mogelijk gebruik te maken van een shortcut die op
elk moment reageert. Ook tools als GExperts
zijn dan in staan om de action via hun shortcut instellingen en
toolbars direct te benaderen.
Een van de regels bij het aanmaken van menu items (en actions)
is dat de aanmaker in de gaten moet houden dat het uitvoeren van
de aan het menu item gekoppelde code mogelijk is op het juiste moment.
Een handig uitgangspunt hierbij is het aanmaken van menu items en
actions zelf te regelen, zodat je precies in de gaten kunt houden
dat een menu item wordt opgeruimd als de expert die de uit te voeren
code implementeert uit de lucht gaat.
Uitbreidbaarheid
Om de uitbreidbaarheid van de expert te verhogen wordt gebruik
gemaakt van een IdeMenuExpert en een IdeMenuObject. De IdeMenuExpert
is de class die de toevoeging aan het Delphi menu verzorgd. IdeMenuObject
afgeleiden implementeren de toe te voegen functionaliteit en kunnen
worden aangemeld bij de IdeMenuExpert.
Het IdeMenuObject ziet er als volgt uit:
TIdeMenuObject = class(TObject) public function ItemName: String; virtual; abstract; function Caption: String; virtual; abstract; function ShortCut: String; virtual; abstract; function Order: Integer; virtual; abstract;
procedure Execute(Sender: TObject); virtual; abstract; end;
De ItemName function geeft een unieke naam terug voor het
toe te voegen item. Deze naam wordt gebruikt bij het aanmaken van
menu items en actions.
De Caption function geeft de caption terug die in het nieuw
toe te voegen menu item moet worden gebruikt.
De ShortCut function spreekt voor zich: de te gebruiken
shortcut voor de nieuw toegevoegde action.
Via de Order function kan een volgorde worden aangehouden
binnen de toe te voegen menu items. Indien de volgorde van een menu
item niet expliciet is opgegeven (of op een bestaande volgorde valt)
dan wordt een alfabetische volgorde van menu items aangehouden.
De Execute method bevat de implementatie van de functionaliteit
van het toegevoegde menu item.
Als er een eenvoudige registratiemogelijkheid in de IdeMenuExpert
komt die IdeMenuObject afgeleiden kan registreren om in het menu
opgenomen te worden dan zit het met de uitbreidbaarheid wel goed.
De IdeMenuExpert ziet er dan ook als volgt uit:
TIdeMenuExpert = class(TIExpert) private ... protected function IdeMenuItem: TMenuItem; virtual; procedure SortMenu; virtual;
procedure RegisterMenuItem(IdeMenuObject: TIdeMenuObject); virtual; procedure UnRegisterMenuItem(Index: Integer); virtual;
procedure RegisterShortcuts(Sender: TObject); virtual; public constructor Create; destructor Destroy; override;
function GetName: string; override; function GetStyle: TExpertStyle; override; function GetIDString: string; override; function GetAuthor: string; override; function GetComment: string; override; function GetPage: string; override; function GetGlyph: HICON; override; function GetState: TExpertState; override; function GetMenuText: string; override; procedure Execute; override; end;
Naast wat private fields en wat helper functies zijn dit de methods
en properties van de IdeMenuExpert.
In de constructor zal zorg worden gedragen dat alle nodige IdeMenuObject
afgeleiden worden aangemaakt en in het menu worden gehangen. In
de destructor wordt alles weer netjes uit het menu gehaald en opgeruimd.
De methods GetName, GetStyle, GetIDString,
GetAuthor, GetComment, GetPage, GetGlyph,
GetState, GetMenuText en Execute moeten worden
geïmplementeerd omdat dit abstract methods zijn van TIExpert,
Delphis basis class voor Experts. In het commentaar van de
ToolsAPI unit staat uitgebreid beschreven wat deze methods dienen
te doen dus daar ga ik niet verder op in. Voor deze expert zijn
deze methods slechts bijzaak.
Waar alles om te doen is zijn de methods RegisterMenuItem
en UnRegisterMenuItem. Aan RegisterMenuItem wordt
een IdeMenuObject meegegeven dat geregistreerd dient te worden in
het menu. RegisterMenuItem zal via de methods die het IdeMenuObject
biedt alles te weten kunnen komen wat nodig is om een nieuw menu
item aan te maken.
Een nieuw toe te voegen menu item zal worden toegevoegd onder een
hoofdmenu item; het NLDelphi hoofdmenu item. De method IdeMenuItem
zorgt ervoor dat dit hoofdmenu item aangemaakt wordt. Het gebruik
van deze method zorgt er tevens voor dat er alleen een hoofdmenu
item wordt aangemaakt als er ook daadwerkelijk IdeMenuObjects geregistreerd
zijn.
Na het toevoegen van het nieuwe item zal het menu natuurlijk opnieuw
gesorteerd moeten worden op basis van de eerder genoemde regels.
De method SortMenu implementeert het sorteren van het menu.
De RegisterShortCuts method wordt gebruikt om met behulp
van een timer de shortcuts van de menu items te zetten. Delphi biedt
faciliteiten in de open tools api om zelf shortcuts te zetten op
menu-items, maar in Delphi 6 werken deze nog niet zonder problemen
(lees: vele access violations). De enige manier om dan shortcuts
te kunnen zetten op actions in de Delphi actionlist is handmatig
in een timer, waardoor het zetten van de shortcuts gebeurd nadat
Delphi via zijn keyboard bindings heeft gezet op alle actions.
Het About IdeMenuObject
Een expert bouwen zonder te bewijzen dat hij werkt kan natuurlijk
niet. Daarom is het about IdeMenuObject toegevoegd. Dit geeft tevens
een voorbeeld van hoe een nieuwe toevoeging aan het menu gebouwd
dient te worden. Dit bestaat altijd uit drie stappen:
1. Bouw de IdeMenuObject afgeleide (in dit geval de class TIdeMenuAbout).
Implementeer in de Execute wat het menu item moet doen.
2. Voeg de in stap 1 aangemaakte unit toe in de uses clause van
de unit uIdeMenuExpert (dus: uses uIdeMenuAbout).
3. Voeg in de constructor van de IdeMenuExpert de regel RegisterMenuItem(<MijnIdeMenuAfgeleide>.Create)
toe (in dit geval dus de RegisterMenuItem(TIdeMenuAbout.Create)
regel).
Dat is alles. Het package toont de code
die nodig is om dit alles te implementeren. In toekomstige artikelen
zal ik nieuwe IdeMenuObject afgeleiden maken die volgens deze drie
stappen kunnen worden toegevoegd in de expert.
Conclusie
Ook hier is weer de eenvoud en toepasbaarheid van de Delphi open
tools API terug te vinden. En weer geldt: alles kan worden geprogrammeerd
in de bekende Delphi syntax. De IDE menu expert is een goede basis
voor uitbreidingen op de Delphi IDE die via een menu item opgeroepen
moeten kunnen worden.
|