Reputation: 6200
How do I enumerate the shell context menu item using Windows API? I need to do it in pure C.
Upvotes: 0
Views: 1493
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
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
Reputation: 16896
Raymond Chen wrote an eleven part series explaining how to do this. It's really not straightforward.
Upvotes: 0