delphimenuruntimetaction

How to add a drop down menu to an Action Item at Runtime


I'm using the following method to create a an ActionClient with an Action at run time.

procedure TMainForm.AddToProjectHistory(Path: string);
var
    NewOption: TAction;
    ActionClient: TActionClientItem;
begin
    NewOption := TAction.Create(self);
    NewOption.ActionList := ActionManager1;
    NewOption.Caption := Path;
    NewOption.OnExecute := ProjectHistoryExecute;
    ActionClient := TActionClientItem(aToolBarFile.ActionClient.Items[0].Items.Add);
    ActionClient.Action := NewOption;
    ActionClient.Caption := Path;
end;

This works fine if there is already an item in the list, but doesn't work at all if there isn't

e.g. if I add an Item at design time then I can add more items at runtime

enter image description here enter image description here

But if I don't add anything at design time, theres no Drop Down to display the list of items, no drop down appears after adding items.

enter image description here

This doesn't have to be done with Actions but the rest of the menu system uses actions and I don't think I can add standard MenuItems to the action drop down.

Delphi 2005


Solution

  • The VCL automatically creates button controls of a type that depends on whether the item has child elements. By default (and depending on the ActionManager's style setting), for an ActionClientItem which has child items, a TXPStyleDropDownBtn button is created, and for a childless ActionClientItem, a TXPStyleButton is created.

    So when the first child item is added during run time, the button is of the wrong type. Changing the type of that button would require destruction of the current button and a complete and manual instantiation of the new button. This should be possible, but have not tried, because:

    The really most easy solution is to fool the VCL by adding a child item at design time, and to delete that item on form creation:

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      aToolBarFile.ActionClient.Items[0].Items[0].Free;
    end;