【发布时间】:2014-07-01 05:52:42
【问题描述】:
如何获取特定文件扩展名的 shell IPreviewHandler?
背景
Windows 允许开发人员为其自定义文件类型创建 预览处理程序:
预览处理程序在选择一个项目以显示“视图”阅读窗格中显示文件的内容的轻量级,丰富,只读预览时。这是在不启动文件的关联应用程序的情况下完成的。
预览处理程序是托管应用程序。主机包括 Windows Vista 或 Microsoft Outlook 2007 中的 Windows 资源管理器。
我想利用现有的IPreviewHandler 基础设施来获取文件的缩略图。
在流中
问题是我的文件没有放在 shell 命名空间中(即它们没有放在硬盘上)。它们位于内存中,可通过IStream 访问。这意味着我不能使用旧的IExtractImage 接口;因为它不支持从 Stream 加载文件。
幸运的是,这就是现代 IPreviewHandler 支持(推荐和更喜欢)从 Stream 加载数据,并建议反对从文件加载预览的原因:
此方法优于 Initialize,因为它能够使用无法通过 Win32 路径访问的流,例如具有 .zip 文件扩展名的压缩文件的内容。
那我怎么得到它?
没有关于正确方法获取与特定扩展关联的IPreviewHandler 的文档。但是,如果我了解如何注册IPreviewHandler、and read the contract from the other side:
HKEY_CLASSES_ROOT
.xyz
(Default) = xyzfile
HKEY_CLASSES_ROOT
xyzfile
shellex
{8895b1c6-b41f-4c1c-a562-0d564250836f} //IPreviewHandler subkey
(Default) = [clsid of the IPreviewHandler]
鉴于我知道扩展程序,我应该能够遵循相同的路线。让我们用一个真实世界的例子,.jpg 文件:
请注意,该文件有一个预览。请注意,我包含第二个屏幕截图只是为了强调预览不是来自硬盘驱动器上的文件的想法。
让我们得到spellunking!
首先它是一个.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} 子键。这一定意味着我们无法获得.jpg 文件的缩略图。
还原为荒谬
真正的问题
细心的读者会意识到我要问的实际问题是:
如何获得仅包含在流中的图像的预览?
虽然这是一个有用的问题,也是我遇到的真正问题,但对如何使用 IPreviewHandler 进行回答也是一个有用的问题。
所以请随意回答;或两者兼而有之!
阅读奖励
【问题讨论】:
-
将流保存到临时文件是否可以接受?在这种情况下,您只需为 .Net like this 使用现成的预览控件即可。
-
你真的需要 IPreviewHandler 吗?看起来 IThumbnailProvider 扩展是您所需要的。即使在 IExtractImage 的情况下,您也可以尝试使用 IInitializeWithStream 或 IPersistStream 初始化扩展(至少 Windows 资源管理器会尝试)。
-
对Hosting Preview Handlers in Windows Forms Applications 的评论指出AssocQueryString 可用于此目的。 ASSOCSTR_SHELLEXTENSION 可用于请求实现特定接口的 shell 扩展,例如
IPreviewHandler。 (将其作为评论发布,因为我无法验证它,并且在这是一个有用的答案之前仍然需要填写一些细节。) -
以 Outlook 为例(类似于您的第二个屏幕截图所示),附件确实作为临时文件保存在磁盘上,因此可以通过许多其他方式提取预览。
-
请注意,
.jpg的PerceivedType是image。见AssocGetPerceivedType MSDN。如果这回答了您的问题,请告诉我。
标签: windows windows-shell ipreviewhandler