如何获得文件扩展名的IPreviewHandler?

我如何获得特定文件扩展名的shell IPreviewHandler

背景

Windows允许开发人员为其自定义文件类型创建预览处理程序:

预览处理程序在选定项目时调用,以在视图的阅读窗格中显示文件内容的轻量级丰富只读预览。 这是在不启动文件的关联应用程序的情况下完成的。

预览处理程序是托管应用程序。 主机包括Windows Vista或Microsoft Outlook 2007中的Windows资源管理器。

我想利用现有的IPreviewHandler设施获取文件的缩略图。

在流

问题是我的文件不在shell命名空间中(即它们没有坐在硬盘上)。 他们坐在记忆里,通过IStream访问。 这意味着我不能使用传统的IExtractImage接口; 因为它不支持从Stream加载文件。

幸运的是,这就是现代IPreviewHandler支持(推荐并优先选择)从Stream加载数据的原因,并建议不要从文件加载预览:

由于该方法能够使用不能通过Win32路径访问的流,例如具有.zip文件扩展名的压缩文件的内容,因此此方法优先于初始化。

那么,我如何得到它?

没有关于如何IPreviewHandler与特定分机关联的IPreviewHandler的正确方法的文档。 但是,如果我按照如何注册 IPreviewHandler的方向,并IPreviewHandler读取合同:

HKEY_CLASSES_ROOT
  .xyz
     (Default) = xyzfile

HKEY_CLASSES_ROOT
   xyzfile
      shellex
         {8895b1c6-b41f-4c1c-a562-0d564250836f} //IPreviewHandler subkey
             (Default) = [clsid of the IPreviewHandler]

鉴于我知道延期,我应该能够遵循相同的路线。 让我们以一个真实世界的例子来说明一个.jpg文件:

在这里输入图像描述

在这里输入图像描述

注意该文件有预览。 请注意,我仅包含第二张截图,以强化预览不是来自坐在硬盘上的文件的想法。

让我们开始拼写!

首先是它是一个.jpg文件的事实:

HKEY_CLASSES_ROOT
   .jpg
      (Default) = ACDC_JPG

HKEY_CLASSES_ROOT
   ACDC_JPG
      ShellEx
         {BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}
         ContextMenuHandlers

等等, {8895b1c6-b41f-4c1c-a562-0d564250836f}没有{8895b1c6-b41f-4c1c-a562-0d564250836f}子项。 这意味着我们无法获得.jpg文件的缩略图。

减少荒谬

真正的问题

仔细的读者会意识到我所问的实际问题是:

如何获取仅包含在流中的图像的预览?

虽然这是一个有用的问题,而且我遇到的实际问题是,如何使用IPreviewHandler也是一个有用的问题。

所以随时回答; 或两者!

奖金阅读

  • MSDN:预览处理程序和外壳预览主机
  • MSDN:如何注册预览处理程序
  • MSDN:IInitializeWithStream :: Initialize方法
  • IPreviewHandler引发不可捕捉的异常
  • Outlook的IPreviewHandler for Delphi

  • @ hvd有正确的答案。

    文件类型具有带{guid}子项的ShellEx密钥。 每个{guid}键代表一个特定的InterfaceID

    有许多可以与文件类型关联的标准shell接口:

  • {BB2E617C-0920-11d1-9A0B-00C04FC2D6C1} IExtractImage
  • {953BB1EE-93B4-11d1-98A3-00C04FB687DA} IExtractImage2
  • {e357fccd-a995-4576-b01f-234630154e96} IThumbnailProvider
  • {8895b1c6-b41f-4c1c-a562-0d564250836f} IPreviewHandler
  • 例如,如果我想查找与.jpg文件关联的IPreviewHandlerclsid ,我会查找:

    HKEY_CLASSES_ROOT/.jpg/ShellEx/{8895b1c6-b41f-4c1c-a562-0d564250836f}
       (default) = [clsid]
    

    但那不是我唯一能看的地方。 我也可以看看:

    HKEY_CLASSES_ROOT/.jpg
       (default) = jpgfile
    HKEY_CLASSES_ROOT/jpgfile/ShellEx/{8895b1c6-b41f-4c1c-a562-0d564250836f}
       (default) = [clsid]
    

    但那不是我唯一能看的地方。 我也可以看看:

    HKEY_CLASSES_ROOT/SystemFileAssociations/.jpg/ShellEx/{8895b1c6-b41f-4c1c-a562-0d564250836f}
       (default) = [clsid] 
    

    但那不是我唯一能看的地方。 我也可以看看:

    HKEY_CLASSES_ROOT/SystemFileAssociations/jpegfile/ShellEx/{8895b1c6-b41f-4c1c-a562-0d564250836f}
       (default) = [clsid]
    

    但那不是我唯一能看的地方。 如果我认为该文件是一个图像,我也可以查看:

    HKEY_CLASSES_ROOT/SystemFileAssociations/image/ShellEx/{8895b1c6-b41f-4c1c-a562-0d564250836f}
       (default) = [clsid]
    

    我是如何找到这些位置的? 我是否只遵循记录和支持的位置? 不,我使用Process Monitor监视Explorer,因为它正在寻找IThumbnailProvider

    所以现在我想为我自己的文件类型使用标准的shell接口。 这意味着我必须抓取位置。 但为什么要以无证件,不支持的方式抓取这些地点。 为什么从[the thing] [2]的顶端引起[guy] [1]的愤怒? 使用[ AssocQueryString ] [3]:

    Guid GetShellClsidForFileType(String fileExtension, Guid interfaceID)
    {
        //E.g.:
        //   String fileExtension = ".jpg"
        //   Guid   interfaceID   = "{8895b1c6-b41f-4c1c-a562-0d564250836f}"; //IExtractImage
    
        //The interface we're after - in string form
        String szInterfaceID := GuidToString(interfaceID);
    
        //Buffer to receive the clsid string
        DWORD bufferSize := 1024; //more than enough to hold a 38-character clsid
        String buffer;
        SetLength(buffer, bufferSize);
    
        HRESULT hr := AssocQueryString(
              ASSOCF_INIT_DEFAULTTOSTAR, 
              ASSOCSTR_SHELLEXTENSION, //for finding shell extensions
              fileExtension, //e.g. ".txt"
              szInterfaceID, //e.g. "{8895b1c6-b41f-4c1c-a562-0d564250836f}"
              buffer,        //will receive the clsid string
              @bufferSize);
       if (hr <> S_OK) 
          return Guid.Empty;
    
       Guid clsid;
       HRESULT hr = CLSIDFromString(buffer, out clsid);
       if (hr <> NOERROR) 
          return Guid.Empty;
    
       return clsid;
    }
    

    所以要获得IPreviewHandler.xps文件的clsid

    Guid clsid = GetShellClsidForFileType(".xps", IPreviewHandler);
    
    链接地址: http://www.djcxy.com/p/20451.html

    上一篇: How to get the IPreviewHandler for a file extension?

    下一篇: Iptables forward port range to another port range on a different host