Need Example Delphi Code to dynamically create a popup menu <with> submenu items

I would like to see example Delphi code for dynamic menu creation <INCLUDING> a submenu with several items.
Here is my current dynamic menu builder
I want to replace the About item with an "Information" item that has a submenu with
  About (calling DoAbout)
  Buy (calling DoBuy)
  News (calling DoNews)

I would appreciate either appropriate modification of my code or a good example using your own code.  
Nothing I've tried has worked.  I know I need to use NewSubItem in place of New Item, but I must not be creating the array of sub items correctly.

Also the Delphi help refers to having to release memory - I need to know about that - don't want memory leaks!

Here's my current code:

procedure T_form.BuildMenu(theMenu: TPopUpMenu);
var
  i, j, k: integer;
  s: string;
begin
  theMenu.items.clear;
  if theMenu <> TrayMenu then
  begin
    for i := 0 to _form.FrameDex.count - 1 do
    begin
      s := _form.FrameDex.Strings[i];
      if i > 0 then for j := 0 to i - 1 do if comparetext(s, _form.FrameDex.Strings[j]) = 0
          then s := '';
      if length(s) > 0 then
      begin
        inc(k);
        theMenu.items.add(NewItem(s + ' Frame', 0, False, True, FrameClick, 0, ''));
      end;
    end;
    theMenu.items.add(NewLine);
  end;
  if theMenu <> TrayMenu then theMenu.items.add(NewItem('Basic Options', 0, False, True, ewFrameForm.ShowControlPanel, 0, ''));
  theMenu.items.add(NewItem('Advanced Options', 0, False, True, Setup, 0, ''));
  theMenu.items.add(NewItem('Help', 0, False, True, HelpCallClick, 0, ''));
  theMenu.items.add(NewItem('About', 0, False, True, DoAbout, 0, ''));
  theMenu.items.add(NewItem('Toggle Desktop Icons', 0, False, True, ToggleIcons, 0, ''));
//    traymenu.items.add(NewItem('PopNotes', 0, False, True, DoPopNotes, 0, ''));
  if theMenu <> TrayMenu then theMenu.items.add(NewItem('Go To Sleep', 0, False, True, DoNada, 0, ''));
  theMenu.items.add(NewLine);
  theMenu.items.add(NewItem('Quit EdgeWize', 0, False, True, QuitNow, 0, ''));
end;
DMTrumpAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

TNameCommented:
Hi, here's a very simple example:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, StdCtrls;

type
  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    Done:Boolean;
    procedure MenuClick(Sender: TObject);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  MenuItem:TMenuItem;
  SubMenuItem1:TMenuItem;
  Sub:TMenuItem;
  i,c:Integer;
begin
  if not Done then begin
    c:=12;
    MenuItem:=TMenuItem.Create(Self);
    MenuItem.Caption:='&File';
    SubMenuItem1:=TMenuItem.Create(Self);
    SubMenuItem1.Caption:='New';
    MenuItem.Add(SubMenuItem1);

    for i:=0 to c do begin
      Sub:=TMenuItem.Create(Self);
      Sub.Caption:='SubMenu '+IntToStr(i);
      Sub.OnClick:=MenuClick;
      SubMenuItem1.Add(Sub);
    end;

    MainMenu1.Items.Add(MenuItem);
    Done:=True;
  end;
end;

procedure TForm1.MenuClick(Sender: TObject);
begin
  ShowMessage(TMenuItem(Sender).Caption);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Done:=False;
end;

end.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Eddie ShipmanAll-around developerCommented:
Why does it have to be dynamic if you already know what is going to be in the menu?

You will avoid memory leaks in dynamically created menus if you don't do this:
  TMenuItem.Create(Self);
But do this instead:
  TMenuItem.Create(PopupMenu1); // substitute the popupmenu that the item is going into.

Then you don't have to worry about freeing the memory because the PopupMenu is the owner
and will release the memory when it is destroyed.
TheRealLokiSenior DeveloperCommented:
using your code

procedure T_form.BuildMenu(theMenu: TPopUpMenu);
var
  i, j, k: integer;
  s: string;
  infomenu: TMenuItem;
begin
  theMenu.items.clear;
  if theMenu <> TrayMenu then
  begin
    for i := 0 to _form.FrameDex.count - 1 do
    begin
      s := _form.FrameDex.Strings[i];
      if i > 0 then for j := 0 to i - 1 do if comparetext(s, _form.FrameDex.Strings[j]) = 0
          then s := '';
      if length(s) > 0 then
      begin
        inc(k);
        theMenu.items.add(NewItem(s + ' Frame', 0, False, True, FrameClick, 0, ''));
      end;
    end;
    theMenu.items.add(NewLine);
  end;
  if theMenu <> TrayMenu then theMenu.items.add(NewItem('Basic Options', 0, False, True, ewFrameForm.ShowControlPanel, 0, ''));
  theMenu.items.add(NewItem('Advanced Options', 0, False, True, Setup, 0, ''));
  theMenu.items.add(NewItem('Help', 0, False, True, HelpCallClick, 0, ''));
//  theMenu.items.add(NewItem('About', 0, False, True, DoAbout, 0, ''));
  theMenu.items.add(NewItem('Toggle Desktop Icons', 0, False, True, ToggleIcons, 0, ''));
//    traymenu.items.add(NewItem('PopNotes', 0, False, True, DoPopNotes, 0, ''));
  if theMenu <> TrayMenu then theMenu.items.add(NewItem('Go To Sleep', 0, False, True, DoNada, 0, ''));
  theMenu.items.add(NewLine);
  theMenu.items.add(NewItem('Quit EdgeWize', 0, False, True, QuitNow, 0, ''));

  infomenu := TMenuItem.Create(theMenu);
  infomenu.Caption := '&Information';
  TheMenu.Items.Add(infomenu);
  infomenu.Add(NewItem('About', 0, False, True, DoAbout, 0, ''));
  infomenu.Add(NewItem('Buy', 0, False, True, DoBuy, 0, ''));
  infomenu.Add(NewItem('News', 0, False, True, DoNews, 0, ''));
end;
DMTrumpAuthor Commented:
Thanks to all three of you!  TName, I basically used your technique - EddieShipman: I modified TNames's solution according to your suggestion - I should have figured that out myself - but for kindly not laughing at me and providing the reminder I needed thanks.  The RealLoki:  Yours came in after I'd pretty much implemented the solution from TName - but thanks anyway.  
Eddie Shipman - look at my example and you can see that the menu is customized at run time - therefore needs to be dynamic.  And the submenu will be run-time customized as well - I just didn't include that in the specs.



It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.