动态创建子菜单

Dynamically create submenu

我有一个带有名为 mnuWindows 的菜单项的 TMainMenu。我希望动态创建子菜单项。我认为这段代码可以做到,但它不起作用:

var
  mnuitm: TMenuItem;

mnuitm:=TMenuItem.Create(nil);
mnuitm.Text:='some text';
mnuWindows.AddObject(mnuitm);

当我点击 mnuWIndows 时,没有任何反应。我哪里错了?

编辑:

子菜单在点击时没有显示,因为每次我这样做时,程序都是全新启动的,我没有意识到在这种情况下,两次点击是必要的。第一次点击并没有明显地做任何事情,第二次点击下拉子菜单。所以,我承认上面的代码片段有效。

但是我还是有困难。我需要创建几个子菜单项,所以我在 mnuWindows OnClick 事件处理程序中尝试了以下循环:

for I := 0 to TabSet1.Tabs.Count - 1 do
begin
  mnuitm := TMenuItem.Create(mnuWindows);
  mnuitm.Text := TabSet1.Tabs[I].Text;
  mnuitm.OnClick:=MenuItemClick;
  if not mnuWindows.ContainsObject(mnuitm) then
    mnuWindows.AddObject(mnuitm);
end;

以上代码的目的是单击 mnuWindows 项目显示选项卡集中的选项卡列表。这段代码在一定程度上起作用。第一次点击时,它会正确列出当前选项卡。但是当我添加一个选项卡并再次单击 mnuWindows 时,新选项卡没有显示在列表中。该列表与以前完全相同。我想知道菜单是否需要以某种方式更新或刷新。我遇到了以下方法

IFMXMenuService.UpdateMenuItem(IItemsContainer, TMenuItemChanges)

但它的文档很少,我不确定如何使用它,甚至不确定它是否相关。

编辑2: 我认为对我的 post 的两次反对票是严厉的。我在网上广泛搜索了如何在 Firemonkey 中动态创建子菜单的示例,但搜索结果很少。我确实找到了 a solution from 2012,但此后的语法更改意味着它在 Tokyo 10.2 中不起作用。

尝试这样的事情。正如其他人在上面评论的那样,您需要提供一个在单击菜单项时会发生的事件。另请注意,我这里的方法需要一堆参数。如果我创建一个 class 并以这种方式传递详细信息,它会更干净,但我很久以前就写了这个,现在我的代码中有很多地方以这种形式使用它。另外,如果我现在写这个,我会使用一个函数来 return 创建的菜单项,以防我在特定情况下需要与之交互(例如,检查它,分配热键等)

procedure PopMenuAddItem(menu: TPopupMenu; sText: string; iID: integer;
  clickEvent: TNotifyEvent; bEnabled: boolean = true);
var
  NewMenuItem: TmenuItem;
begin
  NewMenuItem := TmenuItem.create(menu);
  with NewMenuItem do
  begin
    Caption := sText;
    tag := iID;
    Enabled := bEnabled;
    OnClick := clickEvent;
 end;
 menu.Items.Add(NewMenuItem);
end;

procedure PopMenuAddSubItem(menuItem: TmenuItem; sText: string; iID: integer;
  clickEvent: TNotifyEvent; bEnabled: boolean = true);
var
  NewMenuItem: TmenuItem;
begin
  NewMenuItem := TmenuItem.create(menuItem);
  with NewMenuItem do begin
    Caption := sText;
    tag := iID;
    Enabled := bEnabled;
    OnClick := clickEvent;
  end;
  menuItem.Add(NewMenuItem);
end;

我已经回答了我自己的问题。

提醒一下,我想做的是在我的顶级菜单项 "Windows"(组件名称 "mnuWindows")下动态创建一个子菜单。在子菜单中,我希望列出标签集中标签的名称。

尝试在 mnuWindows.OnClick 事件中动态创建子菜单失败。

我最终的解决方案是使用以下方法重建子菜单,并在创建新选项卡、删除选项卡或重命名选项卡后立即调用此方法:

procedure Form1.ReBuildWindowsMenu;
var
  mnuitm: TMenuItem;
  I: Integer;
begin
  mnuWindows.Clear; // removes submenu items
  for I := 0 to TabSet1.Tabs.Count - 1 do
  begin
    mnuitm := TMenuItem.Create(MainMenu1);
    mnuitm.Caption:= TabSet1.Tabs[I].Text; // submenu item displays same text as associated tab
    mnuitm.OnClick := MenuItemClick; // makes the associated tab active
    mnuWindows.AddObject(mnuitm);
  end;
end;

OnClick 处理程序包含单个语句

TabSet1.ActiveTabIndex:=(Sender as TMenuItem).Index;

这个简单的解决方案使我的 Windows 列表与选项卡集中的选项卡完美同步。我打算使用类似的方法将最近使用的 (MRU) 文件列表放入我的文件菜单中。