桌面右键弹出二级菜单
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}'
}
}
}
}
}
这几天一直在做壁纸。翻了一些资料,终于做出来了。
几个函数:
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}'
}
}
}
}
}
相关文章推荐
- 桌面点击右键,菜单向左弹出,如何改为向右弹出菜单
- 如何解决桌面右键菜单弹出慢的问题
- Windows7点击桌面右键没有反应无菜单弹出
- ext desktop桌面右键弹出菜单代码
- Win7桌面右键弹出菜单慢解决方法!超实用!
- ext desktop桌面图标的右键弹出菜单代码
- opera设置双击弹出右键菜单
- 利用ObjectAnimator编写弹出式二级菜单
- 【CefSharp】 禁用右键菜单 与 控制弹出窗口的方式(限版本39.0.0.1)
- Swing创建带图标的右键弹出菜单
- 如何用程序实现增加二级windows文件右键菜单
- 鼠标右键弹出菜单
- VC Windows shell扩展编程(为系统右键菜单添加二级菜单傻瓜教程)
- 浏览器右键弹出菜单复制
- 右键单击列表控件的一项---弹出菜单
- C# Tips: 1.右键单击dataGrivdView选中该行并弹出菜单
- C#用鼠标钩子屏蔽任务栏右键弹出菜单
- 右键弹出div,模拟右键菜单
- Java中JTextField或JTextArea右键弹出菜单
- 清除所有多余的桌面右键菜单