Динамическое создание подменю в Delphi

У меня есть всплывающее меню, и я хочу, чтобы один из элементов открывал подменю с динамически созданным списком (это список определенных пользователем флагов). Вот как я создаю пункты меню (FlagAs — это пункт меню, к которому я хочу прикрепить подменю):

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);

Обработчик miFlagClick просто переключает проверенный статус своего отправителя:

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

Элементы добавляются отлично, но они не проверяются, когда я нажимаю на них. Обработчик события вызывается EDIT: и Sender является правильным пунктом меню, но галочка не появляется при следующем открытии меню.

Что я делаю неправильно? Или я не так делаю меню? (Примечание flagCount может измениться в будущем, но определено как константа в коде)

EDIT: приведенное выше действительно работает — см. мой ответ ниже


person Mark Pim    schedule 16.02.2009    source источник


Ответы (4)


Я попробовал следующее в Delphi 2009, и это сработало нормально:

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;
person Toon Krijthe    schedule 16.02.2009
comment
Я использовал Delphi 2007, но (как мой ответ ниже) это была моя ошибка где-то еще в коде. Извините, что потратил ваше время. - person Mark Pim; 16.02.2009
comment
Помощь другим никогда не бывает пустой тратой времени. - person Toon Krijthe; 16.02.2009

Просто в сторону (я знаю, что вы нашли причину)

Почему вы используете lNewMenuItems: array[0..flagCount] of tMenuItem; вместо использования одной переменной?

Кроме того, есть ли причина не использовать свойство AutoCheck?

 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;
person Gerry Coll    schedule 17.02.2009

Это была моя ошибка — другая часть моего кода изменяла статус Checked, о котором я забыл. Я чувствую себя глупо сейчас. Извините за потраченное время...

person Mark Pim    schedule 16.02.2009
comment
Лол, нет проблем, сегодня понедельник ;-). - person Toon Krijthe; 16.02.2009

Возможно, у вас есть обработчик событий, прикрепленный к FlagAs, который очищает ваши проверенные флаги?

person Lieven Keersmaekers    schedule 16.02.2009