1

在 Windows 10 上的 32 位 Delphi 11 VCL 应用程序中,我使用一个TApplicationEvents组件来捕获 Windows 消息。不幸的是,当我右键单击MenuItem时,TApplicationEvents似乎对消息没有反应:WM_MENURBUTTONUPTPopupMenu

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
begin
  case Msg.message of
      Winapi.Messages.WM_MENURBUTTONUP: CodeSite.Send('TForm1.ApplicationEvents1Message: WM_MENURBUTTONUP');
  end;
end;

微软文档说:

WM_MENURBUTTONUP 消息
当用户在光标位于菜单项上时释放鼠标右键时发送。

或者,WM_COMMAND通过左键和右键单击发送。但是,出于特定目的,我只需要在右键单击菜单项时做出反应。

4

1 回答 1

5

文档的引用部分解释了为什么您没有看到此消息:

用户 [...]

TApplicationEvents.OnMessage事件只能检测已发布的消息,不能检测已发送的消息。

主菜单

因此,如果您想检测此消息,可以添加

  protected
    procedure WndProc(var Message: TMessage); override;

到您的表单类,实现如下:

procedure TForm1.WndProc(var Message: TMessage);
begin
  if Message.Msg = WM_MENURBUTTONUP then
    ShowMessage('rbu')
  else
    inherited
end;

尝试,例如:

procedure TForm1.WndProc(var Message: TMessage);
begin
  if Message.Msg = WM_MENURBUTTONUP then
  begin
    var MI := Menu.FindItem(Message.LParam, fkHandle);
    if Assigned(MI) and InRange(Message.WParam, 0, MI.Count - 1) then
      ShowMessageFmt('Menu item "%s" right clicked.', [MI.Items[Message.WParam].Caption]);
  end
  else
    inherited
end;

弹出菜单

对于 a TPopupMenu,您需要编写自己的TPopupList后代:

type
  TPopupListEx = class(TPopupList)
  protected
    procedure WndProc(var Message: TMessage); override;
  end;

{ TPopupListEx }

procedure TPopupListEx.WndProc(var Message: TMessage);
begin
  if Message.Msg = WM_MENURBUTTONUP then
    ShowMessage('rbu')
  else
    inherited
end;

initialization
  FreeAndNil(PopupList);
  PopupList := TPopupListEx.Create;

并确保将TPopupMenu's设置TrackButtontbLeftButton.

如果您有多个弹出菜单,您可以尝试这样的操作(未完全测试):

procedure TPopupListEx.WndProc(var Message: TMessage);
begin
  if Message.Msg = WM_MENURBUTTONUP then
  begin
    for var X in PopupList do
      if TObject(X) is TPopupMenu then
      begin
        OutputDebugString(PChar(TPopupMenu(X).Name));
        var MI: TMenuItem;
        if TPopupMenu(X).Handle = HMENU(Message.LParam) then
          MI := TPopupMenu(X).Items
        else
          MI := TPopupMenu(X).FindItem(HMENU(Message.LParam), fkHandle);
        if Assigned(MI) and InRange(Message.WParam, 0, MI.Count - 1) then
        begin
          ShowMessageFmt('Menu item "%s" right clicked.', [MI.Items[Message.WParam].Caption]);
          Break;
        end;
      end;
  end
  else
    inherited
end;

示例应用程序的屏幕记录,显示主菜单中的人民币点击和两个不同的上下文菜单。

于 2021-11-20T17:54:36.000 回答