Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 606
Kevin Black Avatar asked Oct 23 '25 11:10

Kevin Black


1 Answers

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.

like image 178
Tom Brunberg Avatar answered Oct 26 '25 06:10

Tom Brunberg



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!