user877329
user877329

Reputation: 6200

Open Windows Explorer Shell context menu

How do I enumerate the shell context menu item using Windows API? I need to do it in pure C.

Upvotes: 0

Views: 1493

Answers (3)

Anders
Anders

Reputation: 101606

It is a little unclear to me if you want to show a menu or just enumerate the items, this does the latter (Excluding submenus)

HRESULT GetContextMenuForFSItem(PCTSTR path,IContextMenu**ppCM)
{
    PIDLIST_ABSOLUTE pidlAbs;
    HRESULT hr = SHParseDisplayName(path,0,&pidlAbs,0,0);
    if (!hr)
    {
        IShellFolder*pSF;
        PCUITEMID_CHILD pidlLast;
        hr = SHBindToParent(pidlAbs,&IID_IShellFolder,(void**)&pSF,&pidlLast);
        if (!hr)
        {
            hr = pSF->lpVtbl->GetUIObjectOf(pSF,0,1,&pidlLast,&IID_IContextMenu,0,(void**)ppCM);
            pSF->lpVtbl->Release(pSF);
        }
        ILFree(pidlAbs);
    }
    return hr;
}

int main()
{
    CoInitialize(0);
    WCHAR buf[MAX_PATH];
    GetWindowsDirectory(buf,MAX_PATH); /* Arbitrary filesystem item */
    IContextMenu*pCM;
    HRESULT hr = GetContextMenuForFSItem(buf,&pCM);
    if (!hr) 
    {
        HMENU hMenu = CreatePopupMenu();
        hr = pCM->lpVtbl->QueryContextMenu(pCM,hMenu,0,1,0x7fff,0);
        if (hr > 0)
        {
            UINT c=GetMenuItemCount(hMenu), i=0;
            for (; i<c; ++i)
            {
                GetMenuString(hMenu,i,buf,MAX_PATH,MF_BYPOSITION);
                if (GetMenuState(hMenu,i,MF_BYPOSITION)&MF_SEPARATOR) lstrcpy(buf,_T("--separator--"));
                printf("%.2u=%ws\n",i,buf);
                /*
                Call IContextMenu::GetCommandString  to get the verb 
                or IContextMenu::InvokeCommand to execute
                */
            }
        }
        pCM->lpVtbl->Release(pCM);
        DestroyMenu(hMenu);
    }
    CoUninitialize();
    return 0;
}

On my system this prints:

00=&Open
01=--separator--
02=S&hare with
03=Restore previous &versions
04=&Include in library
05=--separator--
06=Se&nd to
07=--separator--
08=Cu&t
09=&Copy
10=--separator--
11=Create &shortcut
12=&Delete
13=--separator--
14=P&roperties

Using COM in C is not fun, switch to C++ if you can...

Upvotes: 1

Roman Ryltsov
Roman Ryltsov

Reputation: 69632

You need to do exactly what Explorer does: for the item in question (file, folder, other shell namespace location) you identify the list of shell extensions. These are COM classes and they implement IContextMenu interface. For every shell extension applicable, you can provide your own menu and request that such extension (handler) populates the menu with its additional items (IContextMenu::QueryContextMenu).

Later on you are free to decide when, where and if you are going to pop this menu up. Should there a need in handle one of those additional handler's commands, you are responsible to fowrward the command to the handler via IContextMenu::InvokeCommand. If you for some reason prefer to automate certain command and invoke it without popping up the menu, you can do it as well.

Links you might be interested in:

Upvotes: 1

arx
arx

Reputation: 16896

Raymond Chen wrote an eleven part series explaining how to do this. It's really not straightforward.

Upvotes: 0

Related Questions