2

表单上有 TPopupMenu 和三个按钮,分别名为“AddButton”、“EditButton”和“DestroyButton”,并为所有三个按钮添加了 OnClick 事件。窗体的 PopupMenu 属性中的 TPopupMenu。我在 TForm1 类型声明中创建了 PopupMenuItemsClick 过程,以便它可以用作菜单项 OnClick 事件的方法调用。

type
  TForm1 = class(TForm)
    AddButton: TButton;
    EditButton: TButton;
    DestroyButton: TButton;
    PopupMenu1: TPopupMenu;
    procedure AddButtonClick(Sender: TObject);
    procedure EditButtonClick(Sender: TObject);
    procedure DestroyButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    procedure PopupMenuItemsClick(Sender: TObject);

  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.AddButtonClick(Sender: TObject);
var
  index: Integer;
  NewItem: TMenuItem;
begin
        // The owner (PopupMenu1) will clean up this menu item.
  NewItem := TMenuItem.Create(PopupMenu1); // Create the new item.
  index := PopupMenu1.Items.Count;
  PopupMenu1.Items.Add(NewItem);// Add it to the pop-up menu.
  NewItem.Caption := 'Menu Item ' + IntToStr(index);
  NewItem.Tag := index;
  NewItem.OnClick :=
    PopupMenuItemsClick; // Assign it an event handler.
end;

procedure TForm1.PopupMenuItemsClick(Sender: TObject);
begin
  with Sender as TMenuItem do
  begin
    case Tag of
      0:  ShowMessage('first item clicked');
      1:  ShowMessage('second item clicked');
      2:  ShowMessage('third item clicked');
      3:  ShowMessage('fourth item clicked');
    end;
  end;
end;

{
To edit or destroy an item, grab its pointer 
using the Items property.
procedure TForm1.EditButtonClick(Sender: TObject);
var
  ItemToEdit: TMenuItem;
begin
  ItemToEdit := PopupMenu.Items[1];
  ItemToEdit.Caption := 'Changed Caption';
end;

procedure TForm1.DestroyButtonClick(Sender: TObject);
var
  ItemToDelete: TMenuItem;
begin
  ItemToDelete := PopupMenu.Items[2];
  ItemToDelete.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  index: Integer;
  NewItem: TMenuItem;
begin
  for index := 0 to 3 do
  begin
          // The owner (PopupMenu1) will clean up this menu item.
    NewItem := TMenuItem.Create(PopupMenu1); // Create the new item.
    PopupMenu1.Items.Add(NewItem);// Add it to the pop-up menu.
    NewItem.Caption := 'Menu Item ' + IntToStr(index);
    NewItem.Tag := index;
    NewItem.OnClick :=
      PopupMenuItemsClick; // Assign it an event handler.
  end;
end;

但是当我单击 addmenu 按钮时,没有出现 PopupMenu。任何人都可以找到加载表单或单击任何按钮时没有出现 Popupmenu 的原因。

4

3 回答 3

3

您的代码不是您真正需要的,使用此代码,它将完美运行

procedure TForm1.PopupMenuItemsClick(Sender: TObject);
  var ICount : Integer;
begin
  ICount := TMenuItem(Sender).MenuIndex;
  ShowMessage('Item Number '+ IntToStr(ICount+1) + ' Selected');
end;

procedure TForm1.AddClick(Sender: TObject);
  var
    Index: Integer;
    NewItem: TMenuItem;
begin
    NewItem := TMenuItem.Create(PopupMenu);
    Index := PopupMenu.Items.Count;
    PopupMenu.Items.Add(NewItem);
    NewItem.Caption := 'Menu Item ' + IntToStr(Index);
    NewItem.Tag := Index;
    NewItem.OnClick := PopupMenuItemsClick;
    PopupMenu.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);
end;

我用 Delphi7、XE2 和 XE3 测试了它的工作原理

于 2013-07-07T11:40:35.590 回答
1

在 FormCreate 中添加此行或在 Object Inspector 中设置此属性。 self.PopupMenu:=PopupMenu1;

于 2013-07-07T07:17:26.613 回答
0

此评论可能有助于解决问题(我在旧的 Delphi 版本中也有类似的情况,我没有 XE 可以测试)。

  • 永远不要创建一个组件并让其清空.Name,总是为它分配一个唯一的值(当让空时我看到很多错误的内部代码,因为它们不能为空)。
  • 并且总是在将属性和事件添加到其父级之前将它们分配给组件。

在评论中查看此建议:

procedure TForm1.AddClick(Sender: TObject);
  var
    Index: Integer;
    NewItem: TMenuItem;
begin
    NewItem := TMenuItem.Create(PopupMenu);
    Index := PopupMenu.Items.Count;

    //PopupMenu.Items.Add(NewItem); // Not the correct place, see below
    NewItem.Name : = 'SomeText' + IntToStr(Index); // Name them, with a unique name not starting with a number (also there is no need to put a number)

    NewItem.Caption := 'Menu Item ' + IntToStr(Index);
    NewItem.Tag := Index;
    NewItem.OnClick := PopupMenuItemsClick;

    PopupMenu.Items.Add(NewItem); // After properties has been set, never before

    PopupMenu.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);
    // Do not forget to free such menu item somewhere on your code, obviously not here
end;

对于菜单,请记住释放创建的项目,它们不会自行释放,名称将在下次使用。

于 2016-09-30T12:17:45.333 回答