应用程序实现上下文菜单处理程序接口IContextMenu,以将菜单项添加到文件对象的上下文菜单。当用户用鼠标按钮2点击对象时,shell会显示对象的上下文菜单。菜单项可以是特定类别(即适用于特定类型的所有文件)或特定于实例(即适用于单个文件)。
当用户通过使用鼠标按钮2单击文件对象时,系统将对象的上下文菜单的地址传递给上下文菜单处理程序,该处理程序应该仅使用句柄将菜单添加到菜单。处理程序不应该删除或修改现有的菜单项,因为其他处理程序可能在它之前或之后添加项。此外,在调用所有上下文菜单处理程序之后,shell将菜单添加到菜单中。
上下文菜单处理程序在应用程序信息区域内的的shellex键下的注册表中输入。ContextMenuHandlers键列出了包含每个上下文菜单处理程序的CLSID的子项的名称。以下显示ContextMenuHandlers键的示例。
ContextMenuHandlers
{00000000-1111-2222-3333-00000000000001}
您可以为文件类型注册多个上下文菜单处理程序。
除了标准的IUnknown成员函数之外,上下文菜单处理程序接口使用InvokeCommand,InvokeCommand和GetCommandString成员函数。
当用户选择由上下文菜单处理程序添加的菜单项之一时,shell会调用处理程序的IContextMenu::InvokeCommand成员函数,让处理程序处理该命令。如果为文件类型注册了多个上下文菜单处理程序,则ContextMenuHandlers键的值确定命令的顺序。
当系统即将显示文件对象的上下文菜单(或菜单栏上的“文件菜单”)时,系统将调用上下文菜单处理程序的QueryContextMenu成员函数。上下文菜单处理程序通过调用InsertMenu函数将位置(MF_POSITION)的菜单项直接插入到上下文菜单中。以下示例显示菜单项必须是字符串项(MF_STRING)。
STDMETHODIMP CShellExt :: QueryContextMenu(HMENU hMenu,
UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags)
{
UINT idCmd = idCmdFirst;
char szMenuText[64];
char szMenuText2[64];
char szMenuText3[64];
char szMenuText4[64];
BOOL bAppendItems=TRUE;
if ((uFlags & 0x000F) == CMF_NORMAL) {
lstrcpy(szMenuText, "&New .GAK menu 1, Normal File");
lstrcpy(szMenuText2, "&New .GAK menu 2, Normal File");
lstrcpy(szMenuText3, "&New .GAK menu 3, Normal File");
lstrcpy(szMenuText4, "&New .GAK menu 4, Normal File");
} else if(uFlags & CMF_VERBSONLY){
lstrcpy(szMenuText, "&New .GAK menu 1, Shortcut File");
lstrcpy(szMenuText2, "N&ew .GAK menu 2, Shortcut File");
lstrcpy(szMenuText3, "&New .GAK menu 3, Shortcut File");
lstrcpy(szMenuText4, "&New .GAK menu 4, Shortcut File");
} else if(uFlags & CMF_EXPLORE){
lstrcpy(szMenuText,“{989 796 005}新.GAK菜单1,
Normal File right click in Explorer");
lstrcpy(szMenuText2,“N {989 796 005} EW .GAK菜单2,
Normal File right click in Explorer");
lstrcpy(szMenuText3,“{989 796 005}新.GAK菜单3,
Normal File right click in Explorer");
lstrcpy(szMenuText4,“{989 796 005}新.GAK菜单4,
Normal File right click in Explorer");
} else if(uFlags & CMF_DEFAULTONLY){
bAppendItems = FALSE;
} else {
char szTemp[32];
bAppendItems = FALSE;
}
if(bAppendItems){en
InsertMenu(hMenu,indexMenu ++,MF_SEPARATOR | MF_BYPOSITION,
0, NULL);
InsertMenu(hMenu,indexMenu ++,MF_STRING | MF_BYPOSITION,
idCmd++, szMenuText);
InsertMenu(hMenu,indexMenu ++,MF_SEPARATOR | MF_BYPOSITION,
0, NULL);
InsertMenu(hMenu,indexMenu ++,MF_STRING | MF_BYPOSITION,
idCmd++, szMenuText2);
InsertMenu(hMenu,indexMenu ++,MF_SEPARATOR | MF_BYPOSITION,
0, NULL);
InsertMenu(hMenu,indexMenu ++,MF_STRING | MF_BYPOSITION,
idCmd++, szMenuText3);
InsertMenu(hMenu,indexMenu ++,MF_STRING | MF_BYPOSITION,
idCmd++, szMenuText4);
//必须返回添加的菜单项数。
return ResultFromShort(idCmd-idCmdFirst);
}
return NOERROR;
}
当用户选择上下文菜单处理程序添加到上下文菜单中的菜单项时,系统调用InvokeCommand成员函数。以下示例中的InvokeCommand功能处理与上一示例添加的菜单项相关联的命令。
STDMETHODIMP CShellExt :: InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
HRESULT hr = E_INVALIDARG;
//如果lpcmi- > lpVerb的高位字不为NULL,那么
//函数被应用程序调用,lpVerb是一个命令
//应该被激活。否则,shell调用了这个
//函数,而lpcmi- > lpVerb的低位字是
//用户选择的菜单项的标识符。
if(!HIWORD(lpcmi- > lpVerb)){
UINT idCmd = LOWORD(lpcmi->lpVerb);
switch(idCmd){
case 0:
hr = DoGAKMenu1(lpcmi->hwnd, lpcmi->lpDirectory,
lpcmi- lpVerb} {989796004,989796004} {lpcmi- lpParameters,lpcmi- n显??示} {989796004)
break;
case 1:
hr = DoGAKMenu2(lpcmi->hwnd, lpcmi->lpDirectory,
lpcmi- lpVerb} {989796004,989796004} {lpcmi- lpParameters,lpcmi- n显??示} {989796004)
break;
case 2:
hr = DoGAKMenu3(lpcmi->hwnd, lpcmi->lpDirectory,
lpcmi- lpVerb} {989796004,989796004} {lpcmi- lpParameters,lpcmi- n显??示} {989796004)
break;
case 3:
hr = DoGAKMenu4(lpcmi->hwnd, lpcmi->lpDirectory,
lpcmi- lpVerb} {989796004,989796004} {lpcmi- lpParameters,lpcmi- n显??示} {989796004)
break;
}
}
return hr;
}
Windows调用GetCommandString成员函数以获取与语言无关的命令字符串或上下文菜单项的帮助文本。