[ShellExtension]属性页扩展-IShellPropSheetExt实现
2016-02-09 00:30
711 查看
还是先亮源码下载地址:https://git.oschina.net/xiangmu110/template_IShellPropSheetExt
以下所讲与提供下载的源码不同,但都是一个模子出来的。
下面代码实现的是在所有类型的文件的属性中添加一页,用于显示该文件的完整路径。支持同时选择多个文件并查看。
首先创建一个名为“ShellPropSheetExt”的工程,并添加一个简称为“FileFullPath”的“ATL简单对象”,如果不清楚的请看该文章:
[ShellExtension]图标扩展-IShellIconlayIdentifier实现
这篇文章的开头讲解了,我就不再赘述了。
现在开始讲解如何继承实现“IShellPropSheetExt”和“IShellExtInit”接口来达成目的。
IDD_PROPPAGE_MEDIUM为添加的属性页资源。
IDI_ICON1为添加的图标资源。
IDC_EDIT为IDD_PROPPAGE_MEDIUM中的一个CEdit控件,用于显示文件路径
最后就是如图标扩展文章中一样,添加注册表项,将该程序注册在所有类型文件下,详细可看图标扩展的文章,这里就不再赘述。
实现效果如下。
到此,功能已经实现,如果还有不明白的地方请留言,本文有许多不足的地方请指正,谢谢。
以下所讲与提供下载的源码不同,但都是一个模子出来的。
下面代码实现的是在所有类型的文件的属性中添加一页,用于显示该文件的完整路径。支持同时选择多个文件并查看。
首先创建一个名为“ShellPropSheetExt”的工程,并添加一个简称为“FileFullPath”的“ATL简单对象”,如果不清楚的请看该文章:
[ShellExtension]图标扩展-IShellIconlayIdentifier实现
这篇文章的开头讲解了,我就不再赘述了。
现在开始讲解如何继承实现“IShellPropSheetExt”和“IShellExtInit”接口来达成目的。
// FileFullPath.h : CFileFullPath 的声明 #pragma once #include "resource.h" // 主符号 #include "ShellPropSheetExt_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; // CFileFullPath class ATL_NO_VTABLE CFileFullPath : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CFileFullPath, &CLSID_FileFullPath>, public IDispatchImpl<IFileFullPath, &IID_IFileFullPath, &LIBID_ShellPropSheetExtLib, /*wMajor =*/ 1, /*wMinor =*/ 0>, public IShellExtInit,//实现初始化接口,用于接收数据 public IShellPropSheetExt//实现属性页接口 { public: CFileFullPath() { } DECLARE_REGISTRY_RESOURCEID(IDR_FILEFULLPATH) BEGIN_COM_MAP(CFileFullPath) COM_INTERFACE_ENTRY(IFileFullPath) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IShellExtInit)//添加入口点 COM_INTERFACE_ENTRY(IShellPropSheetExt)//添加入口点 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); //实现IShellPropSheetExt接口 virtual HRESULT STDMETHODCALLTYPE AddPages(_In_ LPFNSVADDPROPSHEETPAGE pfnAddPage, _In_ LPARAM lParam); virtual HRESULT STDMETHODCALLTYPE ReplacePage(_In_ EXPPS uPageID, _In_ LPFNSVADDPROPSHEETPAGE pfnReplaceWith, _In_ LPARAM lParam); public: //消息响应函数,在类中必须为静态的 static BOOL CALLBACK PropPageDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static UINT CALLBACK PropPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGEW ppsp); static BOOL OnInitDialog(HWND hwnd, LPARAM lParam); }; OBJECT_ENTRY_AUTO(__uuidof(FileFullPath), CFileFullPath)
// FileFullPath.cpp : CFileFullPath 的实现 #include "stdafx.h" #include "FileFullPath.h" # include "dllmain.h" // CFileFullPath HRESULT STDMETHODCALLTYPE CFileFullPath::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); //检查要现实的属性页是否超出限制 if (m_vtFilePath.size() > MAXPROPPAGES) { m_vtFilePath.resize(MAXPROPPAGES); } else if (m_vtFilePath.size() == 0) {//如果没有文件,则不继续执行 hr = E_FAIL; } return hr; } HRESULT STDMETHODCALLTYPE CFileFullPath::AddPages(_In_ LPFNSVADDPROPSHEETPAGE pfnAddPage, _In_ LPARAM lParam) { //为每一个文件添加属性页 for each (std::wstring var in m_vtFilePath) { WCHAR szPageTitle[MAX_PATH]; //拷贝路径 lstrcpyW(szPageTitle, var.c_str()); //移除目录 PathStripPathW(szPageTitle); //移除扩展名 PathRemoveExtensionW(szPageTitle); //截取前24个字符 szPageTitle[24] = '\0'; szPageTitle[23] = '.'; szPageTitle[22] = '.'; //创建属性页 PROPSHEETPAGEW psp; psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE | PSP_DEFAULT | PSP_USEICONID | PSP_USECALLBACK; psp.hInstance = _AtlBaseModule.GetModuleInstance(); psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_MEDIUM);//通过资源加载属性页模版 psp.pszIcon = MAKEINTRESOURCE(IDI_ICON1);//通过资源加载图标 psp.pszTitle = szPageTitle;//标题 psp.pfnDlgProc = (DLGPROC)PropPageDlgProc;//回调函数 psp.lParam = (LPARAM)_wcsdup(var.c_str());//传入参数为文件路径 psp.pfnCallback = (LPFNPSPCALLBACKW)PropPageCallbackProc;//回调函数 psp.pcRefParent = (UINT*)&_AtlModule.m_nLockCnt; HPROPSHEETPAGE hPage = CreatePropertySheetPageW(&psp); if (NULL != hPage) { //添加到属性页窗口 if (!pfnAddPage(hPage, lParam)) { //添加失败的话需要主动删除 DestroyPropertySheetPage(hPage); } } } return S_OK; } HRESULT STDMETHODCALLTYPE CFileFullPath::ReplacePage(_In_ EXPPS uPageID, _In_ LPFNSVADDPROPSHEETPAGE pfnReplaceWith, _In_ LPARAM lParam) {//没有使用,直接返回 return E_NOTIMPL; } BOOL CFileFullPath::PropPageDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {//响应页面事件 BOOL bRet = FALSE; switch (uMsg) { case WM_INITDIALOG://属性页初始化消息 bRet = OnInitDialog(hwnd, lParam); break; } return bRet; } UINT CFileFullPath::PropPageCallbackProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGEW ppsp) {//在页面创建或销毁的时候被调用 if (PSPCB_RELEASE == uMsg) {//在释放时调用 //释放申请的字符串空间 free((void*)ppsp->lParam); } //调用成功 return 1; } BOOL CFileFullPath::OnInitDialog(HWND hwnd, LPARAM lParam) {//初始化 //获取传入的参数 PROPSHEETPAGE* ppsp = (PROPSHEETPAGE*)lParam; LPCWSTR szFile = (LPCWSTR)ppsp->lParam; //设置窗口中发的CEdit控件,显示文件路径 HWND edit = GetDlgItem(hwnd, IDC_EDIT); SetWindowTextW(edit, szFile); return TRUE; }
IDD_PROPPAGE_MEDIUM为添加的属性页资源。
IDI_ICON1为添加的图标资源。
IDC_EDIT为IDD_PROPPAGE_MEDIUM中的一个CEdit控件,用于显示文件路径
最后就是如图标扩展文章中一样,添加注册表项,将该程序注册在所有类型文件下,详细可看图标扩展的文章,这里就不再赘述。
HKCR { NoRemove * { NoRemove shellex { NoRemove PropertySheetHandlers { ForceRemove {1469FE7B-56CD-40BC-BF30-10A8B8009C63} = s 'FileFullPath Class' } } } }
实现效果如下。
到此,功能已经实现,如果还有不明白的地方请留言,本文有许多不足的地方请指正,谢谢。
相关文章推荐
- 如何重装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页