[ShellExtension]属性页扩展-IShellPropSheetExt实现

来源:互联网 发布:菜鸟网络总部 编辑:程序博客网 时间:2024/06/16 12:20

还是先亮源码下载地址:https://git.oschina.net/xiangmu110/template_IShellPropSheetExt

以下所讲与提供下载的源码不同,但都是一个模子出来的。

下面代码实现的是在所有类型的文件的属性中添加一页,用于显示该文件的完整路径。支持同时选择多个文件并查看。

首先创建一个名为“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>//引入头文件,会使用的vectorusing namespace ATL;// CFileFullPathclass 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"// CFileFullPathHRESULT 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'            }                    }         }}

实现效果如下。
这里写图片描述

到此,功能已经实现,如果还有不明白的地方请留言,本文有许多不足的地方请指正,谢谢。

这里写图片描述

0 0
原创粉丝点击