问题
我希望使用TActionManager组件作为一种更好的方法来管理事件,并使用TMainMenu或TActionMainMenuBar构建菜单接口,尽管我们将使用TActionMainMenuBar,因为TActionManager中有ActionBars属性。
我遇到的一个恼人的问题是,图像索引有时会丢失,而不是经常丢失,这意味着必须遍历每个ActionBar项并再次手动输入图像索引,如果要添加/删除操作和图像等,这将是一种痛苦。
为了解决这个问题,我提出了迭代每个TActionClientItem并分配图像索引的想法,图像索引是由其指定的TAction确定的。
到目前为止,我想出的是:
procedure TMyComponent.ReassignActionImages;
var
I, J, K: Integer;
Manager: TActionManager;
BarItem: TActionBarItem;
Client: TActionClientItem;
Action: TAction;
begin
for I := 0 to Owner.ComponentCount -1 do
begin
if (Owner.Components[I].ClassType = TActionManager) then
begin
Manager := TActionManager(Owner.Components[I]);
for J := 0 to Manager.ActionBars.Count -1 do
begin
BarItem := Manager.ActionBars.ActionBars[J];
if BarItem.ActionBar <> nil then
begin
for K := 0 to BarItem.Items.Count -1 do
begin
Client := BarItem.Items[K];
if Client.Action <> nil then
begin
Action := TAction(Client.Action);
if Action <> nil then
begin
Client.ImageIndex := Action.ImageIndex;
//ShowMessage('Has Action: ' + Manager.Name + ' - ' + Action.Name + ' - ' + Client.Caption);
end;
end;
end;
end;
end;
end;
end;
end;虽然这看起来确实有效,但它似乎不处理子项。我想我需要某种递归过程,但我不知道如何实现它。根据我对递归的理解,它基本上意味着在一个过程中运行相同的过程?
使用一个场景来重现丢失的图像索引的TActionClientItem步骤:
TActionManager添加到表单中。TAction添加到TActionManager中,将ImageIndex设为-1。TActionMainMenuBar添加到表单中。TActionManager,然后编辑ActionBars属性。TActionBarItem。TActionMainMenuBar指定为ActionBar。TActionClients)属性。TActionClientItem,给它一个标题,如&File。TActionClients)属性。TActionClientItem。Action属性。TImageList,并添加一个位图。TActionManager,并将TImageList分配给Images属性。TActionManager,对于Action1,将ImageIndex改为0TAction的TAction事件即可。以上场景的解决方案:
TActionClientItem。因此,以上是我可以再现的一个场景,它展示了如何不更新TAction的图像索引以反映TActionClientItem中的更改。
在其他情况下,这种情况已经发生(通常在添加、删除或编辑TActions和图像时),需要手动更新TActionClientItem。
这就是为什么我决定尝试制作一个简单的组件,以确保图像在任何时候都是同步的,并且不管TActionClientItem图像索引是否丢失或变得多余,如果它有一个分配有图像索引的TAction,我希望该图像索引与TActionClientItem链接回来。
发布于 2014-07-29 13:25:32
我其实有点高兴,因为这一次我能够解决一个不那么明显的简单问题!
解决方案是在IterateClients上调用TActionManager.ActionBars,通过使用回调过程,我们可以访问每个TActionClientItem。
有用的文件链接:
http://docwiki.embarcadero.com/VCL/XE/en/ActnMan.TActionBars
Members
http://docwiki.embarcadero.com/VCL/XE/en/ActnMan.TActionClientsCollection.IterateClients
在代码中,我成功地做到了:
TMyComponent = class(TComponent)
protected
procedure Loaded; override;
procedure ActionCallBack(Client: TActionClient);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;和
procedure TMyComponent.Loaded;
procedure SyncImages;
var
I: Integer;
Manager: TActionManager;
begin
for I := 0 to Owner.ComponentCount -1 do
begin
if (Owner.Components[I].ClassType = TActionManager) then
begin
Manager := TActionManager(Owner.Components[I]);
Manager.ActionBars.IterateClients(Manager.ActionBars, ActionCallBack);
end;
end;
end;
begin
inherited Loaded;
SyncImages;
end;
{ ---------------------------------------------------------------------------- }
procedure TMyComponent.ActionCallBack(Client: TActionClient);
begin
if (Client is TActionClientItem) then
begin
with TActionClientItem(Client) do
begin
if Action <> nil then
begin
Caption := TAction(Action).Caption; // if you want to sync caption
ImageIndex := TAction(Action).ImageIndex;
end;
end;
end;
end;https://stackoverflow.com/questions/25002303
复制相似问题