[ShellExtension]上下文扩展-IContextMenu实现
2016-02-07 14:54
706 查看
还是先亮源码下载地址:https://git.oschina.net/xiangmu110/template_IContextMenuExt
以下所讲与提供下载的源码不同,但都是一个模子出来的。
下面这段程序实现的是在所有类型文件的右键扩展菜单中添加“获取文件大小”和“显示全路径”两个菜单,并实现其功能并支持多文件。
首先创建一个名为“ContextMenu”的工程,并添加一个简称为“CalcFileSizeExt”的“ATL简单对象”,如果不清楚的请看该文章:
[ShellExtension]图标扩展-IShellIconlayIdentifier实现
这篇文章的开头讲解了,我就不再赘述了。
现在开始讲解如何继承实现“IContextMenu”和“IShellExtInit”接口来达成目的。
同图标扩展文章中所讲的一样,需要将这个程序注册到注册表中去。这次不是注册到资源管理器下,而是注册到对应的文件下。下面这段代码,是将其注册到所有类型的文件的上下文菜单中。
注册与反注册及删除均和图标扩展文章中所讲的一模一样,这里就不再赘述。
下面是运行效果图。
![](http://img.blog.csdn.net/20160208185549489)
![](http://img.blog.csdn.net/20160208185602833)
![](http://img.blog.csdn.net/20160208185613974)
以下所讲与提供下载的源码不同,但都是一个模子出来的。
下面这段程序实现的是在所有类型文件的右键扩展菜单中添加“获取文件大小”和“显示全路径”两个菜单,并实现其功能并支持多文件。
首先创建一个名为“ContextMenu”的工程,并添加一个简称为“CalcFileSizeExt”的“ATL简单对象”,如果不清楚的请看该文章:
[ShellExtension]图标扩展-IShellIconlayIdentifier实现
这篇文章的开头讲解了,我就不再赘述了。
现在开始讲解如何继承实现“IContextMenu”和“IShellExtInit”接口来达成目的。
// CalcFileSizeExt.h : CCalcFileSizeExt 的声明 #pragma once #include "resource.h" // 主符号 #include "ContextMenu_i.h" #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA) #error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。" #endif # include <vector>//引入头文件,会使用的vector using namespace ATL; // CCalcFileSizeExt class ATL_NO_VTABLE CCalcFileSizeExt : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CCalcFileSizeExt, &CLSID_CalcFileSizeExt>, public IDispatchImpl<ICalcFileSizeExt, &IID_ICalcFileSizeExt, &LIBID_ContextMenuLib, /*wMajor =*/ 1, /*wMinor =*/ 0>, public IShellExtInit,//接收explorer传递的信息 public IContextMenu//实现右键扩展 { public: CCalcFileSizeExt() { } DECLARE_REGISTRY_RESOURCEID(IDR_CALCFILESIZEEXT) BEGIN_COM_MAP(CCalcFileSizeExt) COM_INTERFACE_ENTRY(ICalcFileSizeExt) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IShellExtInit)//添加入口点 COM_INTERFACE_ENTRY(IContextMenu)//添加入口点 END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } //用于保存文件路径 std::vector<std::wstring> m_vtFilePath; //IShellExtInit的接口实现 virtual HRESULT STDMETHODCALLTYPE Initialize(_In_opt_ PCIDLIST_ABSOLUTE pidlFolder, _In_opt_ IDataObject *pdtobj, _In_opt_ HKEY hkeyProgID); //IContextMenu的接口实现 virtual HRESULT STDMETHODCALLTYPE QueryContextMenu(_In_ HMENU hmenu, _In_ UINT indexMenu, _In_ UINT idCmdFirst, _In_ UINT idCmdLast, _In_ UINT uFlags); virtual HRESULT STDMETHODCALLTYPE InvokeCommand(_In_ CMINVOKECOMMANDINFO *pici); virtual HRESULT STDMETHODCALLTYPE GetCommandString(_In_ UINT_PTR idCmd, _In_ UINT uType, _Reserved_ UINT *pReserved, _Out_writes_bytes_((uType & GCS_UNICODE) ? (cchMax * sizeof(wchar_t)) : cchMax) _When_(!(uType & (GCS_VALIDATEA | GCS_VALIDATEW)), _Null_terminated_) CHAR *pszName, _In_ UINT cchMax); //获取所有文件大小 void ShowAllFileSIze(); //显示所有文件路径 void ShowAllFilePath(); }; OBJECT_ENTRY_AUTO(__uuidof(CalcFileSizeExt), CCalcFileSizeExt)
// CalcFileSizeExt.cpp : CCalcFileSizeExt 的实现 #include "stdafx.h" #include "CalcFileSizeExt.h" // CCalcFileSizeExt HRESULT STDMETHODCALLTYPE CCalcFileSizeExt::Initialize(_In_opt_ PCIDLIST_ABSOLUTE pidlFolder, _In_opt_ IDataObject *pdtobj, _In_opt_ HKEY hkeyProgID) { FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; STGMEDIUM stg = { TYMED_HGLOBAL }; HDROP hDrop; //在数据对象中查找CF_HDROP类型数据 if (FAILED(pdtobj->GetData(&fmt, &stg))) {//没有该数据 return E_INVALIDARG; } //获取指向实际数据的指针 hDrop = (HDROP)GlobalLock(stg.hGlobal); //检查 if (NULL == hDrop) { return E_INVALIDARG; } HRESULT hr = S_OK; do { //有效性检查,保证最少有一个文件名 UINT uNumFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); if (0 == uNumFiles) { hr = E_INVALIDARG; break; } WCHAR tFilePath[MAX_PATH]; //取得所有所有文件的文件名 for (UINT i = 0; i < uNumFiles; i++) { if (0 != DragQueryFileW(hDrop, i, tFilePath, MAX_PATH)) { //存放如文件列表中 m_vtFilePath.push_back(tFilePath); } else {//有错误 hr = E_INVALIDARG; break; } } } while (0); //释放资源 GlobalUnlock(stg.hGlobal); ReleaseStgMedium(&stg); return hr; } HRESULT STDMETHODCALLTYPE CCalcFileSizeExt::QueryContextMenu(_In_ HMENU hmenu, _In_ UINT indexMenu, _In_ UINT idCmdFirst, _In_ UINT idCmdLast, _In_ UINT uFlags) { if (uFlags & CMF_DEFAULTONLY) {//此时不做任何处理 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); } BOOL bRet = false; int nCmdId = idCmdFirst; //添加按钮 bRet = InsertMenu(hmenu, indexMenu, MF_STRING | MF_BYPOSITION, nCmdId, _T("获取文件大小")); //设置按钮的图标 HBITMAP hBitmap = LoadBitmap(_AtlBaseModule.GetModuleInstance(), MAKEINTRESOURCE(IDB_BITMAP1)); bRet = SetMenuItemBitmaps(hmenu, indexMenu, MF_BYPOSITION, hBitmap, NULL); ++indexMenu;//序号递增 ++nCmdId;//命令ID递增 bRet = InsertMenu(hmenu, indexMenu, MF_STRING | MF_BYPOSITION, nCmdId, _T("显示全路径")); //最后一个参数为创建的菜单的个数 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 2); } //对加入的菜单的事件响应 HRESULT STDMETHODCALLTYPE CCalcFileSizeExt::InvokeCommand(_In_ CMINVOKECOMMANDINFO *pici) { //如果lpVerb指向一个字符串,忽略此次调用 if (0 != HIWORD(pici->lpVerb)) { return E_INVALIDARG; } //检查lpVerb是不是添加的命令,并进行响应 switch (LOWORD(pici->lpVerb))//为创建菜单时的indexMenu数值 { case 0: ShowAllFileSIze(); break; case 1: ShowAllFilePath(); break; default: return E_INVALIDARG; } return S_OK; } HRESULT STDMETHODCALLTYPE CCalcFileSizeExt::GetCommandString(_In_ UINT_PTR idCmd, _In_ UINT uType, _Reserved_ UINT *pReserved, _Out_writes_bytes_((uType & GCS_UNICODE) ? (cchMax * sizeof(wchar_t)) : cchMax) _When_(!(uType & (GCS_VALIDATEA | GCS_VALIDATEW)), _Null_terminated_) CHAR *pszName, _In_ UINT cchMax) { //是否是获取提示,设置帮助字符串 if (uType & GCS_HELPTEXT) { //选择内容 LPCTSTR szPrompt = NULL; switch (idCmd) { case 0: szPrompt = _T("Help:显示获取选取文件的总大小。"); break; case 1: szPrompt = _T("Help:显示选择文件的全路径。"); break; default: return E_INVALIDARG; } //字符编码 USES_CONVERSION; if (uType & GCS_UNICODE) { lstrcpynW((LPWSTR)pszName, T2CW(szPrompt), cchMax); } else { lstrcpynA(pszName, T2CA(szPrompt), cchMax); } } return S_OK; } //显示文件大小 void CCalcFileSizeExt::ShowAllFileSIze() { struct _stat status; _off_t allSize = 0; std::wstring msg; std::wstring errorMsg = L"获取以下文件大小失败:"; bool isError = false; for each (std::wstring var in m_vtFilePath) { //获取文件信息 if (0 == _wstat(var.c_str(), &status)) { allSize += status.st_size; } else { isError = true; errorMsg += var; errorMsg += L"\n"; } } WCHAR buff[10]; msg += L"文件个数:"; _itow_s((int)m_vtFilePath.size(), buff, 10); msg += buff; msg += L"\n文件大小为(byte):"; _itow_s(allSize, buff, 10); msg += buff; if (isError) { msg += errorMsg; } MessageBoxW(NULL, msg.c_str(), L"获取文件大小", MB_OK); } //显示文件路径 void CCalcFileSizeExt::ShowAllFilePath() { std::wstring msg; for each (std::wstring var in m_vtFilePath) { msg += var; msg += L"\n"; } MessageBoxW(NULL, msg.c_str(), L"获取文件路径", MB_OK); }
同图标扩展文章中所讲的一样,需要将这个程序注册到注册表中去。这次不是注册到资源管理器下,而是注册到对应的文件下。下面这段代码,是将其注册到所有类型的文件的上下文菜单中。
HKCR { NoRemove * { NoRemove shellex { NoRemove ContextMenuHandlers { ForceRemove CalcFileSizeExt = s '{3E9A1A8A-1311-48F1-9843-879C758E49A0}' } } } }
注册与反注册及删除均和图标扩展文章中所讲的一模一样,这里就不再赘述。
下面是运行效果图。
相关文章推荐
- 如何重装TCP/IP协议
- Windows 8 官方高清壁纸欣赏与下载
- 谁是桌面王者?Win PK Linux三大镇山之宝
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- Windows Clang开发环境备忘
- 从Windows系统下访问Linux分区相关软件
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- Windows下搭建本地SVN服务器
- 利用开源软件打造自己的全功能远程工具
- Visual Studio 2012 示例代码浏览器 - 数以千计的开发示例近在手边,唾手可得
- Visual Studio 2012 示例代码浏览器 - 数以千计的开发示例近在手边,唾手可得
- 微软镜像下载
- windows server域用户提升到本地更高权限组中的方法
- 使用命令修改注册表键值及权限
- 通过手机、电脑远程开关机,Windows和linux机手机,电脑相互控制
- Windows XP最新应用技巧大荟萃
- Windows 系统组策略应用全攻略(上)第1/2页