Loop through IContextMenu

前端 未结 2 1984
执念已碎
执念已碎 2021-01-14 10:37

How do I loop through all items and sub items of a IContextMenu and list all available verbs? So far, I have this working code extracted from JCL:

function D         


        
2条回答
  •  半阙折子戏
    2021-01-14 11:31

    After you call QueryContextMenu your menu will be mostly populated. You know your menu's handle, so can iterate its items and get the information you need.

    function DisplayContextMenuPidl(const Handle: THandle; const Folder: IShellFolder; Item: PItemIdList; Pos: TPoint): Boolean;
    
    //++
      procedure RecurseItems(const Menu: HMENU; Strings: TStrings; Indent: Integer = 0);
    
        function GetItemString(Parent: HMENU; Item: Integer): string;
        begin
          SetLength(Result, GetMenuString(Parent, Item, nil, 0, MF_BYPOSITION) + 1);
          GetMenuString(Parent, Item, PChar(Result), Length(Result), MF_BYPOSITION);
        end;
    
      var
        i: Integer;
        ItemInfo: TMenuItemInfo;
      begin
        for i := 0 to GetMenuItemCount(Menu) - 1 do begin
          FillChar(ItemInfo, SizeOf(ItemInfo), 0);
          ItemInfo.cbSize := SizeOf(ItemInfo);
          ItemInfo.fMask := MIIM_SUBMENU or MIIM_TYPE;
          GetMenuItemInfo(Menu, i, True, ItemInfo);
          if ItemInfo.fType <> MFT_SEPARATOR then
            Strings.Add(StringOfChar('-', Indent * 2) + GetItemString(Menu, i));
          if ItemInfo.hSubMenu <> 0 then
            RecurseItems(ItemInfo.hSubMenu, Strings, Indent + 1);
        end;
      end;
    //--
    
    var
      Cmd: Cardinal;
      ContextMenu: IContextMenu;
      ContextMenu2: IContextMenu2;
      ...
    
      begin
        Menu := CreatePopupMenu;
        if Menu <> 0 then
        begin
          if Succeeded(ContextMenu.QueryContextMenu(Menu, 0, 1, $7FFF, CMF_EXPLORE)) then
    
    //++
          Memo1.Clear;
          RecurseItems(Menu, Memo1.Lines);
    //--
    
          begin
            CallbackWindow := 0;
          ..
    


    It won't really make any difference if you get items' text after you retrieve an 'IContextMenu2' interface or not, because sub menus like 'Send To' or 'New' are not populated until their parent menu item is selected. There's no way in that routine you'll have access to them. Note below the two items that have failed to expand in the sample output of the above code:

    &Open
    Run as &administrator
    Troubleshoot compatibilit&y
    7-Zip
    --Open archive
    --Extract files...
    --Extract Here
    --Test archive
    --Add to archive...
    S&hare with
    --
    Pin to Tas&kbar
    Pin to Start Men&u
    Restore previous &versions
    Se&nd to
    --
    Cu&t
    &Copy
    Create &shortcut
    &Delete
    P&roperties
    


    Messages to show the sub-items will be passing through your CallbackWindow's WndProc, like WM_INITMENUPOPUP, WM_ENTERIDLE, WM_MEASUREITEM, WM_DRAWITEM. But I don't think trying to extract the information there would make any sense at all..

提交回复
热议问题