简体   繁体   English

如何在 Delphi 应用程序中检测 TPopupMenu 的 OnClose (OnPopDown) 事件

[英]How to Detect a TPopupMenu's OnClose (OnPopDown) Event in Delphi applications

I can write some code inside TPopupMenu's OnPopUp event.我可以在 TPopupMenu 的 OnPopUp 事件中编写一些代码。 But I also need another event for OnPopDown.但我还需要另一个 OnPopDown 事件。 Is there any way to do it using Delphi 10.3.3?有没有办法使用 Delphi 10.3.3 来做到这一点?

There are various options you can try.您可以尝试多种选择。

Approach 1方法一

In the simpler case when you have a particular control whose context menu you need to track, you can handle its WM_CONTEXTMENU message manually:在更简单的情况下,当您有一个需要跟踪其上下文菜单的特定控件时,您可以手动处理其WM_CONTEXTMENU消息:

  protected
    procedure WMContextMenu(var Message: TWMContextMenu);
      message WM_CONTEXTMENU;

where (for example)哪里(例如)

procedure TForm1.WMContextMenu(var Message: TWMContextMenu);
begin
  if
    Assigned(PopupMenu)
      and
    (ClientRect.Contains(ScreenToClient(Message.Pos)) or (Message.Pos = Point(-1, -1)))
  then
  begin
    Windows.Beep(200, 500); // pre-popup code
    if (Message.XPos = -1) and (Message.YPos = -1) then // Menu key or Shift+F10
      with ClientToScreen(Point(0, 0)) do
        PopupMenu.Popup(X, Y)
    else
      PopupMenu.Popup(Message.XPos, Message.YPos);
    Windows.Beep(400, 500); // post-popup code
  end
  else
    inherited;
end;

The test ClientRect.Contains(ScreenToClient(Message.Pos)) is necessary so that you don't "overwrite" the scrollbar's own context menu.测试ClientRect.Contains(ScreenToClient(Message.Pos))是必要的,这样您就不会“覆盖”滚动条自己的上下文菜单。 Also, you need to consider the case when the context menu is opened using the keyboard (eg menu key or Shift+F10).此外,您需要考虑使用键盘(例如菜单键或 Shift+F10)打开上下文菜单的情况。

Approach 2方法二

If this is not enough for you, you could create your own TPopupMenu child class and override its Popup method, which is virtual.如果这对您来说还不够,您可以创建自己的TPopupMenu子 class 并覆盖其虚拟的Popup方法。 Add a DoPopdown method and call it at the end (following the design of the DoPopup method).添加一个DoPopdown方法并在最后调用它(遵循DoPopup方法的设计)。

To quickly test this approach, you can use an interposer class:要快速测试这种方法,您可以使用插入器 class:

type
  TPopupMenu = class(Vcl.Menus.TPopupMenu)
    procedure Popup(X, Y: Integer); override;
  end;

implemented as实现为

{ TPopupMenu }

procedure TPopupMenu.Popup(X, Y: Integer);
begin
  inherited;
  Windows.Beep(400, 500); // post-popup code
end;

But of course it is nicer to create a true descendant class ( TPopupMenuEx , perhaps?) that you register in the IDE.但是,当然最好创建一个您在 IDE 中注册的真正后代TPopupMenuEx (也许是 TPopupMenuEx ?)。 Add an FOnPopdown: TNotifyEvent private field, a DoPopdown protected function, and an OnPopdown published property.添加FOnPopdown: TNotifyEvent私有字段、 DoPopdown保护 function 和OnPopdown发布属性。 This precisely mimics the OnPopup mechanism.这精确地模仿了OnPopup机制。

Needless to say, this approach also works with a TTrayIcon 's menu.不用说,这种方法也适用于TTrayIcon的菜单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM