当前位置 : 主页 > 编程语言 > delphi >

delphi – 通过IContextMenu循环

来源:互联网 收集:自由互联 发布时间:2021-06-23
如何遍历IContextMenu的所有项目和子项并列出所有可用的动词?到目前为止,我从JCL中提取了这个工作代码: function DisplayContextMenuPidl(const Handle: THandle; const Folder: IShellFolder; Item: PItemIdList
如何遍历IContextMenu的所有项目和子项并列出所有可用的动词?到目前为止,我从JCL中提取了这个工作代码:

function DisplayContextMenuPidl(const Handle: THandle; const Folder: IShellFolder; Item: PItemIdList; Pos: TPoint): Boolean;
var
  Cmd: Cardinal;
  ContextMenu: IContextMenu;
  ContextMenu2: IContextMenu2;
  Menu: HMENU;
  CommandInfo: TCMInvokeCommandInfo;
  CallbackWindow: THandle;
  vteste : string;
begin
  Result := False;
  if (Item = nil) or (Folder = nil) then
    Exit;
  Folder.GetUIObjectOf(Handle, 1, Item, IID_IContextMenu, nil,
    Pointer(ContextMenu));
  if ContextMenu <> nil then
  begin
    Menu := CreatePopupMenu;
    if Menu <> 0 then
    begin
      if Succeeded(ContextMenu.QueryContextMenu(Menu, 0, 1, $7FFF, CMF_EXPLORE)) then
      begin
        CallbackWindow := 0;
        if Succeeded(ContextMenu.QueryInterface(IContextMenu2, ContextMenu2)) then
        begin
          CallbackWindow := CreateMenuCallbackWnd(ContextMenu2);
        end;
        ClientToScreen(Handle, Pos);
        Cmd := Cardinal(TrackPopupMenu(Menu, TPM_LEFTALIGN or TPM_LEFTBUTTON or TPM_RIGHTBUTTON or TPM_RETURNCMD, Pos.X, Pos.Y, 0, CallbackWindow, nil));
        if Cmd <> 0 then
        begin
          ResetMemory(CommandInfo, SizeOf(CommandInfo));
          CommandInfo.cbSize := SizeOf(TCMInvokeCommandInfo);
          CommandInfo.hwnd := Handle;
          CommandInfo.lpVerb := MakeIntResourceA(Cmd - 1);
          CommandInfo.nShow := SW_SHOWNORMAL;
          Result := Succeeded(ContextMenu.InvokeCommand(CommandInfo));
        end;
        if CallbackWindow <> 0 then
          DestroyWindow(CallbackWindow);
      end;
      DestroyMenu(Menu);
    end;
  end;
end;

此代码工作正常,它显示上下文菜单.我需要调整它,以便它可以列出(可能是一个日志文件)所有菜单和子菜单动词.

编辑

为了澄清,我假设我有这个上下文菜单:

我想记录这样的事情:

项目动词

open = open
properties =属性
发送到= sendto
发送到bluetooh = xxx

编辑

如果某人有另一种获取动词或通过显示文本调用项目的方式,我也会很感激.

要枚举上下文菜单的项目,可以使用Windows Menu functions: GetMenuItemCount, GetMenuItemInfo, GetSubMenu.

使用这些函数我写了这个函数

uses
JclShell,
ShlObj;

function DisplayContextMenuInfo( const Folder: IShellFolder; Item: PItemIdList; List :TStrings): Boolean;

  function GetMenuItemCaption(const hSubMenu: HMENU; const MenuId: Integer): string;
  var
    MenuItemInfo: TMenuItemInfo;
  begin
    MenuItemInfo.cbSize := SizeOf(MenuItemInfo);
    MenuItemInfo.fMask := MIIM_STRING;
    SetLength(Result, 1024*Sizeof(Char));
    MenuItemInfo.dwTypeData := PChar(Result);
    MenuItemInfo.cch        := Length(Result)-1;
    if not GetMenuItemInfo(hSubMenu, MenuId, False, MenuItemInfo) then
      RaiseLastOSError;
    SetLength(Result, MenuItemInfo.cch*Sizeof(Char));
  end;

  Procedure LogGetMenuInfo(Menu: HMENU);
  var
    i             : Integer;
    ItemsCount    : Integer;
    MenuId        : Cardinal;
    Caption       : string;
  begin
     ItemsCount:=GetMenuItemCount(Menu);

     List.Add(Format('Number of items %d ',[ItemsCount]));
      for i:= 0 to ItemsCount - 1 do
      begin
        MenuId:=GetMenuItemID(Menu,i);

        case MenuId of

         Cardinal(-1) : begin
                          List.Add('');
                          List.Add(Format('Sub Menu',[]));
                          LogGetMenuInfo(GetSubMenu(Menu,i));
                        end;
         0            :

         else
                        begin
                          Caption:=GetMenuItemCaption(Menu, MenuId);
                          List.Add(Format('MenuId (Cmd) %d Caption %s  ',[MenuId,Caption]))
                        end;

        end;
      end;

  end;


var
  ContextMenu: IContextMenu;
  Menu: HMENU;

begin
  Result := False;
  if (Item = nil) or (Folder = nil) then  Exit;
  Folder.GetUIObjectOf(0, 1, Item, IID_IContextMenu, nil,  Pointer(ContextMenu));
  if ContextMenu <> nil then
  begin
    Menu := CreatePopupMenu;
    try
      if Menu <> 0 then
        if Succeeded(ContextMenu.QueryContextMenu(Menu, 0, 1, $7FFF, CMF_EXPLORE)) then
           LogGetMenuInfo(Menu);
    finally
      DestroyMenu(Menu);
    end;
  end;
end;

并以这种方式打电话

var
  ItemIdList: PItemIdList;
  Folder    : IShellFolder;
  FileName  : string;
begin
  FileName:= 'C:\Users\Dexter\Downloads\VirtualTreeview.pdf';
  ItemIdList := PathToPidlBind(FileName, Folder);
  if ItemIdList <> nil then
  begin
    DisplayContextMenuInfo( Folder, ItemIdList, Memo1.lines);
    PidlFree(ItemIdList);
  end;
end;

这将填充作为参数传递的TStrings,其信息如下:

Number of items 26 
MenuId (Cmd) 141 Caption Open with Adobe Reader X
MenuId (Cmd) 142 Caption &Open
MenuId (Cmd) 143 Caption &Print
MenuId (Cmd) 146 Caption Run &Sandboxed
MenuId (Cmd) 140 Caption Analizar con &AVG
Sub Menu
Number of items 28 
MenuId (Cmd) 105 Caption Add To Send To
MenuId (Cmd) 106 Caption Add To Templates
MenuId (Cmd) 107 Caption Change Date && Time
MenuId (Cmd) 108 Caption Change Extension: pdf
MenuId (Cmd) 109 Caption Choose Program
MenuId (Cmd) 110 Caption Command Prompt
MenuId (Cmd) 111 Caption Copy/Move To Folder
MenuId (Cmd) 112 Caption Copy Path
MenuId (Cmd) 113 Caption Delete On Reboot
MenuId (Cmd) 114 Caption Duplicate File
MenuId (Cmd) 115 Caption Encrypt File
MenuId (Cmd) 116 Caption Explore Rooted
MenuId (Cmd) 117 Caption Extended Delete
MenuId (Cmd) 118 Caption Extended Search && Replace

现在使用此功能,您可以传递要执行的menuid(cmd)

function InvokeContextMenuCommand(const Comnand: Cardinal; const Folder: IShellFolder; Item: PItemIdList): Boolean;
var
  ContextMenu   : IContextMenu;
  CommandInfo   : TCMInvokeCommandInfo;
  Menu          : HMENU;
  CallbackWindow: THandle;
begin
  Result := False;
  if Comnand=0 then exit;

  if (Item = nil) or (Folder = nil) then  Exit;
    Folder.GetUIObjectOf(0, 1, Item, IID_IContextMenu, nil,  Pointer(ContextMenu));
  if ContextMenu <> nil then
   begin
    Menu := CreatePopupMenu;
    try
      if Menu <> 0 then
      if Succeeded(ContextMenu.QueryContextMenu(Menu, 0, 1, $7FFF, CMF_EXPLORE)) then
      begin
        CallbackWindow:=0;
        TrackPopupMenu(Menu, TPM_LEFTALIGN or TPM_LEFTBUTTON or  TPM_RIGHTBUTTON or TPM_RETURNCMD, 0, 0, 0, CallbackWindow, nil);
        ZeroMemory(@CommandInfo, SizeOf(CommandInfo));
        CommandInfo.cbSize := SizeOf(TCMInvokeCommandInfo);
        CommandInfo.hwnd   := 0;
        CommandInfo.lpVerb := MakeIntResourceA(Comnand - 1);
        CommandInfo.nShow  := SW_SHOWNORMAL;
        Result := Succeeded(ContextMenu.InvokeCommand(CommandInfo));
      end;
    finally
     DestroyMenu(Menu);
    end;
   end;
end;

以这种方式打电话

var
  ItemIdList: PItemIdList;
  Folder    : IShellFolder;
  FileName  : string;
begin
  FileName:= 'C:\Users\Dexter\Downloads\VirtualTreeview.pdf';
  ItemIdList := PathToPidlBind(FileName, Folder);
  if ItemIdList <> nil then
  begin
    //calling the 141 Menuid = `Open with Adobe Reader X`
    InvokeContextMenuCommand(141,Folder, ItemIdList);
    PidlFree(ItemIdList);
  end;
end;
网友评论