t e m p o r a l 
 d o o r w a y 

Dynamically Adding Submenus To A Popup Menu

 

Introduction

If you have a menu whose content is determined at run time, the best course is to dynamically create the menu entries for the submenu, usually in the menu OnPopup handler. The following is an example...

The Menu

The menu contains a placeholder for the submenu to be added - this greatly simplifies dynamically adding items. The placeholder item has Visible = false so it is never seen by the user, but it is visible to the programmer at design time.

Indeed, the placeholder can be used as the vehicle for providing the event handler to be used by the other items. Typically, all items in a dynamically created menu share the same event handler, and use the menu caption or a tag on the menu item to determine any specialization of the handler behavior.

The following is the menu for the example (which can be copied and pasted to a form)...

object SamplePopup: TPopupMenu
   object SomeEntry
      Caption = 'Some Entry'
   end
    object PlaceholderForInsert: TMenuItem
      Caption = 'Placeholder'
      object SubmenuPlaceholder: TMenuItem
         Caption = 'SubmenuPlaceholder'
         Visible = False
         OnClick = SubmenuPlaceholderClick

      end
   end
end

Adding The Submenu Entries

This part is now quite easy... Note that this example uses a table (definition not shown) for menu item captions, and it is reloaded each time the popup menu is popped up (so that changes to the table are instantly reflected).

void __fastcall TForm1::DynamicallyAddEntriesToMenu(TMenuItem *theSubmenuParent,TNotifyEvent theClickHandler)
{
   for (int Index = theSubmenuParent->Count-1; Index > 0; Index--) // Deletes old entries - leaves the invisible placeholder
   {
      theSubmenuParent->Delete(Index);
   };

   MenuItemTable->First();

   while (!MenuItemTable->Eof)
   {
      TMenuItem   *NewMenuItem = new TMenuItem(this); // Owned by form, destroyed by form, or by this function

      NewMenuItem->Caption = MenuItemTable->FieldByName("Caption")->AsString;
      NewMenuItem->OnClick = theClickHandler;

      theSubmenuParent->Add(NewMenuItem);

      MenuItemTable->Next();
   };
}
//---------------------------------------------------------------------------
void __fastcall TForm1::SamplePopupPopup(TObject *Sender)
{
   DynamicallyAddEntriesToMenu(SubmenuPlaceholder->Parent,SubmenuPlaceholder->OnClick);
}

Conclusion

Dynamically adding and deleting submenu entries is easy - and with the use of the invisible placeholder item, it is even easier.

Copyright © 2004 by Mark Cashman (unless otherwise indicated), All Rights Reserved