访问不存在的缩略图 [英] Accessing thumbnails that don't exist

查看:29
本文介绍了访问不存在的缩略图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我制作了一个应用程序,可以向您显示计算机中的文件列表.每当您单击列表中的任何项目时,它旁边的小图片框应显示相应文件的缩略图.我在 Windows 7 上使用 C#.

I have made an application that presents you a list of files in your computer. Whenever you click any item in the list, a small PictureBox next to it should show the thumbnail of the corresponding file. I am using C# on Windows 7.

为了获取缩略图,我再次使用了在另一个问题中发布的方法.首先,我参考了 Windows API 代码包.然后,我使用以下代码:

To obtain the thumbnail, I've recurred to a method posted in a different question. First, I reference the Windows API Code pack. Then, I use the following code:

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

这并不总是有效.有时,显示的缩略图只是默认应用程序"图标.我发现只有在 Windows 之前为该文件生成了缩略图并将其存储在缩略图缓存中时,才会显示真正的缩略图.这意味着我必须手动打开一个文件夹,等待 Windows 为每个文件生成缩略图,然后我的应用程序才能看到这些缩略图.

This doesn't always work. Sometimes, the thumbnail shown is merely the 'default application' icon. I've found out that the real thumbnail is only shown if Windows had previously generated the thumbnail for that file and stored it in the thumbnails cache. This means that I have to manually open a folder, wait for Windows to generate thumbnails for each file, and then my application will be able to see those thumbs.

我的程序如何强制 Windows 7 在使用之前生成真实的缩略图?

How can my program force Windows 7 to generate real thumbnails before using them?

更新(由 Li0liQ)

可以通过添加 FormatOption 来强制检索缩略图:

It is possible to force thumbnail retrieval by adding FormatOption:

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

但是,如果缩略图尚不存在,我会收到一个例外:

however, I'm getting an exception in case thumbnail is not there yet:

当前的 ShellObject 没有有效的缩略图处理程序或提取此特定的缩略图时出现问题壳对象.---> System.Runtime.InteropServices.COMException: 类未注册(来自 HRESULT 的异常:0x80040154(REGDB_E_CLASSNOTREG))

The current ShellObject does not have a valid thumbnail handler or there was a problem in extracting the thumbnail for this specific shell object. ---> System.Runtime.InteropServices.COMException: Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))

请参阅如何刷新文件的缩略图Windows 资源管理器?问题和代码片段以获取潜在线索.

See How do I refresh a file's thumbnail in Windows Explorer? question and code snippet for potential clues.

推荐答案

这是一段提取缩略图位图的代码(仅使用 Windows Vista 或更高版本).它基于很酷的 IShellItemImageFactory 接口:

Here is a piece of code that extracts thumbnail bitmaps (using Windows Vista or higher only). It's based on the cool IShellItemImageFactory interface:

    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 文件需要在后台加载整个 Adob​​e Reader .exe.
  • 在与外壳(Windows 资源管理器)对话时,您希望确保您的进程在与外壳相同的 UAC 级别 上运行,否则,出于安全原因,某些操作将失败.因此,例如,如果您在 Visual Studio 中从 F5 或 CTRL+F5 运行您的进程,并且您的 Visual Studio 以管理员身份运行,您的进程可能无法检索缩略图,而在双击 .exe 运行时它会工作来自探险家.REGDB_E_CLASSNOTREG 是您在这些情况下可能遇到的一种典型错误.
  • The GetImage method has various interesting flags (SIIGBF) you can play with.
  • For performance reasons, you can cache the factories. For example, .PDF files requires the whole Adobe Reader .exe to load in the background.
  • When talking to the shell (Windows Explorer), you want to make sure your process runs at the same UAC level than the shell otherwise, for security reasons, some operations will fail. So for example, if you run your process from F5 or CTRL+F5 in Visual Studio, and your Visual Studio runs as admin, your process may not be able to retrieve thumbnails, while it will work when run double-clicking on the .exe from the explorer. The REGDB_E_CLASSNOTREG is a typical kind of error you may get in these cases.

这篇关于访问不存在的缩略图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