访问缩略图不存在(Accessing thumbnails that don't exist

2019-08-01 01:13发布

我已经呈现您的文件在您的计算机列表中的应用。 每当你点击列表中的任何项目,一个小图片框旁边应该显示相应的文件的缩略图。 我使用的Windows 7 C#。

要获得缩略图,我已经复发张贴在不同的问题的方法。 首先,我引用的Windows API代码包。 然后,我用下面的代码:

ShellFile shellFile = ShellFile.FromFilePath(fullPathToFile);
myPictureBox.Image = shellFile.Thumbnail.LargeBitmap;

这并不总是奏效。 有时,显示的缩略图仅仅是“默认应用程序”图标。 我发现,如果视窗以前生成该文件的缩略图并将其存储在缩略图缓存真正缩略图时,才会显示。 这意味着我必须手动打开文件夹,等待Windows生成每个文件的缩略图,然后我的应用程序将能够看到那些竖起大拇指。

如何让我的计划力Windows 7中使用它们之前产生真正的缩略图?

更新(由Li0liQ)

这可以通过增加FormatOption强制缩略图检索:

ShellFile shellFile = ShellFile.FromFilePath(fullPathToFile);
shellFile.Thumbnail.FormatOption = ShellThumbnailFormatOption.ThumbnailOnly;
myPictureBox.Image = shellFile.Thumbnail.LargeBitmap;

但是,我得到的情况下,缩略图的异常现在还没有:

目前ShellObject没有一个有效的缩略图处理或有在提取缩略图这个特定的壳对象的问题。 ---> System.Runtime.InteropServices.COMException:类未注册(从HRESULT异常:0x80040154的(REGDB_E_CLASSNOTREG))

见我如何刷新文件的缩略图在Windows资源管理器? 问题和代码段用于潜在线索。

Answer 1:

下面是一段代码,提取缩略图位图(使用的是Windows Vista或更高版本)。 它基于酷上IShellItemImageFactory接口 :

    static void Main(string[] args)
    {
        // you can use any type of file supported by your windows installation.
        string path = @"c:\temp\whatever.pdf";
        using (Bitmap bmp = ExtractThumbnail(path, new Size(1024, 1024), SIIGBF.SIIGBF_RESIZETOFIT))
        {
            bmp.Save("whatever.png", ImageFormat.Png);
        }
    }

    public static Bitmap ExtractThumbnail(string filePath, Size size, SIIGBF flags)
    {
        if (filePath == null)
            throw new ArgumentNullException("filePath");

        // TODO: you might want to cache the factory for different types of files
        // as this simple call may trigger some heavy-load underground operations
        IShellItemImageFactory factory;
        int hr = SHCreateItemFromParsingName(filePath, IntPtr.Zero, typeof(IShellItemImageFactory).GUID, out factory);
        if (hr != 0)
            throw new Win32Exception(hr);

        IntPtr bmp;
        hr = factory.GetImage(size, flags, out bmp);
        if (hr != 0)
            throw new Win32Exception(hr);

        return Bitmap.FromHbitmap(bmp);
    }

    [Flags]
    public enum SIIGBF
    {
        SIIGBF_RESIZETOFIT = 0x00000000,
        SIIGBF_BIGGERSIZEOK = 0x00000001,
        SIIGBF_MEMORYONLY = 0x00000002,
        SIIGBF_ICONONLY = 0x00000004,
        SIIGBF_THUMBNAILONLY = 0x00000008,
        SIIGBF_INCACHEONLY = 0x00000010,
        SIIGBF_CROPTOSQUARE = 0x00000020,
        SIIGBF_WIDETHUMBNAILS = 0x00000040,
        SIIGBF_ICONBACKGROUND = 0x00000080,
        SIIGBF_SCALEUP = 0x00000100,
    }

    [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
    private static extern int SHCreateItemFromParsingName(string path, IntPtr pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IShellItemImageFactory factory);

    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("bcc18b79-ba16-442f-80c4-8a59c30c463b")]
    private interface IShellItemImageFactory
    {
        [PreserveSig]
        int GetImage(Size size, SIIGBF flags, out IntPtr phbm);
    }

补充说明:

  • GetImage方法有各种有趣的标志( SIIGBF ),你可以玩。
  • 出于性能的考虑,你可以缓存工厂。 例如,.PDF文件需要全ADOBE READER .exe文件在后台加载。
  • 当聊到外壳(Windows资源管理器),你要确保你的过程中,在同一级别的UAC比外壳运行,否则,出于安全考虑,一些操作将失败。 因此,例如,如果您从F5或CTRL + F5的过程在Visual Studio中,和你的Visual Studio运行作为管理员,您的过程可能无法在运行.exe文件双击时能够检索缩略图,而将工作从资源管理器。 该REGDB_E_CLASSNOTREG是一种典型的错误,你可以在这些情况下得到的。


Answer 2:

经过一番搜索,我发现的Microsoft Office缩略图在Sharepoint 。 它可能只对办公文档的工作,但可能是你想要的。 将需要一些转换的例子是在C ++和VB.Net。



Answer 3:

如何让我的计划力Windows 7中使用它们之前产生真正的缩略图?

从壳牌接口: IThumbnailCache接口 (重点煤矿)

缩略图缓存API的目的是提供一个统一的方法来检索和缓存缩略图的应用程序。 在Windows XP中,缩略图缓存在每个文件夹的基础上完成的,并且高速缓存保持在每个文件夹内的文件的Thumbs.db。 虽然这种方法提供了空间局部性,它不支持在文件夹预览和查询。 Windows Vista中的缩略图缓存,提供全局缓存解决了这个缺点。

缓存缩略图,应用程序必须先获得表示为将要获得的缩略图的项目的IShellItem,然后传递到的IShellItem调用IThumbnailCache :: GetThumbnail。 如果flags参数IThumbnailCache :: GetThumbnail包括标志WTS_EXTRACT和缩略图尚未缓存,缩略图将被提取并放置在缓存中。 如果标志WTS_FORCEEXTRACTION设置,缓存被忽略,新的缩略图总是被提取。 见传递到IThumbnailCache :: GetThumbnail标志更多细节IThumbnailCache :: GetThumbnail话题。

如果缩略图是不是已经在缓存中,它会自动使用被注册的操作系统上IExtractImage或IThumbnailProvider的现有实现(一个或多个)源文件提取 。 您的应用程序没有提供缩略图提取的实现。

因此,假设您的系统具有IThumbnail提供商与PDF工作的落实:

  1. 得到一个shell项目为您的PDF。
  2. 得到shell的缩略图缓存的引用。 让我们把它thumbNailCache
  3. 呼叫thumbNailCache.GetThumbnail (shellItem, thumbNailpx, wtxFlagSet , out thumbNailBitmap); 。 该文件说,这将创建缩略图你和输出参数thumbNailBitmap返回。

注意事项:我不知道,如果你的代码包充分暴露IThumbnailCache,但如果这样做,这看起来是非常简单的。 如果不是这样,你就必须从shell32.dll中导入。

有一个IThumbnailProvider接口,以及可能为你工作,但阅读群体的意见。 这似乎是脆弱的,棘手的使用。



Answer 4:

据我知道你不能强制Windows 7生成缩略图。 但是,你可以用自己的代码创建它:

Image image = Image.FromFile(fileName);
Image thumbNail = image.GetThumbnailImage(120, 120, ()=>false, IntPtr.Zero);
thumbNail.Save(Path.ChangeExtension(fileName, "thumb"));

http://msdn.microsoft.com/en-us/library/system.drawing.image.getthumbnailimage.aspx



文章来源: Accessing thumbnails that don't exist