要获取缩略图,我已经重新发布到另一个问题中发布的方法.首先,我参考Windows API代码包.然后,我使用以下代码:
ShellFile shellFile = ShellFile.FromFilePath(fullPathToFile); myPictureBox.Image = shellFile.Thumbnail.LargeBitmap;
这并不总是奏效有时,所示的缩略图只是“默认应用程序”图标.我发现,如果Windows以前生成了该文件的缩略图并将其存储在缩略图缓存中,则只会显示真实的缩略图.这意味着我必须手动打开一个文件夹,等待Windows为每个文件生成缩略图,然后我的应用程序将能够看到这些大拇指.
在使用Windows 7之前,我的程序如何强制Windows 7生成实际的缩略图?
更新(由Li0liQ)
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.
解决方法@H_301_30@
这是一段代码,它提取缩略图位图(仅使用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是一种典型的错误.
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是一种典型的错误.