初始化 Shell 扩展处理程序

Shell 扩展处理程序对象的大部分实现由其类型决定。 但是,存在一些常见元素。 本主题讨论由所有 Shell 扩展处理程序共享的实现的那些方面。

所有 Shell 扩展处理程序都是进程内组件对象模型 (COM) 对象。 必须为其分配 GUID 并按照注册 Shell 扩展处理程序中所述进行注册。 它们作为 DLL 实现,必须导出以下标准函数:

  • DllMain。 DLL 的标准入口点。
  • DllGetClassObject。 公开对象的类工厂。
  • DllCanUnloadNow。 COM 调用此函数以确定对象是否为任何客户端提供服务。 否则,系统可以卸载 DLL 并释放关联的内存。

与所有 COM 对象一样,Shell 扩展处理程序必须实现 IUnknown 接口和 类工厂。 大多数还必须在 Windows XP 或更早版本中实现 IPersistFile 或 IShellExtInit 接口。 这些内容被 Windows Vista 中的 IInitializeWithStream、 IInitializeWithItem 和 IInitializeWithFile 所取代。 Shell 使用这些接口来初始化处理程序。

IPersistFile 接口必须通过以下方式实现:

  • 图标处理程序
  • 数据处理程序
  • 删除处理程序

IShellExtInit 接口必须由以下项实现:

  • 快捷菜单处理程序
  • 拖放处理程序
  • 属性表处理程序

本主题的其余部分将讨论以下主题:

实现 IPersistFile

IPersistFile 接口旨在允许从磁盘文件加载或保存到对象。 除了 IUnknown 之外,它还具有六种方法(其自己的五种方法)以及它从 IPersist 继承的 GetClassID 方法。 使用 Shell 扩展时, IPersist 仅用于初始化 Shell 扩展处理程序对象。 由于通常不需要从磁盘读取或写入磁盘,因此只有 GetClassID 和 Load 方法需要非ken 实现。

Shell 首先调用 GetClassID ,函数 (扩展处理程序对象的 CLSID) 返回类标识符。 然后,Shell 调用 Load 并传入两个值。 第一个 是 pszFile,是一个 Unicode 字符串,其中包含 Shell 要操作的文件或文件夹的名称。 第二个是 dwMode,它指示文件访问模式。 由于通常不需要访问文件, 因此 dwMode 通常为零。 方法根据需要存储这些值,供以后参考。

以下代码片段演示了典型的 Shell 扩展处理程序如何实现 GetClassID 和 Load 方法。 它旨在处理 ANSI 或 Unicode。 CLSID_SampleExtHandler是扩展处理程序对象的 GUID,CSampleShellExtension 是用于实现接口的类的名称。 m_szFileName和m_dwMode变量是专用变量,用于存储文件的名称和访问标志。

class CSampleShellExtension : public IPersistFile
{
    // Method declarations not included

    private:
    WCHAR m_szFileName[MAX_PATH];    // The file name
    DWORD m_dwMode;                  // The file access mode
}

IFACEMETHODIMP CSampleShellExtension::GetClassID(__out CLSID *pCLSID)
{
    *pCLSID = CLSID_SampleExtHandler;
}

IFACEMETHODIMP CSampleShellExtension::Load(PCWSTR pszFile, DWORD dwMode)
{
    m_dwMode = dwMode;
    return StringCchCopy(m_szFileName, ARRAYSIZE(m_szFileName), pszFile); 
}

// The implementation sample is continued in the next section.

实现 IShellExtInit

