问题
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?
回答1:
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.
来源:https://stackoverflow.com/questions/4283491/how-do-i-programatically-add-actions-to-an-action-manager-in-delphi-2010