您的位置:首页 > 其它

桌面右键弹出二级菜单

2013-04-25 16:14 302 查看
桌面右键弹出你添加的二级菜单。COM技术,ATL。

这几天一直在做壁纸。翻了一些资料,终于做出来了。

几个函数:

SHGetSpecialFolderPath用于获取特殊文件夹路径

SHGetPathFromIDList从id list获取路径

 

1.新建ATL工程,选支持MFC(因为要使用CString)和合并存根两个选项(因为不需要远程COM)。

 

2.右键工程,选添加类-ATL-ATL简单对象。取个名称。叫做SimpleShlExt。

 

3.下面就该添加SimpleShlExt.h和SimpleShlExt.cpp中的代码了

因为要用到这两个接口IShellExtInit和IContextMenu这两个接口,所以CSimpleShlExt要继承这两个接口,并实现之

class ATL_NO_VTABLE CSimpleShlExt :

 public CComObjectRootEx<CComSingleThreadModel>,

 public CComCoClass<CSimpleShlExt, &CLSID_SimpleShlExt>,

 public IDispatchImpl<ISimpleShlExt, &IID_ISimpleShlExt, &LIBID_SimpleExtLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,

 public IShellExtInit,//这俩是新添的。用于ShellExt的初始化

 public IContextMenu//用于右键的上下文菜单

 

4.为CSimpleShlExt实现如下的方法// IShellExtInit

 STDMETHOD(Initialize)(LPCITEMIDLIST, LPDATAOBJECT, HKEY);

 // IContextMenu

 STDMETHOD(GetCommandString)(UINT_PTR, UINT, UINT*, LPSTR, UINT);

 STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO);

 STDMETHOD(QueryContextMenu)(HMENU, UINT, UINT, UINT, UINT);

 

5.在实现文件中CSimpleShlExt.cpp,实现这四种方法 

STDMETHODIMP CSimpleShlExt::Initialize( LPCITEMIDLIST pidlFolder , LPDATAOBJECT pDataObj , HKEY hProgID )

{

 //MessageBox(0,0,0,0);

 if (pDataObj)//如果鼠标选中了什么,这时候操作结束。做shellex程序一定要负责,要不这个崩溃了,加载这个dll的explorer也会崩溃

 {

  return E_INVALIDARG;

 }

 TCHAR szCurrentPath[MAX_PATH] = {0};

 TCHAR szDesktopPath[MAX_PATH] = {0};

 //这两步当然是为了,你在桌面右键,菜单里会有效果,在其他文件夹,就没有效果

 SHGetSpecialFolderPath( NULL , szDesktopPath , CSIDL_DESKTOP , FALSE);//获取桌面文件夹的路径

 SHGetPathFromIDList ( pidlFolder, szCurrentPath );//获取当前用户点击的路竟

 int ret = lstrcmp(szCurrentPath,szDesktopPath);

 if (ret)

 {

  return E_INVALIDARG;

 }

 return S_OK;

}

 

6.建立右键菜单项 STDMETHODIMP CSimpleShlExt::QueryContextMenu( HMENU hmenu , UINT uMenuIndex , UINT uidFirstCmd , UINT uidLastCmd , UINT uFlags )

{

 UINT uCmdId = uidFirstCmd;

 // 如果标志包含 CMF_DEFAULTONLY 我们不作任何事情.

 if ( uFlags & CMF_DEFAULTONLY )

 {

  return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 );

 }

 //InsertMenu ( hmenu, uMenuIndex, MF_BYPOSITION, uidFirstCmd, _T("SimpleShlExt Test Item") );

 //++uMenuIndex;

 HMENU hSubMenu = CreateMenu();

 if (hSubMenu)

 {

  InsertMenu(hSubMenu , 0 , MF_STRING|MF_BYPOSITION , uCmdId++ , TEXT("下一张"));

  //SetMenuItemBitmaps(hSubMenu , 0 , MF_BYPOSITION , nextBitmap , nextBitmap);

  InsertMenu(hSubMenu , 1 , MF_STRING|MF_BYPOSITION , uCmdId++ , TEXT("打开壁纸"));

  //SetMenuItemBitmaps(hSubMenu , 1 , MF_BYPOSITION , openBitmap , openBitmap);

  InsertMenu(hSubMenu , 2, MF_BYPOSITION | MF_SEPARATOR , uCmdId++ , NULL);

  InsertMenu(hSubMenu , 3 , MF_STRING|MF_BYPOSITION , uCmdId++ , TEXT("保存当前壁纸"));

  //SetMenuItemBitmaps(hSubMenu , 3 , MF_BYPOSITION , saveBitmap , saveBitmap);

 }

 InsertMenu(hmenu , uMenuIndex , MF_BYPOSITION | MF_STRING | MF_POPUP , (UINT_PTR)hSubMenu , TEXT("壁纸"));

 return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, uCmdId-uidFirstCmd+1/*这个不能错,要不就少菜单项了*/ );

}

 

7.显示帮助信息STDMETHODIMP CSimpleShlExt::GetCommandString( UINT_PTR idCmd , UINT uFlags, UINT* pwReserved , LPSTR pszName , UINT cchMax )

{

 return S_OK;//啥都不做

}

 

8.实现各个菜单的响应STDMETHODIMP CSimpleShlExt::InvokeCommand( LPCMINVOKECOMMANDINFO pCmdInfo )

{

 if (0 != HIWORD(pCmdInfo->lpVerb))

 {

  return E_INVALIDARG;

 }

 

 switch(LOWORD(pCmdInfo->lpVerb))//根据用户选择了那一项,对应操作

 {

 case 0:

  MessageBox(pCmdInfo->hwnd , _T("下一张") , _T("SimpleShlExt") , MB_ICONINFORMATION);

  return S_OK;

  break;

 case 1:

  MessageBox(pCmdInfo->hwnd , _T("打开壁纸") , _T("SimpleShlExt") , MB_ICONINFORMATION);

  return S_OK;

  break;

 case 3:

  MessageBox(pCmdInfo->hwnd , _T("保存当前壁纸") , _T("SimpleShlExt") , MB_ICONINFORMATION);

  return S_OK;

  break;

 default:

  return E_INVALIDARG;

  break;

 }

}

 9.最后一步。当然是注册注册表了。要不explorer怎么知道你的程序呢在你的工程的rgs文件写下面的注册信息。可以看到两个rgs文件,一个是SimpleShlExt.rgs,这个里面是注册该组件到CLSID下面。SimpleExt.rgs是你要修改成下面的。因为你要支持目录的右键扩展HKCR

{

    NoRemove Directory

    {

        NoRemove Background

        {

            NoRemove shellex

            {

    NoRemove ContextMenuHandlers

    {

     ForceRemove WallPaper = s '{30A75CFD-6E16-4CA0-9D83-3D8E3022E3DB}'

    }

            }

        }

    }

}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: