Hallo,
Ich möchte eine ActionMainMenuBar komplett dynamisch zur Laufzeit erzeugen (verschiedene Gründe, warum sei an dieser Stelle egal...). Ich habe intern eine Liste mit MenuItems, die wiederum MenuItems beinhalten können, sprich der Menübaum ist darüber abgeregelt. Das ganze basiert auf Interfaces, sprich es ist ungefähr so aufgebaut:
Delphi-Quellcode:
{ Achtung, Pseudo-Code }
IMainMenu = interface(IInterface)
procedure AddItem(const MenuItem: IMenuItem);
property MenuItems: IMenuItemIterator;
end;
IMenuItem = interface(IInterface)
procedure AddItem(const MenuItem: IMenuItem);
procedure Invoke;
property Caption: string;
property MenuItems: IMenuItemIterator;
end;
Meine Idee sollte relativ klar sein, IMainMenu ist so im Prinzip das Hauptmenü und jeder Menüpunkt kann wiederum Menüpunkte besitzen. Mit dieser Schicht möchte ich die eigentliche Oberfläche (bzw. wie sie implementiert ist) von dem Menüaufbau trennen (
GUI sollte nach Möglichkeit austauschbar sein, aber das Menü immer gleich aufgebaut.
Damit ich damit in der ActionBand auf ein OnClick ereignis reagieren kann, hab ich folgendes deklariert bzw. dann implementiert:
Delphi-Quellcode:
TInterfaceAction = class(TAction)
public
property ContainedMenuItem: IMenuItem;
end;
{ dann die Execute Methode, die dem TInterfaceAction zugewiesen ist: }
procedure TMainForm.OnCustomActionClick(Sender: TObject)
begin
if Sender is TInterfaceAction then
TInterfaceAction(Sender).ContainedMenuItem.Invoke();
end;
Das ganze Menü ist an sich auch rasch aufgebaut, das ganze geht über einen ActionManager:
Delphi-Quellcode:
procedure TMainForm.GenerateMainMenu;
procedure AddItem(MenuItem: IMenuItem; ClientItem: TActionClientItem);
var
AnAction: TInterfaceAction;
SubItems: IMenuItemIterator;
begin
{ Action erzeugen }
AnAction := TInterfaceAction.Create(ActionManager);
AnAction.ActionList := ActionManager;
AnAction.Caption := MenuItem.Caption;
AnAction.ContainedMenuItem := MenuItem;
AnAction.OnExecute := OnCustomActionExecute;
{ Action dem ClientItem zuweisen }
ClientItem.Action := AnAction;
ClientItem.Caption := MenuItem.Caption;
{ Subitems anlegen }
SubItems := MenuItem.MenuItems;
while SubItems.Next do
AddItem(SubItems.CurrentItem, ClientItem.Items.Add);
end;
var
MenuItems: IMenuItemIterator;
begin
MenuItems := MainMenu.MenuItems;
while MenuItems.Next do
AddItem(MenuItems.CurrentItem, ActionManager.ActionBars[0].Items.Add);
end;
Das klappt an sich auch einwandfrei, nur hab ich folgende "Unschönheit": Normalerweise wenn man auf erster Ebene von einem Menüpunkt auf den anderen geht, dann sollten ja die Menüpunkte des anderen angezeigt werden. Passiert hier nicht, ich muss draufklicken, was ziemlich nervig ist. Ich hab schon überlegt, das könnte an der am ActionClientItem hängenden Action liegen bzw. am OnExecute, aber wenn ich das OnExecute weglasse, ist der MenuItem auf der ActionBand nicht mehr enabled. Wenn ich die Action ganz weg lasse, wird der MenuItem gar nicht angezeigt.
Kann mir jemand dabei helfen?
Gruß
Nicolai