views:

2110

answers:

4

I have a popup menu and I want one of the items to open a sub-menu with a dynamically created list (it's a list of user defined flags). Here's how I'm creating the menu items (FlagAs is the menu item I want to attach the sub-menu to):

lNewMenuItems: array[0..flagCount] of tMenuItem;

for I := 0 to flagCount do
begin
  { Create a new menu item }
  lNewMenuItems[I] := tMenuItem.Create(FlagAs);
  lNewMenuItems[I].Caption := FlagNames[I];
  lNewMenuItems[I].Tag := I; { Tag with the flag number }
  lNewMenuItems[I].OnClick := miFlagClick;
end;

FlagAs.Add(lNewMenuItems);

The miFlagClick handler simply toggles the checked status of its sender:

procedure TMyForm.miFlagClick(Sender: TObject);
begin
  (Sender as tMenuItem).Checked := not (Sender as tMenuItem).Checked;
end;

The items get added perfectly, but they don't get checked when I click on them. The event handler is being called EDIT: and Sender is the correct menu item, but the check mark doesn't appear next time I open the menu.

What am I doing wrong? Or am I going about the menu creation in the wrong way? (Note flagCount may change in the future, but is defined as a constant in the code)

EDIT: the above does actually work - see my answer below

+3  A: 

I tried the following in Delphi 2009 and it worked fine:

procedure TForm5.FormCreate(Sender: TObject);
var
  i : Integer;
  mis : array[0..3] of TMenuItem;
begin
  for i := 0 to 3 do begin
    mis[i] := tMenuItem.Create(SubMenu);
    NewMenu(mis[i]);
  end;
  SubMenu.Add(mis);
end;

procedure TForm5.NewMenu(var mi: TMenuItem);
begin
  mi.Caption := 'Test';
  mi.OnClick := TestClick;
end;

procedure TForm5.TestClick(Sender: TObject);
begin
 (Sender as tMenuItem).Checked := not (Sender as tMenuItem).Checked;
end;
Gamecat
I was using Delphi 2007 but (as my answer below) it was my mistake somewhere else in the code. Sorry to waste your time.
Mark Pim
Helping others is never a waste of time.
Gamecat
A: 

This was my mistake - another bit of my code was modifying the Checked status which I had forgotten about. I feel stupid now. Sorry for the waste of time...

Mark Pim
Lol, no problem, its monday ;-).
Gamecat
A: 

Do you perhaps have an eventhandler attached to FlagAs that clears your checked flags?

Lieven
+1  A: 

Just an aside (I know you have found the cause)

Why are you using lNewMenuItems: array[0..flagCount] of tMenuItem; instead of using a singe variable?

Also, is there a reason for not using the AutoCheck property?

 var
    NewMenuItem: TMenuItem;
    I : Integer;
  begin
    for I := 0 to flagCount do
    begin
      { Create a new menu item }
      NewMenuItem := TMenuItem.Create(FlagAs);
      NewMenuItem.Caption := FlagNames[I];
      NewMenuItem.Tag := I; { Tag with the flag number }
      // NewMenuItem.OnClick := miFlagClick;
      NewMenuItem.AutoCheck := True;
      FlagAs.Add(NewMenuItem);
    end;
  end;
Gerry