系列专题:【附源码】Windows Shell接口之VB实现(三):IThumbnailProvider接口 (缩略图)
【源码下载地址】:http://econet.zjgsu.edu.cn/cy_filesxxx/vbsrc/ThumbnailProvider.rar
我们知道,在Windows XP中,系统会在每个需要产生缩略图的文件夹中创建一个名为thumb.db的缩略图数据库文件。但是,这种以文件夹为单位维护手段无法为我们提供预览或跨文件夹的查询的功能。针对这些缺点,MS在Windows Vista中对缩略图功能做了比较大的调整,将权利从地方收回中央,建立了一个全局的缩略图缓存。打开 "%SystemDrive%\Users\%UserName%\AppData\Local\Microsoft\Windows\Explorer" 文件夹,你会发现若干个名为thumbcache_*.*的文件。这些文件名后面标着数字32、96、256、1024的db文件就是保存了系统中相应尺寸缩略图(分别对应资源管理器“视图”中的“小图标”、“中等图标”、“大图标”和“特大图标”)的缓存数据库。根据新的设计,我们在Vista中可以不受限制的为每一个单独的文件提供任意大小、任意内容的缩略图,完全摆脱了以往那种只能提供几个特定尺寸的死板约束。
Windows Vista用户界面中常用的是32位256x256的缩略图。根据微软的文档的建议,当你使用自己自定义格式的文件时,最好能同时为其提供上述规格的动态缩略图,以随时反映出特定文件的内容。有鉴于此,Vista中引入了全新的接口IThumbnailProvider,以一种更加简洁方便的方式替代以前的IExtractImage帮助我们完成提供缩略图的工作。当然,为了保持兼容,IExtractImage在Vista中依旧可用,只是资源管理器中的“详细信息面板”不支持该接口。
缩略图提供器(ThumbnailProvider)主要由两个接口组成,除了实现IThumbnailProvider之外,你还必须要实现IInitializeWithStream或IInitializeWithItem接口,以获得目标文件的信息。系统在调用你的IThumbnailProvider之前会依照顺序先后尝试调用这两个接口。如果你已实现了IInitializeWithStream或已同时实现了两个接口,系统将会调用IInitializeWithStream.Initialize方法将代表目标文件内容的流对象通过第一个参数(pstream)传到你的提供器程序中。IInitializeWithItem当然也是可以使用的,通过IInitializeWithItem.Initialize传入的是代表目标文件的IShellItem对象。但是,MS强烈建议我们不要使用这个接口,如果你实在要使用它的话,请通过在HKEY_CLASSES_ROOT\CLSID\{缩略图提供器类的CLSID}下新建一个名为DisableProcessIsolation、值为1、类型为REG_DWORD的键,取消你提供器组件的进程隔离特性(process isolation feature)。另外,MS的文档中还提到了另一个接口IinitializeWithFile,但是不知道什么原因,似乎系统从来不会访问它。
介绍了有关缩略图以及缩略图提供器(ThumbnailProvider)的前世今生后,下面就让我们动手,使用Visual Basic 6创建一个我们自己的缩略图提供器(ThumbnailProvider)吧。
假设你某天早晨刷牙时,突然想到为自己的新软件设计一种文本格式的自定义文件,并给它取了一个很响亮的扩展名.myext。而现在你想为它写一个能够用于显示特定文件内容的缩略图提供器。
就像所有其他的接口编程一样,在开始之前我们得有一个类型库,一个包含了IThumbnailProvider、IInitializeWithStream以及IStream声明的类型库。这一步我已经帮你做好,示例文件中的ThumbnailProvider.tlb应该可以满足你的要求。
接着打开你的VB6 IDE,新建一个ActiveX DLL工程(比如叫MyThumbnailProvider),并添加一个"Instancing=5 - MultiUse"的公共类(比如叫CMyThumbnailProvider)。引用前面提到的类型库ThumbnailProvider.tlb。
OK,现在万事俱备,你可以开始写你的缩略图提供器了。
首先,实现两个接口:
Implements IInitializeWithStreamImplements IThumbnailProvider
Private Sub IInitializeWithStream_Initialize(ByVal pstream As ThumbnailProvider.IStream, ByVal grfMode As Long) If pstream Is Nothing Then Err.Raise E_NOTIMPL Else Set m_pStream = pstream End IfEnd Sub接下来是IThumbnailProvider的GetThumbnail方法,系统会调用此方法以获得相应的缩略图。Private Sub IThumbnailProvider_GetThumbnail(ByVal cx As Long, phbmp As Long, pdwAlpha As WTS_ALPHATYPE) Dim sFileName As String Dim st As STATSTG '取得IStream对象的信息 m_pStream.Stat st '获取IStream对象的名称信息 If st.pwcsName <> 0 Then sFileName = StrFromPtr(st.pwcsName, True) CoTaskMemFree st.pwcsName End If '获得流对象中的字节数据大小 Dim lFileSize As Long lFileSize = IntegerFromCurrency(st.cbSize) If lFileSize <= 0 Then Exit Sub Dim sBuffer As String Dim abBuffer() As Byte ReDim abBuffer(lFileSize - 1) '读取所有数据 If m_pStream.Read(abBuffer(0), lFileSize) <= 0 Then Exit Sub sBuffer = StrConv(abBuffer, vbUnicode) '创建缩略图 phbmp = CreateThumbnail(sBuffer)End Sub
使用VB6的我们,在这里就要碰到一点点小麻烦了。如果我们用VC之类的工具来编写这个缩略图提供器,那么我们不仅可以自己指定类的ID,而且上面的注册表操作过程我们也完全可以在组件的DllRegisterServer函数中写入。可是,在VB6中我们在这个类被注册前,是无法在代码中得到类ID的,而且虽然通过拦截编译过程修改Dll导出函数等手段,可以达到自定义DllRegisterServer等函数的目的,但是,这个工程量就有点儿太大了。于是,我就想了一种变通的手段,通过第三者(RegProvider)读取组件中的类信息,并将相关的信息写入注册表。
以下是RegProvider的使用方法:
1. 选择提供ThumbnailProvider服务的文件
2. 选择要注册的类
3. 输入要注册的文件扩展名
4. 选择用于显示覆盖图标的图标文件或资源(任何图标或资源引用皆可) (可选操作)
5. 选择系统显示缩略图时所用的修饰效果 (可选操作)
6. 选择是否作为进程内组件运行 (可选操作)
7. 单击 注册 或 注销
在结束前,我再提下MS在文档中就缩略图所提的几点指导原则:
A、提供能在32位256x256像素大小下很好显示的缩略图。Windows Vista的预览窗格在找不到相对应的预览处理程序(preview handler)时,会使用该规格的缩略图以作替代。但是,最好的选择还是预览处理程序,所以,应该尽可能的提供之。
B、当你创建尺寸不同的多个图像时,不要通过裁剪大图像的页面、帧或图像的方式创建小图像,而应该整体缩放之。
C、不要一次显示多个页面、帧或图像,一次只使用一个。如果一个文档由多个页面组成,比如一个文本文档或多页电子表格,那么最佳的选择就是封面。但是,不管你使用哪一页,一次只使用一次。不要同时混合多个不同的页面,这样看起来很乱。
D、Windows Vista会负责缩小图像。如果系统要求你的处理程序提供的图像比你能提供的要大,那就提供大小最相近的。不要意图动态改变你图片的大小。
E、你的处理程序在任何时候都应返回一个缩略图像,而非通过某种特殊的逻辑返回传统的图标。当低于特定的尺寸时,Windows Vista会自动显示传统图标而非缩略图。更多详情可以参考Thumbnail Providers中的Thumbnail Cache and Sizing部分。
F、在任何时候都应返回与页面、帧或图像纵横比相同的缩略图。对于非正方形的图像, Windows Vista会负责正确摆正其位置,不要使用透明去补全图像。
G、不要在你的缩略图上添加修饰效果。Windows Vista会自动在适当的时候应用投影等修饰效果,也会对特定的文件类型,比如图片或视频,应用特殊的修饰效果。
H、不要在你的缩略图上覆盖文件类型或应用程序信息。Windows Vista在图像的右下角会显示一个类型覆盖图标。覆盖图标是基于文件类型的,但是也可以根据单独的文件类型进行设置。
I、为了能有更好的性能表现,如果你的缩略图是基于文件内容的——比如某个文档中的某一页——那么,在文件保存时应连同预览的图像一起保存,而不是实时对其进行计算。如果这种计算操作是内存敏感的(操作时间大于1、2秒),就应当采取这种方式。否则,在显示具有大量使用不同处理程序显示文件缩略图的文件视图时,将会花去不少时间——而这是一种很糟糕的用户体验。Windows Vista缓存缩略图,并根据最近的修改时间以决定是否更新某个缩略图。
Windows Vista中除了提供缩略图的IThumbnailProvider之外,还有一个更好玩的IPreviewHandler,它可以让我们为自己的文件提供预览功能。不过当然,这个就只能且听下回分解了,哈!
[解决办法]
顶
[解决办法]
学习.
[解决办法]
学习..
[解决办法]
顶了
[解决办法]
哈哈.
支持豆子同学!!!!!
很久没见你发文章了..........
[解决办法]
还是一如既往的YD 顶上去
[解决办法]
收藏好贴
[解决办法]
学习
[解决办法]
好文共赏~~
[解决办法]
kankan
[解决办法]
VB6有你更精彩。有一种苍凉的感动……
[解决办法]
是不是这个只能在VISTA系统中有效果啊?我在XP系统中把 一个有内容的TXT文档后缀改为myext,并且也注册了,似乎没看到效果,。
[解决办法]
俺是打工滴
[解决办法]
进来学习了
[解决办法]
多多学习了~
[解决办法]
好东西值得一看啊
[解决办法]
分享是美德,为楼主的美德,顶一顶!!!
学习!
[解决办法]
虽然我不是学VB的,但绝对有参考价值~!!顶啦~
[解决办法]
mark 学习
------解决方案--------------------
看不懂
[解决办法]
学习!
[解决办法]
感谢lz
[解决办法]
学习了
[解决办法]
好 学习学习[u][/u]
[解决办法]
mark
[解决办法]
三个专题都齐全了,收藏!
[解决办法]
up!
[解决办法]
学习
[解决办法]
不错,好东西
[解决办法]
认真学习中
[解决办法]
UP
[解决办法]
up
[解决办法]
学习,再学习!