c# – 访问不存在的缩略图

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

获取缩略图,我已经重新发布到另一个问题中发布的方法.首先,我参考Windows API代码包.然后,我使用以下代码

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

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

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

更新(由Li0liQ)

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

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

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

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))

有关可能的线索,请参阅How do I refresh a file’s thumbnail in Windows Explorer?问题和代码snippet.

解决方法

这是一段代码,它提取缩略图位图(仅使用Windows Vista或更高版本).它基于酷 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文件要求整个Adobe Reader .exe在后台加载.>当与外壳(Windows资源管理器)通话时,您希望确保您的进程与shell的UAC级别相同,否则出于安全考虑,某些操作将失败.因此,例如,如果您在Visual Studio中从F5或CTRL F5运行流程,并且Visual Studio管理员身份运行,则您的进程可能无法检索缩略图,而在双击.exe从探险家.在这些情况下,REGDB_E_CLASSNOTREG是一种典型的错误.

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...