【问题标题】:Creating a popup menu at runtime在运行时创建弹出菜单
【发布时间】:2013-08-31 03:15:50
【问题描述】:

我试图简单地创建一个弹出菜单(或上下文菜单),向其中添加一些项目,然后在鼠标位置显示它。我发现的所有示例都是使用设计器执行此操作的。我是从 DLL 插件执行此操作的,因此没有表单/设计器。用户将单击主应用程序中的一个按钮,该按钮调用下面的execute 过程。我只是想出现类似于右键菜单的东西。

我的代码显然不起作用,但我希望有一个在运行时而不是设计时创建弹出菜单的示例。

procedure TPlugIn.Execute(AParameters : WideString);
var
  pnt: TPoint;
  PopupMenu1: TPopupMenu;
  PopupMenuItem : TMenuItem;
begin
  GetCursorPos(pnt);
  PopupMenuItem.Caption := 'MenuItem1';
  PopupMenu1.Items.Add(PopupMenuItem);
  PopupMenuItem.Caption := 'MenuItem2';
  PopupMenu1.Items.Add(PopupMenuItem);
  PopupMenu1.Popup(pnt.X, pnt.Y);

end;

【问题讨论】:

  • @Warren 有一些静态类型的语言,声明一个变量就足以初始化它。 C++ 就是一个明显的例子。
  • @ike 预计插件 DLL 中的 GUI 代码会出现问题。
  • -1 表示“我的代码显然不起作用”。总是用逐字复制的错误消息来描述失败
  • “我的代码显然不起作用”。为什么,哦,为什么?好像你知道答案!那为什么要问呢?
  • @Rigel 这就是包存在的原因。使用 DLL 而不是插件的包意味着 DLL 对宿主可执行文件具有单独的 VCL 实例。典型的症状是类型标识不能按预期工作。例如,在上面的代码中,TPopupMenu 在 DLL 中是与主机中完全相同的命名类型不同的类型,因为存在不同的 VCL 实例。但是还有很多问题。如果包不是一个可行的选择,那么你需要做更多的工作来启用插件。

标签: delphi popup contextmenu


【解决方案1】:

您必须在 Delphi 中实际创建一个类的实例,然后才能使用它们。以下代码创建一个弹出菜单,向其中添加一些项目(包括单击的事件处理程序),并将其分配给表单。请注意,您必须像我所做的那样自己声明(并编写)HandlePopupItemClick 事件)。

在接口部分(在uses 子句中添加Menus):

type
  TForm1 = class(TForm)
    // Double-click the OnCreate in the Object Inspector Events tab. 
    // It will add this item.
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    // Add the next two lines yourself, then use Ctrl+C to
    // generate the empty HandlePopupItem handler
    FPopup: TPopupMenu;      
    procedure HandlePopupItem(Sender: TObject);
  public
    { Public declarations }
  end;

implementation

// The Object Inspector will generate the basic code for this; add the
// parts it doesn't add for you.
procedure TForm1.FormCreate(Sender: TObject);
var
  Item: TMenuItem;
  i: Integer;
begin
  FPopup := TPopupMenu.Create(Self);
  FPopup.AutoHotkeys := maManual;
  for i := 0 to 5 do
  begin
    Item := TMenuItem.Create(FPopup);
    Item.Caption := 'Item ' + IntToStr(i);
    Item.OnClick := HandlePopupItem;
    FPopup.Items.Add(Item);
  end;
  Self.PopupMenu := FPopup;
end;

// The Ctrl+C I described will generate the basic code for this;
// add the line between begin and end that it doesn't.
procedure TForm1.HandlePopupItem(Sender: TObject);
begin
  ShowMessage(TMenuItem(Sender).Caption);
end;

现在我将留给你弄清楚如何做剩下的事情(创建并显示在特定位置)。

【讨论】:

  • 我在同一过程中创建并显示了上下文菜单。我不需要释放任何正确的东西?
  • 我无法回答这个问题,因为我不知道你到底做了什么。在我发布的代码中,菜单属于表单(表单方法中的TPopupMenu.Create(Self)表示表单是所有者,并负责释放它)并且单个项目属于菜单('TMenuItem.Create(FPopup) `)。您的菜单必须存在足够长的时间,以便事件处理程序在单击项目时仍然有效。
  • 我可能会做的是让插件在它的构造函数中创建弹出菜单。 Execute 然后将获取光标位置并在该位置显示菜单,并且插件的析构函数可以释放弹出菜单。我不知道这是否对您有用,因为除了您在问题中发布的内容之外,我没有任何信息。
  • 是的,很抱歉缺少细节,部分原因是试图弄清楚描述什么以及如何描述。但添加destructor 和添加FPopup.Free; 有效。在那之前,我的应用程序一直在崩溃。谢谢。
  • 我无法理解人们在发布像Warren P 这样的 cmets 时如此激进。哪里来的这么嚣张?他们忘记了他们曾经是新手并犯了同样的基本错误。如果您没有必要的耐心来处理这些基本问题,我认为最好不要制作 cmets。以Ken White 为例,他的回答直截了当、简单、客观,实际上帮助用户解决了问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多