无法销毁 Delphi 中动态创建的菜单项

Posted

技术标签:

【中文标题】无法销毁 Delphi 中动态创建的菜单项【英文标题】:Cannot Destroy Dynamically created Menu Item in Delphi 【发布时间】:2015-02-26 05:49:32 【问题描述】:

首先,是的,我浏览了整个网络,但似乎仍然无法破坏动态创建的菜单项。使用德尔福 XE。我因此创建了项目(为了练习 SubMenuName 的目的是'Test1':

MenuItemCreated := TMenuItem.Create(PopupMenu1);
MenuItemCreated.Caption:= SubMenuCaption
MenuItemCreated.Hint := SubMenuHint;
MenuItemCreated.Name := SubMenuName;
MenuItemCreated.OnClick :=  SubMenuClick;
MenuItemCreated.AutoHotkeys := maManual;
MySubMenu.Add(MenuItemCreated);

使用创建的子菜单没有问题。 SubMenuClick 过程正常工作,并且我确定了正确的 subMenu 项目,因此那里没有问题。然后我要做的是一个应用程序注销,它应该使用此代码释放动态创建的子菜单(尽管我尝试了很多变体):

  // Get rid of the menu items created
  While MySubMenu.Count > 0 do
  begin
    Itemtodelete := MySubMenu.Items[0];
    FreeandNil(ItemtoDelete);
  end;

我已经放入了 showmessage() 调试行,显示菜单项的组件名称是 freeandnil'd 并且它们是我所期望的,即。 'Test1' 和我创建的任何其他人。然后我重新登录到我的应用程序(它仍在运行,但我已注销)。然后,该软件会尝试重新创建具有相同名称的相同子菜单(因为就我的应用程序而言,没有任何改变,并且它们之前已被处理(假设))。我立即提出了异常:

错误:名为 Test1 的组件已存在

我完全不知道如何处理子菜单项,以便以后可以使用相同的名称重新创建它们。

非常感谢任何帮助。

谢谢, 知识库

【问题讨论】:

【参考方案1】:

你没有说,所以我不得不假设MySubMenu是PopupMenu1的一个MenuItem。如果不是,请澄清。

要从 MySubMenu 中删除项目以便稍后重新创建它们,调用 Clear 方法是最简单的:

procedure TForm5.Button2Click(Sender: TObject);
begin
  MySubMenu.Clear;
end;

删除 MySubMenu 的所有菜单项并释放它们的内存。

为了稍后重新创建项目,您不能使用 Delete() 或 Remove(),同时释放内存,因为它们不会释放项目的内存。这记录在帮助中:

http://docwiki.embarcadero.com/Libraries/XE7/en/Vcl.Menus.TMenuItem.Delete http://docwiki.embarcadero.com/Libraries/XE7/en/Vcl.Menus.TMenuItem.Remove

使用这些方法,您必须自己释放内存,然后再重新创建菜单项。但是,甚至不需要调用 Delete 或 Remove,您可以简单地释放项目:

procedure TForm5.Button2Click(Sender: TObject);
var
  mi: TMenuItem;
begin
  while MySubMenu.Count > 0 do
  begin
    mi := MySubMenu.Items[0];
    mi.Free;
  end;
end;

无需调用 FreeAndNil。 最后一个选项看起来与您的非常相似,您在重新创建菜单项时遇到了问题。除非使用 Delete() 或 Remove() 而不释放,否则我无法重现该错误。

【讨论】:

【参考方案2】:

由于弹出菜单拥有这些项目,您不能释放它。代替 FreeAndNil 使用 MySubMenu.Delete(0) 或更合适的是 MySubMenu.Items.Clear 而不是整个 While 例程。

在应用关闭时弹出菜单会清除它,除非您正在重建菜单,否则无需手动执行。

【讨论】:

汤姆,谢谢,感谢您的回复。 MySubMenu 是 PopupMenu1 的一个菜单项。我的子菜单。清除;仍然导致相同的错误:错误:当我尝试重新创建子菜单项时,一个名为 Test1 的组件已经存在。 mi := MySubMenu.Items[0]; mi.免费;我以前尝试过此操作,但在尝试重新创建子菜单项时仍然出现错误。 Mike,MySubMenu.Clear 确实编译,当我尝试重新创建子菜单项时它只是返回相同的错误。我之前尝试过 MySubMenu.Delete(0),但在尝试重新创建子菜单项时仍然出现相同的错误。 你为什么要首先命名这个项目?你曾经调用过 FindComponent('Test1') 吗?如果不是,那么名称无关紧要,最好不要将名称留空。如果您确实按名称查找菜单项,那么您需要找到名称冲突的其他组件并对其进行处理。例如,给所有东西起更有意义的名字。 – Rob Kennedy 43 分钟前 Rob,我重新插入了您的评论,因为我删除了评论中的“答案”(这是错误的)。你在我删除它之前发表了评论。为混乱道歉。 因此,我认为所有组件都“需要一个名称”。无论如何,如果 MySubMenu.Clear 实际上并没有摆脱 MySubMenu 下的 MenuItems,那么有什么不对吗?在我的实际代码中,它们具有更有意义的名称,我使用这些名称,它们提供上下文。我会尽量不命名组件,看看会发生什么和使用什么,比如 .Hint 属性来提供上下文。 所有,感谢您的建议,非常感谢。从那以后,我发现我以某种方式循环了那段代码两次(因此该组件存在错误)。目前我看不到这是哪里。一旦我解决了这个问题,我相信我会看到释放组件的所有选项都在实际工作。再次感谢您的宝贵时间,我学到了一些必须是好事的东西。编辑:找到罪魁祸首,SubMenu.Clear 确实可以正常工作,再次感谢大家。

以上是关于无法销毁 Delphi 中动态创建的菜单项的主要内容,如果未能解决你的问题,请参考以下文章

delphi 动态添加系统菜单

Delphi动态创建菜单

delphi7 中如何点击菜单项弹出新窗体

如何动态创建菜单项?

如何从数组动态创建复选框列表?

怎么使用CSS3创建动态菜单