Einzelnen Beitrag anzeigen

Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#2
  Alt 11. Mai 2003, 16:43
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.

......
Angehängte Dateien
Dateityp: zip delphi-plug_sample__ii_.zip (53,7 KB, 239x aufgerufen)
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat