Cannot Destroy Dynamically created Menu Item in Delphi

Firstly, yes I have looked all over the net and still cannot seem to destroy dynamically created menu items. Using Delphi XE. I create the items thus (for the purposes of the exercise SubMenuName is 'Test1':

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

There is no issue using the sub-menu(s) created. The procedure SubMenuClick works as it should, and I identify the correct subMenu item so no issues there. What I then do is an application logout which is supposed to free the dynamically created sub-menus using this code (although I have tried many variations):

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

I have put in showmessage() debug lines that show the component names of the menu items being freeandnil'd and they are what I'd expect, ie. 'Test1' and any others I've created. I then log back in to my application (which was still running, but with me logged out). The software then tries to recreate the same sub menus with the same names (as nothing has changed as far as my application is concerned and they were previously disposed of (supposedly)). I immediately get the exception raised:

Error: A component Named Test1 already exists

I am at a complete loss as to how to dispose of the submenu items so that I can recreate them later with the same names.

Any help greatly appreciated.

Thanks, KB


You did not say it, so I have to assume that MySubMenu is a MenuItem of PopupMenu1. If not please clarify.

To delete items from MySubMenu in order to recreate them again later, it's easyest to call the Clear method:

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

which deletes all menu items of MySubMenu and frees their memory.

In order to recreate the items later, you can not use Delete() or Remove(), without also freeing the memory because they do not free the memory of the items. This is documented in help:

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

With these methods you must free the memory yourself, before you recreate the menu items. But then, it's not necessary to even call Delete or Remove, you can just simply Free the items:

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

There's no need to call FreeAndNil. This last option looks very much as yours, with which you had problems when recreating the menu items. I can't reproduce the error except when using Delete() or Remove() without freeing.


Since the Popup menu owns the items, you do not Free it. Instead of FreeAndNil use MySubMenu.Delete(0) OR more appropriately MySubMenu.Items.Clear instead of the entire While routine.

On App shutdown the popup menu will clear it, there's no need to do it manually unless you're rebuilding the menu.

链接地址: http://www.djcxy.com/p/16174.html

上一篇: 如何停止在Delphi中使用IVBSAXXMLReader解析XML文档?

下一篇: 不能在Delphi中销毁动态创建的菜单项