WPF 获取文件夹的缩略图

Posted

技术标签:

【中文标题】WPF 获取文件夹的缩略图【英文标题】:WPF Get Thumbnail of folder 【发布时间】:2020-10-27 01:06:38 【问题描述】:

我想获取文件夹的缩略图,但我没有找到任何方法来使用 WPF。对于 UWP,有一个函数 StorageFolder.GetThumbnailAsync()。但是在 WPF 我没有找到任何解决方案。

【问题讨论】:

看看***.com/a/2994451/1360389也许有帮助。 已经尝试过,但它只适用于文件 你试过ShellFolder吗? 谢谢,我不敢相信我自己没有弄明白。它只是ShellFolder.FromParsingName(FolderPath).Thumbnail.BitmapSource 它有效,而且它也比 UWP 更好。它还为您提供文件夹的真实缩略图,而不仅仅是默认的空文件夹。将其作为答案发布,以便被接受。 【参考方案1】:

我能够通过 pinvoke 以一种不太干净的方式做到这一点,但它可以正常工作,因为它应该看到代码(使用 GetIcon 方法):

 public static class UITools
    
        private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;
        private const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;

        /// <summary>
        /// Converts a <see cref="System.Drawing.Bitmap"/> into a WPF <see cref="BitmapSource"/>.
        /// </summary>
        /// <remarks>Uses GDI to do the conversion. Hence the call to the marshalled DeleteObject.
        /// </remarks>
        /// <param name="source">The source bitmap.</param>
        /// <returns>A BitmapSource</returns>
        public static BitmapSource ToBitmapSource(this System.Drawing.Bitmap source)
        
            BitmapSource bitSrc = null;

            var hBitmap = source.GetHbitmap();

            try
            
                bitSrc = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                    hBitmap,
                    IntPtr.Zero,
                    Int32Rect.Empty,
                    BitmapSizeOptions.FromEmptyOptions());
            
            catch (Win32Exception)
            
                bitSrc = null;
            
            finally
            
                DeleteObject(hBitmap);
            

            return bitSrc;
        

        public static BitmapSource GetIcon(string path,bool isDirectory)
        
            IntPtr hIcon = GetJumboIcon(GetIconIndex(path,isDirectory));
            BitmapSource icon = null;

            using (Icon ico = (Icon)System.Drawing.Icon.FromHandle(hIcon).Clone())
            

                icon = ico.ToBitmap().ToBitmapSource();
            

            DestroyIcon(hIcon);

            return icon;
        

        internal static int GetIconIndex(string pszFile,bool isDirectory)
        
            uint attributes = FILE_ATTRIBUTE_NORMAL;
            if (isDirectory)
                attributes |= FILE_ATTRIBUTE_DIRECTORY;

            SHFILEINFO sfi = new SHFILEINFO();
            NativeMethods.SHGetFileInfo(pszFile
                , attributes //0
                , ref sfi
                , (uint)System.Runtime.InteropServices.Marshal.SizeOf(sfi)
                , (uint)(SHGFI.SysIconIndex | SHGFI.LargeIcon | SHGFI.UseFileAttributes));
            return sfi.iIcon;
        

        // 256*256
        internal static IntPtr GetJumboIcon(int iImage)
        
            IImageList spiml = null;
            Guid guil = new Guid(IID_IImageList); //or IID_IImageList2

            SHGetImageList(SHIL_EXTRALARGE, ref guil, ref spiml);
            IntPtr hIcon = IntPtr.Zero;
            spiml.GetIcon(iImage, ILD_TRANSPARENT | ILD_IMAGE, ref hIcon); //

            return hIcon;
        

    

如您所见,这适用于文件和文件夹。 您可以使用我不久前制作的一个小工具看到它的实际效果: GitHub

【讨论】:

你为什么要传递SHIL_EXTRALARGE 而不是SHIL_JUMBO (0x0004)?只是好奇,你的方法被命名为GetJumboIcon() 顺便说一句,还有从hIcon获取字节数组的方法,因此可以将其传递给IconBitmapDecoder(作为MemoryStream),以从前提中删除System.Drawing。但那是另一回事了。 @Jimi 我正在尝试使用尺寸标志,SHIL_JUMBO 给了我清晰的图标,但有像素化的边缘和 WPF 抗锯齿并没有帮助我解决这种情况,而SHIL_EXTRALARGE 给了我像jumbo一样清晰但边缘柔和的图标,我当时忘记更改方法名称。 是的,当超大尺寸的图标不可用时会发生这种情况,因此无论如何都会返回超大尺寸 (256x256) 的图标,但它实际上是列表中最大(最后一个)图标,放大到要求的尺寸。您可以向该方法添加一个参数,用户可以在其中以枚举数的形式指定 SHIL_ 值(我并不是说您应该在这里更改任何内容,当然,它可以简单地说明一下 - 对于那些谁不知道发生了什么——有什么选择)。 WPF 中的抗锯齿也确实有......它自己的意愿。 @Jimi 谢谢,我不知道放大行为。【参考方案2】:

使用http://***.com/a/2994451/1360389 中提到的Windows API Code Pack 可能会有所帮助。 使用ShellFile.FromFilePath(FilePath).Thumbnail.BitmapSource 文件和 文件夹使用ShellFolder.FromParsingName(FolderPath).Thumbnail.BitmapSource

【讨论】:

以上是关于WPF 获取文件夹的缩略图的主要内容,如果未能解决你的问题,请参考以下文章

获取任意文件类型的缩略图

背水一战 Windows 10 (86) - 文件系统: 获取文件夹的属性, 获取文件夹的缩略图

背水一战 Windows 10 (87) - 文件系统: 获取文件的属性, 修改文件的属性, 获取文件的缩略图

我可以获取特定文件夹中的所有缩略图吗?

有时在获取文件缩略图时位图是颠倒的

Android:如何获取匹配缩略图 URI 的文件路径?