Einzelnen Beitrag anzeigen

rochus

Registriert seit: 23. Dez 2004
Ort: Dornstadt
30 Beiträge
 
Delphi 7 Enterprise
 
#1

ActionBand bzw ActionMainMenuBar und dynamische Items

  Alt 1. Mai 2006, 15:18
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
Nicolai Waniek
Im Nachhinein ist man immer ein Schlauch!
"Dream as if you'll live forever, live as if you'll die today!" James Dean
  Mit Zitat antworten Zitat