访问不存在的缩略图

Tir*_*rus 11 c# windows-shell thumbnails windows-api-code-pack

我已经创建了一个应用程序,它为您提供计算机中的文件列表.每当您单击列表中的任何项目时,它旁边的小PictureBox都应显示相应文件的缩略图.我在Windows 7上使用C#.

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

ShellFile shellFile = ShellFile.FromFilePath(fullPathToFile);
myPictureBox.Image = shellFile.Thumbnail.LargeBitmap;
Run Code Online (Sandbox Code Playgroud)

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

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

更新(由Li0liQ提供)

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

ShellFile shellFile = ShellFile.FromFilePath(fullPathToFile);
shellFile.Thumbnail.FormatOption = ShellThumbnailFormatOption.ThumbnailOnly;
myPictureBox.Image = shellFile.Thumbnail.LargeBitmap;
Run Code Online (Sandbox Code Playgroud)

但是,我得到一个例外,如果缩略图还没有:

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

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

Sim*_*ier 5

下面是一段提取缩略图位图的代码(仅使用 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);
    }
Run Code Online (Sandbox Code Playgroud)

补充笔记:

  • GetImage方法有各种有趣的标志 ( SIIGBF) 您可以使用。
  • 出于性能原因,您可以缓存工厂。例如,.PDF 文件需要整个 Adob​​e Reader .exe 在后台加载。
  • 与 shell(Windows 资源管理器)通信时,您需要确保进程与 shell 运行在相同的UAC 级别,否则,出于安全原因,某些操作将失败。例如,如果您在 Visual Studio 中通过 F5 或 CTRL+F5 运行进程,并且您的 Visual Studio 以管理员身份运行,则您的进程可能无法检索缩略图,但在双击 .exe 运行时它将起作用。来自探险家。这REGDB_E_CLASSNOTREG是在这些情况下您可能会遇到的典型错误。


Bur*_*dar -1

据我所知,您无法强制 Windows 7 生成缩略图。但是,您可以自己使用代码创建它:

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

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