除了 IUnknown 之外,IShellExtInit 接口只有一种方法 IShellExtInit::Initialize。 方法具有三个参数,Shell 可以使用这些参数传递各种类型的信息。 传入的值取决于处理程序的类型,有些值可以设置为 NULL。

  • pidlFolder 保存指向 PIDL) (项标识符列表的文件夹指针。 这是绝对 PIDL。 对于属性表扩展,此值为 NULL。 对于快捷菜单扩展,它是包含显示其快捷菜单的项的文件夹的 PIDL。 对于非默认拖放处理程序,它是目标文件夹的 PIDL。
  • pDataObject 保存指向数据对象的 IDataObject 接口的指针。 数据对象保存 CF_HDROP格式的 一个或多个文件名。
  • hRegKey 保存文件对象或文件夹类型的注册表项。

IShellExtInit::Initialize 方法根据需要存储文件名、IDataObject 指针和注册表项,以供以后使用。 以下代码片段演示 了 IShellExtInit::Initialize 的实现。 为简单起见,此示例假定数据对象仅包含单个文件。 通常,数据对象可能包含多个文件,其中每个文件都需要提取。

// This code continues the CSampleShellExtension sample shown in the
// "Implementing IPersistFile" section above.

class CSampleShellExtension : public IShellExtInit
{
    // Method declarations not included
    
    private:
    // IDList of the folder for extensions invoked on the folder, such as 
    // background context menu handlers or nondefault drag-and-drop handlers. 
    PIDLIST_ABSOLUTE m_pidlFolder;
    
    // The data object contains an expression of the items that the handler is 
    // being initialized for. Use SHCreateShellItemArrayFromDataObject to 
    // convert this object to an array of items. Use SHGetItemFromObject if you
    // are only interested in a single Shell item. If you need a file system
    // path, use IShellItem::GetDisplayName(SIGDN_FILESYSPATH, ...).
    IDataObject *m_pdtobj;
    
    // For context menu handlers, the registry key provides access to verb 
    // instance data that might be stored there. This is a rare feature to use 
    // so most extensions do not need this variable.
    HKEY m_hRegKey;             
}
    
// This method must be very efficient. Do not do any unnecessary work here.
// Use Initialize to acquire resources that will be used later.

IFACEMETHODIMP CSampleShellExtension::Initialize(__in_opt PCIDLIST_ABSOLUTE pidlFolder,
                                                 __in_opt IDataObject *pDataObject, 
                                                 __in_opt HKEY hRegKey) 
{ 
    // In some cases, handlers are initialized multiple times. Therefore, 
    // clear any previous state here.
    CoTaskMemFree(m_pidlFolder);
    m_pidlFolder = NULL;
    
    if (m_pdtobj)
    { 
        m_pdtobj->Release(); 
    }
    
    if (m_hRegKey)
    {
        RegCloseKey(m_hRegKey);
        m_hRegKey = NULL;
    }
    
    // Capture the inputs for use later.
    HRESULT hr = S_OK;
    
    if (pidlFolder)
    {
        m_pidlFolder = ILClone(pidlFolder);   // Make a copy to use later.
        hr = m_pidlFolder ? S_OK : E_OUTOFMEMORY;
    }
    
    if (SUCCEEDED(hr))
    {
        // If a data object pointer was passed into the method, save it and
        // extract the file name. 
        if (pDataObject) 
        { 
            m_pdtobj = pDataObject; 
            m_pdtobj->AddRef(); 
        }
    
        // It is uncommon to use the registry handle, but if you need it,
        // duplicate it now.
        if (hRegKey)
        {
            LSTATUS const result = RegOpenKeyEx(hRegKey, NULL, 0, KEY_READ, &m_hRegKey); 
            hr = HRESULT_FROM_WIN32(result);
        }
    }
    
    return hr;
}

信息提示自定义

可通过两种方式自定义信息提示。 一种方法是实现支持 IQueryInfo 的对象,然后在注册表中的适当子项下注册该对象, (请参阅下面的) 。 或者,可以指定要显示的固定字符串或特定文件属性的列表。

若要显示命名空间扩展的固定字符串,请在命名空间扩展的 CLSID 键下创建名为 InfoTip 的子项。 将该子项的数据设置为要显示的字符串。

HKEY_CLASSES_ROOT
   CLSID
      {CLSID}
         InfoTip = InfoTip string for your namespace extension

若要显示某个文件类型的固定字符串,请在要为其提供信息提示的文件类型的 ProgID 键下面创建一个名为“信息提示”的子项。 将该子项的数据设置为要显示的字符串。

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = InfoTip string for all files of this type

如果希望 Shell 在特定文件类型的信息提示中显示某些文件属性,请在该文件类型的 ProgID 键下创建一个名为 InfoTip 的子项。 将该子项的数据设置为规范属性名称或 {fmtid} 的分号分隔列表,其中 propname 是规范属性名称的 pid 对 ,而 {fmtid},pid 是 FMTID/PID 对。

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = propname;propname;{fmtid},pid;{fmtid},pid

可以使用以下属性名称。

属性名称 说明 检索自
作者 文档的作者 PIDSI_AUTHOR
标题 文档的标题 PIDSI_TITLE
主题 主题摘要 PIDSI_SUBJECT
评论 文档注释 PIDSI_COMMENT 或文件夹/驱动器属性
PageCount 页数 PIDSI_PAGECOUNT
名称 友好名称 标准文件夹视图
OriginalLocation 原始文件的位置 公文包文件夹和回收站文件夹
DateDeleted 删除日期文件 回收站文件夹
类型 文件类型 标准文件夹详细信息视图
大小 文件大小 标准文件夹详细信息视图
SyncCopyIn 与 OriginalLocation 相同 与 OriginalLocation 相同
修改时间 上次修改日期 标准文件夹详细信息视图
创建 创建日期 标准文件夹详细信息视图
已访问 上次访问日期 标准文件夹详细信息视图
InFolder 包含文件的目录 文档搜索结果
级别 搜索匹配的质量 文档搜索结果
FreeSpace 可用存储空间 磁盘驱动器
NumberOfVisits 访问次数 收藏夹文件夹
特性 文件属性 标准文件夹详细信息视图
Company 公司名称 PIDDSI_COMPANY
类别 文档类别 PIDDSI_CATEGORY
版权信息 媒体版权 PIDMSI_COPYRIGHT
HTMLInfoTipFile HTML 信息提示文件 文件夹的Desktop.ini文件

 

注册 Shell 扩展处理程序