Delphi tools - Ide menu expertGeplaatst door Baldo op 11-04-03Erik 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 NL Delphi 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. |