如何遍历IContextMenu的所有项目和子项并列出所有可用的动词?到目前为止,我从JCL中提取了这个工作代码: function DisplayContextMenuPidl(const Handle: THandle; const Folder: IShellFolder; Item: PItemIdList
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
编辑
如果某人有另一种获取动词或通过显示文本调用项目的方式,我也会很感激.
要枚举上下文菜单的项目,可以使用WindowsMenu 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;