如何编程实现扩展右键菜单之二:使用子菜单
2010-04-08 17:23
701 查看
在上一篇教程中,我们已经实现了在资源管理器的右键菜单中增加自己的菜单项。本文中,笔者将介绍如何将自己的菜单项分组到子菜单中。如果需要添加的菜单项比较多,则使用子菜单将有助于提高右键菜单的友好性。
本文中的实例是在上一篇教程的基础上进行修改,在上一篇的基础上,增加一个菜单项用于使用记事本打开所选TXT文件,同时将我们在这两篇教程中添加的菜单项放到一个子菜单中。建议读者先完成上一篇教程。
一. 错误的方法
有过对菜单编程经验的读者可能很自然的想到,可以使用如下代码添加子菜单
使用这种方法,你确实可以在右键菜单中添加一个子菜单,但是如果你在TXT文件上多次点击右键,然后在选中TXT文本文件时,点击资源管理器的“文件”菜单,你立刻就会发现问题:
“文件”菜单中,我们添加的子菜单重复了多次!这是这么回事儿?
问题的原因是,Windows在释放右键菜单时,会删除由扩展DLL通过QueryContextMenu()方法添加的菜单项,我们知道,QueryContextMenu()的返回值会告诉调用者我们添加了多少个菜单项,Windows将通过此返回值计算需要删除的菜单项的ID。出现上述问题的原因在于,我们添加的子菜单没有ID!因此,这个子菜单无法删除。
二. 正确的方法
解决这个问题的诀窍在于,使用InsertMenuItem()添加我们的子菜单,该API函数可以给子菜单赋一个ID,这样,Windows就可以正常的删除我们添加的子菜单了。如下是正确的代码:
现在,QueryContextMenu()方法返回的菜单项个数是3,且子菜单也有自己的ID,这样,Windows就可以正确的删除我们添加的子菜单了。
本文中的实例是在上一篇教程的基础上进行修改,在上一篇的基础上,增加一个菜单项用于使用记事本打开所选TXT文件,同时将我们在这两篇教程中添加的菜单项放到一个子菜单中。建议读者先完成上一篇教程。
一. 错误的方法
有过对菜单编程经验的读者可能很自然的想到,可以使用如下代码添加子菜单HRESULT CShlExtObj::QueryContextMenu (HMENU hmenu,
UINT uMenuIndex,
UINT uidFirstCmd,
UINT uidLastCmd,
UINT uFlags )
{
if (uFlags & CMF_DEFAULTONLY)
return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
// 创建一个级联菜单
HMENU hSubMenu=CreatePopupMenu();
// 将菜单项添加到子菜单中
InsertMenu (hSubMenu,
0,
MF_BYPOSITION,
uidFirstCmd,
_T("显示文件名称"));
InsertMenu (hSubMenu,
1,
MF_BYPOSITION,
uidFirstCmd+1,
_T("用记事本打开"));
// 将子菜单插入到右键菜单中
InsertMenu (hmenu,
uMenuIndex,
MF_BYPOSITION|MF_POPUP,
(UINT_PTR)hSubMenu,
_T("处理文本文件"));
return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 2 );
}
使用这种方法,你确实可以在右键菜单中添加一个子菜单,但是如果你在TXT文件上多次点击右键,然后在选中TXT文本文件时,点击资源管理器的“文件”菜单,你立刻就会发现问题:
“文件”菜单中,我们添加的子菜单重复了多次!这是这么回事儿?
问题的原因是,Windows在释放右键菜单时,会删除由扩展DLL通过QueryContextMenu()方法添加的菜单项,我们知道,QueryContextMenu()的返回值会告诉调用者我们添加了多少个菜单项,Windows将通过此返回值计算需要删除的菜单项的ID。出现上述问题的原因在于,我们添加的子菜单没有ID!因此,这个子菜单无法删除。
二. 正确的方法
解决这个问题的诀窍在于,使用InsertMenuItem()添加我们的子菜单,该API函数可以给子菜单赋一个ID,这样,Windows就可以正常的删除我们添加的子菜单了。如下是正确的代码:HRESULT CShlExtObj::QueryContextMenu (HMENU hmenu,
UINT uMenuIndex,
UINT uidFirstCmd,
UINT uidLastCmd,
UINT uFlags )
{
if (uFlags & CMF_DEFAULTONLY)
return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
// 创建一个级联菜单
HMENU hSubMenu=CreatePopupMenu();
// 将菜单项添加到子菜单中
InsertMenu (hSubMenu,
0,
MF_BYPOSITION,
uidFirstCmd,
_T("显示文件名称"));
InsertMenu (hSubMenu,
1,
MF_BYPOSITION,
uidFirstCmd+1,
_T("用记事本打开"));
// 将子菜单插入到右键菜单中
MENUITEMINFO mii;
ZeroMemory(&mii, sizeof(mii));
mii.cbSize=sizeof(mii);
mii.fMask = MIIM_SUBMENU | MIIM_STRING | MIIM_ID;
mii.wID = uidFirstCmd+2;
mii.hSubMenu = hSubMenu;
mii.dwTypeData = _T("处理文本文件");
InsertMenuItem ( hmenu, uMenuIndex, TRUE, &mii );
return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 3 );
}
现在,QueryContextMenu()方法返回的菜单项个数是3,且子菜单也有自己的ID,这样,Windows就可以正确的删除我们添加的子菜单了。
相关文章推荐
- 如何编程实现扩展右键菜单之三:调试Shell扩展DLL
- 如何编程实现扩展右键菜单之一:增加自己的菜单项
- 如何动态添加菜单/菜单项、子菜单、右键菜单
- Windows外壳扩展编程之添加右键菜单
- VC Windows shell扩展编程(为系统右键菜单添加二级菜单傻瓜教程)
- 如何动态添加菜单/菜单项、子菜单、右键菜单
- JS实现不使用图片仿Windows右键菜单效果代码
- 使用Delphi开发IE右键菜单扩展
- 使用Delphi开发IE右键菜单扩展
- 使用Delphi开发IE右键菜单扩展
- 如何动态添加菜单/菜单项、子菜单、右键菜单
- chrome扩展学习 右键菜单实现代码
- 图形的绘制,如何使用自定义画笔(颜色,线宽,线形)。如何为程序中添加选项菜单和选项设置对话框,如何使用标准颜色对话框,如何使用字体对话框,在选项对话框中实现预览功能。实现选项对话框和窗口类中的数据交换。如何改变对话框和控件的背景色,如何改变控件的文本颜色,
- 平台如如何实现类似windows的右键菜单
- 如何用程序实现增加二级windows文件右键菜单
- 编程如何实现使用新建的Revit楼板族,创建楼板构件
- Windows外壳扩展编程之添加右键菜单
- 如何实现网页自定义右键菜单?
- 在windows下修改右键菜单以实现使用vs2010快速编译代码
- Matlab 不使用GUI,底层代码实现右键菜单