您的位置:首页 > 编程语言

如何编程实现扩展右键菜单之二:使用子菜单

2010-04-08 17:23 701 查看
      在上一篇教程中,我们已经实现了在资源管理器的右键菜单中增加自己的菜单项。本文中,笔者将介绍如何将自己的菜单项分组到子菜单中。如果需要添加的菜单项比较多,则使用子菜单将有助于提高右键菜单的友好性。

      本文中的实例是在上一篇教程的基础上进行修改,在上一篇的基础上,增加一个菜单项用于使用记事本打开所选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就可以正确的删除我们添加的子菜单了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息