首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何迭代TActionManager.ActionBars类中的每个TActionManager.ActionBars?

如何迭代TActionManager.ActionBars类中的每个TActionManager.ActionBars?
EN

Stack Overflow用户
提问于 2014-07-28 18:56:19
回答 1查看 1.2K关注 0票数 1

问题

我希望使用TActionManager组件作为一种更好的方法来管理事件,并使用TMainMenuTActionMainMenuBar构建菜单接口,尽管我们将使用TActionMainMenuBar,因为TActionManager中有ActionBars属性。

我遇到的一个恼人的问题是,图像索引有时会丢失,而不是经常丢失,这意味着必须遍历每个ActionBar项并再次手动输入图像索引,如果要添加/删除操作和图像等,这将是一种痛苦。

为了解决这个问题,我提出了迭代每个TActionClientItem并分配图像索引的想法,图像索引是由其指定的TAction确定的。

到目前为止,我想出的是:

代码语言:javascript
复制
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
  • 仍然在对象检查器中单击Items (TActionClients)属性。
  • 添加一个新的TActionClientItem,给它一个标题,如&File。
  • 再次单击Items (TActionClients)属性。
  • 添加一个新的TActionClientItem
  • 在对象检查器中,将TAction (例如,Action1)分配给Action属性。
  • 在表单上放置一个TImageList,并添加一个位图。
  • 再次在窗体设计器中选择TActionManager,并将TImageList分配给Images属性。
  • 双击TActionManager,对于Action1,将ImageIndex改为0
  • 运行应用程序,注意没有显示图像。
  • 文件菜单项也将被禁用,因此如果您愿意,只需编辑TActionTAction事件即可。
  • 再次运行,仍然没有图像显示。

以上场景的解决方案:

  • 若要使图像可见,请编辑ActionBars并找到手动将图像索引设置为0的TActionClientItem
  • 运行应用程序,图像将显示。

因此,以上是我可以再现的一个场景,它展示了如何不更新TAction的图像索引以反映TActionClientItem中的更改。

在其他情况下,这种情况已经发生(通常在添加、删除或编辑TActions和图像时),需要手动更新TActionClientItem

这就是为什么我决定尝试制作一个简单的组件,以确保图像在任何时候都是同步的,并且不管TActionClientItem图像索引是否丢失或变得多余,如果它有一个分配有图像索引的TAction,我希望该图像索引与TActionClientItem链接回来。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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

在代码中,我成功地做到了:

代码语言:javascript
复制
TMyComponent = class(TComponent)
protected
  procedure Loaded; override;
  procedure ActionCallBack(Client: TActionClient);
public
  constructor Create(AOwner: TComponent); override;
  destructor Destroy; override;
end;

代码语言:javascript
复制
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;
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25002303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档