当使用键盘打开弹出窗口时,如何使 Tpopupmenu 预先选择第一个菜单项

发布于 2025-01-14 07:17:12 字数 532 浏览 1 评论 0原文

TPopupMenu 中的项目可以通过键盘或鼠标突出显示/选择。当使用键盘选择时,您可以使用箭头键在菜单中移动。

如何在不使用 VK_DOWN 模拟向下箭头按键的情况下将第一个菜单项标记为已选择(蓝色)(请参见下面的代码)?

Popup := TPopupMenu.create(nil);
Popup.OnPopup := PopupClick;
class procedure TTrayMain.PopupClick(Sender: TObject) ;
begin    
  // Code below activates the first menu entry.. 
  // Now Looking for an alternative solution to replace this hack:
  keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN,0), 0, 0);
  keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN,0), KEYEVENTF_KEYUP, 0);

end;

The items in TPopupMenu can be highlighted/selected with keyboard or mouse. When selected with keyboard, you can move in the menu with the arrow keys.

How to mark the 1st menu item as selected (blue) without simulating the down arrow keypress with VK_DOWN (see code below)?

Popup := TPopupMenu.create(nil);
Popup.OnPopup := PopupClick;
class procedure TTrayMain.PopupClick(Sender: TObject) ;
begin    
  // Code below activates the first menu entry.. 
  // Now Looking for an alternative solution to replace this hack:
  keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN,0), 0, 0);
  keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN,0), KEYEVENTF_KEYUP, 0);

end;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

断舍离 2025-01-21 07:17:12

您需要将未记录的 MN_SELECITEM 消息发送到弹出窗口。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    PopupMenu1: TPopupMenu;
    Item1: TMenuItem;
    Item2: TMenuItem;
    Item3: TMenuItem;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  //To override the default PopupList, based on Remy Lebeau's code
  TPopupListEx = class(TPopupList)
  protected
    procedure WndProc(var Message: TMessage); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

const MN_SELECTITEM = $01E5;

{ TPopupListEx }

procedure TPopupListEx.WndProc(var Message: TMessage);
var hm:HMENU;

begin
  inherited;
  if (Message.Msg = WM_ENTERMENULOOP) and (Message.WParam = 1) then
    begin
      //When the popupwindow is already created, we can ask it's handle
      hm:=FindWindow(PChar('#32768'),nil);
      //Send the MN_SELECTITEM message. The third parameter is the desired menuitem's index.
      SendMessage(hm,MN_SELECTITEM,0,0);
    end;
end;

initialization
  Popuplist.Free; //free the "default", "old" list
  PopupList := TPopupListEx.Create; //create the new one
  // The new PopupList will be freed by
  // finalization section of Menus unit.
end.

注意其他(包括提到的 delphipraxis 示例)解决方案:

使用 SetMenuItemInfoWHiliteMenuItem 将 MenuItem 设置为突出显示状态不会'不起作用,因为它只影响外观,但是当您将鼠标悬停在任何其他项目上时,第一个项目将保持突出显示。

You need to send the undocumented MN_SELECITEM message to the popupwindow.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    PopupMenu1: TPopupMenu;
    Item1: TMenuItem;
    Item2: TMenuItem;
    Item3: TMenuItem;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  //To override the default PopupList, based on Remy Lebeau's code
  TPopupListEx = class(TPopupList)
  protected
    procedure WndProc(var Message: TMessage); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

const MN_SELECTITEM = $01E5;

{ TPopupListEx }

procedure TPopupListEx.WndProc(var Message: TMessage);
var hm:HMENU;

begin
  inherited;
  if (Message.Msg = WM_ENTERMENULOOP) and (Message.WParam = 1) then
    begin
      //When the popupwindow is already created, we can ask it's handle
      hm:=FindWindow(PChar('#32768'),nil);
      //Send the MN_SELECTITEM message. The third parameter is the desired menuitem's index.
      SendMessage(hm,MN_SELECTITEM,0,0);
    end;
end;

initialization
  Popuplist.Free; //free the "default", "old" list
  PopupList := TPopupListEx.Create; //create the new one
  // The new PopupList will be freed by
  // finalization section of Menus unit.
end.

Note about other (including the mentioned delphipraxis sample) solutions:

Setting the MenuItem to a highlight state with SetMenuItemInfoW or with HiliteMenuItem won't work, since it's only affect the appearance, but when you hover the mouse over any other item, the first item remains highlighted.

秋风の叶未落 2025-01-21 07:17:12

我相信您被伪造的输入所困。我认为您可以通过 PostMessage 将向下/向上消息发送至 GetFocus。这使得它至少是本地黑客而不是全球黑客。您可能需要一个钩子来捕获正确的消息以触发黑客攻击。

理想情况下,这应该记录在此处,但遗憾的是它不是。要确切了解 Microsoft 的做法的唯一方法是在 98/2000/XP 中调试 Explorer。 Explorer 和 Internet Explorer 中这些系统上的菜单实现是从工具栏按钮下拉的上下文菜单,模拟菜单栏。

I believe you are stuck with faking input. I think you can PostMessage key down/up messages to GetFocus. That makes it at least a local hack instead of global. You might need a hook to catch the right message to trigger the hack.

Ideally this should be documented here but sadly it's not. The only way to know for sure how Microsoft does it would be to debug Explorer in 98/2000/XP. The menu implementation on these systems in Explorer and Internet Explorer is a context menu dropped down from toolbar buttons, faking a menu bar.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文