Dieser zweite Teil beschäftigt sich mit der Erweiterung des Menüs der Delphi-
IDE.
Erster, wichtiger Unterschied zu einem einfachen Plugin
Im Vergleich zum ersten Teil möchten wir dieses Mal alles selbst erledigen. Damit kommt auch schon die erste Änderung einher. Die Methode
GetStyle muß einen anderen Wert zurück liefern.
Delphi-Quellcode:
function TDelphiPlug.GetStyle: TExpertStyle;
begin
// liefert die Art des Experten zurück
// mögliche Werte: esStandard, esForm, esProject, esAddIn
Result := esAddIn;
end;
Wir könnten auch hier wieder
esStandard nutzen, allerdings würde die Delphi-
IDE dann einen Eintrag im Hilfe-Menü erstellen, welchen wir dieses Mal nicht benötigen.
Das PlugIn kommt in das Menü der Delphi-IDE
Dieses PlugIn wird im Tools-Menü ein Submenü einrichten, welches wiederum drei Menüeinträge hat. Dazu dient die Methode
CreateMenuEntries unserer PlugIn-Klasse. Um das Menü der
IDE anzusteuern muß die Schnittstelle zur
IDE (
TIToolServices) bekannt sein.
Diese Schnittstelle liefert uns die Schnittstelle zum Hauptmenü (
TIMainMenuIntf) zurück. Über diese können wir das gewünschte Menü (
TIMenuItemIntf) ansteuern. Diese Schnittstelle bietet uns die Methode
InsertItem, welche es uns ermöglicht einen neuen Menüpunkt zu erstellen. Diese Methode ist wie folgt definiert
Delphi-Quellcode:
function InsertItem(Index: Integer; Caption, Name, Hint: string;
ShortCut, Context, GroupIndex: Integer; Flags: TIMenuFlags;
EventHandler: TIMenuClickEvent): TIMenuItemIntf; stdcall;
Der dritte Parameter
Name muß eindeutig für die gesamte Delphi-
IDE sein, also seid kreativ! Der fünfte Parameter ist für Short-Cuts, aufgrund eines Bugs bis einschließlich Delphi 7 jedoch unbrauchbar.

Um das zu umgehen ist ein sogenannter
AddInNotifier notwendig, das sprengt jedoch den aktuellen Rahmen des Tutorials. Der sechste Parameter
Context ist wichtig, um zu ermitteln, welcher Menüpunkt vom User angesteuert wurde und sollte innerhalb des PlugIns eindeutig sein. Der letzte Parameter
EventHandler ist ein Pointer auf eine Methode der PlugIn-Klasse, welcher aufgerufen wird, wenn der Menüpunkt in der Delphi-
IDE geklickt wurde. Für Menüeinträge mit Untereinträgen sollte dieser
nil sein, da es sonst zu Problemen kommen kann. Auszug aus dem relevanten Code
Delphi-Quellcode:
procedure TDelphiPlug.CreateMenuEntries;
var
MainMenu: TIMainMenuIntf;
ToolsMenu: TIMenuItemIntf;
begin
// get main menu
MainMenu := FToolServices.GetMainMenu;
if MainMenu <>
nil then
try
// get tools menu
ToolsMenu := MainMenu.FindMenuItem('
ToolsMenu');
try
// create sub-menu
FMI_Sub := ToolsMenu.InsertItem(1, '
Mein PlugIn', '
mplugMain',
'
Ein Hinttext', 0, MIdx_Main, 0, [mfVisible, mfEnabled],
nil);
// create three sub-menu entries
FMI_Main := FMI_Sub.InsertItem(0, '
Über mein PlugIn', '
mplugInfo',
'
Ein Hinttext', 0, MIdx_Main, 0, [mfVisible, mfEnabled],
MenuItemClick);
FMI_ShowItems := FMI_Sub.InsertItem(1, '
Hauptmenü Namen', '
mplugShow',
'
Ein Hinttext', 0, MIdx_ShowItems, 0, [mfVisible, mfEnabled],
MenuItemClick);
FMI_RunCommand := FMI_Sub.InsertItem(2, '
Visit DP!', '
mplugDP',
'
Ein Hinttext', 0, MIdx_RunCommand, 0, [mfVisible, mfEnabled],
MenuItemClick);
finally
ToolsMenu.Free;
end;
finally
MainMenu.Free;
end;
end;
Der Eventhandler
Im Eventhandler muß überprüft werden, welcher Menüpunkt durch den User ausgewählt wurde. Am einfachsten ist das mit einem
case...of Statement zu erreichen. Auszug aus dem Code
Delphi-Quellcode:
procedure TDelphiPlug.MenuItemClick(Sender: TIMenuItemIntf);
begin
case Sender.getContext
of
MIdx_Main: MessageBox(ToolServices.GetParentHandle, PChar(
'
Der Hauptmenüpunkt wurde aktiviert.'#13#10 +
'
Der Name der Expert-DLL ist: ' + GetDllName), '
Öhm', MB_ICONERROR
or
MB_OK);
MIdx_ShowItems: ShowMainMenuItems;
MIdx_RunCommand: RunCommand;
else
// unerwarteter, bzw. nicht implementierter Aufruf
MessageBox(ToolServices.GetParentHandle, '
Wer hat gerufen?', '
Öhm',
MB_ICONERROR
or MB_OK);
end;
end;
Wo liegt die DLL eigentlich rum?
In normalen Anwendungen (EXE-Apps) kann man immer über ParamStr(0) bzw. Application.ExeName den Namen inkl. Pfad der Anwendung erhalten. Dieses ist bei DLLs allerdings nicht möglich, deshalb ist im Code noch die Funktion
GetDllName zu finden, welche den Pfad und Namen der PlugIn
DLL zurückliefert, falls Sie dort irgendwelche INI Dateien oder ähnliches hinterlegen wollen. Diese Funktion kann in jeder beliebigen Anwendung (EXE,
DLL, ...) genutzt werden.
Delphi-Quellcode:
function GetDllName: String; stdcall;
var
TheFileName : array[0..MAX_PATH] of char;
begin
FillChar(TheFileName, sizeof(TheFileName), #0);
GetModuleFileName(hInstance, TheFileName, sizeof(TheFileName));
Result := TheFileName;
end;
Der liebe Rest...
kann dem beigefügten Download entnommen werden. Und nicht vergessen, das PlugIn muß in der Registry eingetragen werden, damit Delphi es auch lädt.
...

...