Search code examples
delphidelphi-2010tactiontactionmanager

How do I programatically add actions to an Action Manager in Delphi 2010


I am trying to dynamically add actionitems, I can add the item and it works when I do this:

HostActionItem := ActionManager.ActionBars[0].Items[0].Items[2];
  NewItem := HostAction.Items.Add;
  NewItem.Action :=  MyActionToPerform;
  NewItem.Caption := Description;
  NewItem.ImageIndex := 1;
  NewItem.Tag := 13;

However, when the action Execute method fires I attempt to get the ActionComponent from the Sender object like this:

  if (Sender is TAction) then
  tag := (Sender As TAction).ActionComponent.Tag;

But the ActionComponent is always nil. Why is the ActionComponent not being initialised?


Solution

  • short answer:

    You're expecting a TActionClientItem to show up as ActionComponent of an TAction. That won't happen since TActionClientItem does not descend from TComponent.

    longer answer:

    I believe you're adding your item to a menu bar. It seems to be by design that an TAction linked to a menu item would not support the ActionComponent. The items of a menu bar is of type TActionClientItem. This is a 'collection item', not a 'component'. Hence the menu cannot fill in the ActionComponent parameter with the menu item when calling the Execute method of the action link of the selected item. If this sounds confusing, I guess the below quotes from the VCL source would make it clear:

    TBasicActionLink.Execute method:

    function Execute(AComponent: TComponent = nil): Boolean; virtual;
    

    The passed component is assigned to FAction.ActionComponent before it is executed.

    How it's called from TCustomActionMenuBar.ExecAction:

    FSelectedItem.ActionLink.Execute;
    

    For the question in the title, I don't think you're doing anything wrong, apart from setting the Caption and ImageIndex of a TActionClientItem is unnecessary, as it's the TAction's title and image which will be shown.