首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >C#通过windows api从文件中获取缩略图

C#通过windows api从文件中获取缩略图
EN

Stack Overflow用户
提问于 2009-09-17 15:52:36
回答 5查看 75.6K关注 0票数 79

Windows资源管理器能够显示文件的缩略图。这些缩略图由核心和第三方shell扩展提供。

我知道如何扩展shell来为Windows提供缩略图。

我想要做的是使用C#通过shell从系统上的任何文件中检索缩略图。这个是可能的吗?

从本质上讲,我正在编写一个自定义的文件浏览器,我想要显示缩略图,而不可能解析地球上的每个文件来生成我自己的缩略图。

澄清:许多答案似乎都集中在网页缩略图或缩放图像上。但这根本不是我要找的。我想要的是向Windows要这些文件类型的缩略图表示:.DOC、.PDF、.3DM、.DWG……可能还有十几个。我不想自己解析、渲染和制作缩略图,因为Windows已经知道怎么做了。

我作为答案发布的代码实际上是有效的。也许它可以被简化和清理一点。

EN

回答 5

Stack Overflow用户

发布于 2009-09-17 23:15:33

这可能会有所帮助:

http://blogs.msdn.com/windowssdk/archive/2009/06/12/windows-api-code-pack-for-microsoft-net-framework.aspx

这包括Shell API,并允许您执行shell所能执行的几乎所有操作(包括呈现缩略图)。

票数 7
EN

Stack Overflow用户

发布于 2009-09-17 21:55:21

这是我在互联网上搜索到的一个类。它看起来像是来自http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_21789724.html的原始代码,但是我看不到它给出正确的属性。我在这里找到了源码:http://www.vbforums.com/showthread.php?t=527704

下面是一个带有正确的COM调用的类,在这里复制给后人:

using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace RMA.Shell
{
  public class ShellThumbnail : IDisposable
  {

    [Flags]
    private enum ESTRRET
    {
      STRRET_WSTR = 0,
      STRRET_OFFSET = 1,
      STRRET_CSTR = 2
    }

    [Flags]
    private enum ESHCONTF
    {
      SHCONTF_FOLDERS = 32,
      SHCONTF_NONFOLDERS = 64,
      SHCONTF_INCLUDEHIDDEN = 128,
    }

    [Flags]
    private enum ESHGDN
    {
      SHGDN_NORMAL = 0,
      SHGDN_INFOLDER = 1,
      SHGDN_FORADDRESSBAR = 16384,
      SHGDN_FORPARSING = 32768
    }

    [Flags]
    private enum ESFGAO
    {
      SFGAO_CANCOPY = 1,
      SFGAO_CANMOVE = 2,
      SFGAO_CANLINK = 4,
      SFGAO_CANRENAME = 16,
      SFGAO_CANDELETE = 32,
      SFGAO_HASPROPSHEET = 64,
      SFGAO_DROPTARGET = 256,
      SFGAO_CAPABILITYMASK = 375,
      SFGAO_LINK = 65536,
      SFGAO_SHARE = 131072,
      SFGAO_READONLY = 262144,
      SFGAO_GHOSTED = 524288,
      SFGAO_DISPLAYATTRMASK = 983040,
      SFGAO_FILESYSANCESTOR = 268435456,
      SFGAO_FOLDER = 536870912,
      SFGAO_FILESYSTEM = 1073741824,
      SFGAO_HASSUBFOLDER = -2147483648,
      SFGAO_CONTENTSMASK = -2147483648,
      SFGAO_VALIDATE = 16777216,
      SFGAO_REMOVABLE = 33554432,
      SFGAO_COMPRESSED = 67108864,
    }

    private enum EIEIFLAG
    {
      IEIFLAG_ASYNC = 1,
      IEIFLAG_CACHE = 2,
      IEIFLAG_ASPECT = 4,
      IEIFLAG_OFFLINE = 8,
      IEIFLAG_GLEAM = 16,
      IEIFLAG_SCREEN = 32,
      IEIFLAG_ORIGSIZE = 64,
      IEIFLAG_NOSTAMP = 128,
      IEIFLAG_NOBORDER = 256,
      IEIFLAG_QUALITY = 512
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0, CharSet = CharSet.Auto)]
    private struct STRRET_CSTR
    {
      public ESTRRET uType;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 520)]
      public byte[] cStr;
    }

    [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
    private struct STRRET_ANY
    {
      [FieldOffset(0)]
      public ESTRRET uType;
      [FieldOffset(4)]
      public IntPtr pOLEString;
    }
    [StructLayoutAttribute(LayoutKind.Sequential)]
    private struct SIZE
    {
      public int cx;
      public int cy;
    }

    [ComImport(), Guid("00000000-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IUnknown
    {

      [PreserveSig()]
      IntPtr QueryInterface(ref Guid riid, ref IntPtr pVoid);

      [PreserveSig()]
      IntPtr AddRef();

      [PreserveSig()]
      IntPtr Release();
    }

    [ComImportAttribute()]
    [GuidAttribute("00000002-0000-0000-C000-000000000046")]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IMalloc
    {

      [PreserveSig()]
      IntPtr Alloc(int cb);

      [PreserveSig()]
      IntPtr Realloc(IntPtr pv, int cb);

      [PreserveSig()]
      void Free(IntPtr pv);

      [PreserveSig()]
      int GetSize(IntPtr pv);

      [PreserveSig()]
      int DidAlloc(IntPtr pv);

      [PreserveSig()]
      void HeapMinimize();
    }

    [ComImportAttribute()]
    [GuidAttribute("000214F2-0000-0000-C000-000000000046")]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IEnumIDList
    {

      [PreserveSig()]
      int Next(int celt, ref IntPtr rgelt, ref int pceltFetched);

      void Skip(int celt);

      void Reset();

      void Clone(ref IEnumIDList ppenum);
    }

    [ComImportAttribute()]
    [GuidAttribute("000214E6-0000-0000-C000-000000000046")]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IShellFolder
    {

      void ParseDisplayName(IntPtr hwndOwner, IntPtr pbcReserved,
        [MarshalAs(UnmanagedType.LPWStr)]string lpszDisplayName,
        ref int pchEaten, ref IntPtr ppidl, ref int pdwAttributes);

      void EnumObjects(IntPtr hwndOwner,
        [MarshalAs(UnmanagedType.U4)]ESHCONTF grfFlags,
        ref IEnumIDList ppenumIDList);

      void BindToObject(IntPtr pidl, IntPtr pbcReserved, ref Guid riid,
        ref IShellFolder ppvOut);

      void BindToStorage(IntPtr pidl, IntPtr pbcReserved, ref Guid riid, IntPtr ppvObj);

      [PreserveSig()]
      int CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);

      void CreateViewObject(IntPtr hwndOwner, ref Guid riid,
        IntPtr ppvOut);

      void GetAttributesOf(int cidl, IntPtr apidl,
        [MarshalAs(UnmanagedType.U4)]ref ESFGAO rgfInOut);

      void GetUIObjectOf(IntPtr hwndOwner, int cidl, ref IntPtr apidl, ref Guid riid, ref int prgfInOut, ref IUnknown ppvOut);

      void GetDisplayNameOf(IntPtr pidl,
        [MarshalAs(UnmanagedType.U4)]ESHGDN uFlags,
        ref STRRET_CSTR lpName);

      void SetNameOf(IntPtr hwndOwner, IntPtr pidl,
        [MarshalAs(UnmanagedType.LPWStr)]string lpszName,
        [MarshalAs(UnmanagedType.U4)] ESHCONTF uFlags,
        ref IntPtr ppidlOut);
    }
    [ComImportAttribute(), GuidAttribute("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IExtractImage
    {
      void GetLocation([Out(), MarshalAs(UnmanagedType.LPWStr)]
        StringBuilder pszPathBuffer, int cch, ref int pdwPriority, ref SIZE prgSize, int dwRecClrDepth, ref int pdwFlags);

      void Extract(ref IntPtr phBmpThumbnail);
    }

    private class UnmanagedMethods
    {

      [DllImport("shell32", CharSet = CharSet.Auto)]
      internal extern static int SHGetMalloc(ref IMalloc ppMalloc);

      [DllImport("shell32", CharSet = CharSet.Auto)]
      internal extern static int SHGetDesktopFolder(ref IShellFolder ppshf);

      [DllImport("shell32", CharSet = CharSet.Auto)]
      internal extern static int SHGetPathFromIDList(IntPtr pidl, StringBuilder pszPath);

      [DllImport("gdi32", CharSet = CharSet.Auto)]
      internal extern static int DeleteObject(IntPtr hObject);

    }

    ~ShellThumbnail()
    {
      Dispose();
    }

    private IMalloc alloc = null;
    private bool disposed = false;
    private Size _desiredSize = new Size(100, 100);
    private Bitmap _thumbNail;

    public Bitmap ThumbNail
    {
      get
      {
        return _thumbNail;
      }
    }

    public Size DesiredSize
    {
      get { return _desiredSize; }
      set { _desiredSize = value; }
    }
    private IMalloc Allocator
    {
      get
      {
        if (!disposed)
        {
          if (alloc == null)
          {
            UnmanagedMethods.SHGetMalloc(ref alloc);
          }
        }
        else
        {
          Debug.Assert(false, "Object has been disposed.");
        }
        return alloc;
      }
    }

    public Bitmap GetThumbnail(string fileName)
    {
      if (string.IsNullOrEmpty(fileName))
        return null;

      if (!File.Exists(fileName) && !Directory.Exists(fileName))
      {
        throw new FileNotFoundException(string.Format("The file '{0}' does not exist", fileName), fileName);
      }
      if (_thumbNail != null)
      {
        _thumbNail.Dispose();
        _thumbNail = null;
      }
      IShellFolder folder = null;
      try
      {
        folder = getDesktopFolder;
      }
      catch (Exception ex)
      {
        throw ex;
      }
      if (folder != null)
      {
        IntPtr pidlMain = IntPtr.Zero;
        try
        {
          int cParsed = 0;
          int pdwAttrib = 0;
          string filePath = Path.GetDirectoryName(fileName);
          folder.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, filePath, ref cParsed, ref pidlMain, ref pdwAttrib);
        }
        catch (Exception ex)
        {
          Marshal.ReleaseComObject(folder);
          throw ex;
        }
        if (pidlMain != IntPtr.Zero)
        {
          Guid iidShellFolder = new Guid("000214E6-0000-0000-C000-000000000046");
          IShellFolder item = null;
          try
          {
            folder.BindToObject(pidlMain, IntPtr.Zero, ref iidShellFolder, ref item);
          }
          catch (Exception ex)
          {
            Marshal.ReleaseComObject(folder);
            Allocator.Free(pidlMain);
            throw ex;
          }
          if (item != null)
          {
            IEnumIDList idEnum = null;
            try
            {
              item.EnumObjects(IntPtr.Zero, (ESHCONTF.SHCONTF_FOLDERS | ESHCONTF.SHCONTF_NONFOLDERS), ref idEnum);
            }
            catch (Exception ex)
            {
              Marshal.ReleaseComObject(folder);
              Allocator.Free(pidlMain);
              throw ex;
            }
            if (idEnum != null)
            {
              int hRes = 0;
              IntPtr pidl = IntPtr.Zero;
              int fetched = 0;
              bool complete = false;
              while (!complete)
              {
                hRes = idEnum.Next(1, ref pidl, ref fetched);
                if (hRes != 0)
                {
                  pidl = IntPtr.Zero;
                  complete = true;
                }
                else
                {
                  if (_getThumbNail(fileName, pidl, item))
                  {
                    complete = true;
                  }
                }
                if (pidl != IntPtr.Zero)
                {
                  Allocator.Free(pidl);
                }
              }
              Marshal.ReleaseComObject(idEnum);
            }
            Marshal.ReleaseComObject(item);
          }
          Allocator.Free(pidlMain);
        }
        Marshal.ReleaseComObject(folder);
      }
      return ThumbNail;
    }

    private bool _getThumbNail(string file, IntPtr pidl, IShellFolder item)
    {
      IntPtr hBmp = IntPtr.Zero;
      IExtractImage extractImage = null;
      try
      {
        string pidlPath = PathFromPidl(pidl);
        if (Path.GetFileName(pidlPath).ToUpper().Equals(Path.GetFileName(file).ToUpper()))
        {
          IUnknown iunk = null;
          int prgf = 0;
          Guid iidExtractImage = new Guid("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1");
          item.GetUIObjectOf(IntPtr.Zero, 1, ref pidl, ref iidExtractImage, ref prgf, ref iunk);
          extractImage = (IExtractImage)iunk;
          if (extractImage != null)
          {
            Console.WriteLine("Got an IExtractImage object!");
            SIZE sz = new SIZE();
            sz.cx = DesiredSize.Width;
            sz.cy = DesiredSize.Height;
            StringBuilder location = new StringBuilder(260, 260);
            int priority = 0;
            int requestedColourDepth = 32;
            EIEIFLAG flags = EIEIFLAG.IEIFLAG_ASPECT | EIEIFLAG.IEIFLAG_SCREEN;
            int uFlags = (int)flags;
            try
            {
              extractImage.GetLocation(location, location.Capacity, ref priority, ref sz, requestedColourDepth, ref uFlags);
              extractImage.Extract(ref hBmp);
            }
            catch (System.Runtime.InteropServices.COMException ex)
            {

            }
            if (hBmp != IntPtr.Zero)
            {
              _thumbNail = Bitmap.FromHbitmap(hBmp);
            }
            Marshal.ReleaseComObject(extractImage);
            extractImage = null;
          }
          return true;
        }
        else
        {
          return false;
        }
      }
      catch (Exception ex)
      {
        if (hBmp != IntPtr.Zero)
        {
          UnmanagedMethods.DeleteObject(hBmp);
        }
        if (extractImage != null)
        {
          Marshal.ReleaseComObject(extractImage);
        }
        throw ex;
      }
    }

    private string PathFromPidl(IntPtr pidl)
    {
      StringBuilder path = new StringBuilder(260, 260);
      int result = UnmanagedMethods.SHGetPathFromIDList(pidl, path);
      if (result == 0)
      {
        return string.Empty;
      }
      else
      {
        return path.ToString();
      }
    }

    private IShellFolder getDesktopFolder
    {
      get
      {
        IShellFolder ppshf = null;
        int r = UnmanagedMethods.SHGetDesktopFolder(ref ppshf);
        return ppshf;
      }
    }

    public void Dispose()
    {
      if (!disposed)
      {
        if (alloc != null)
        {
          Marshal.ReleaseComObject(alloc);
        }
        alloc = null;
        if (_thumbNail != null)
        {
          _thumbNail.Dispose();
        }
        disposed = true;
      }
    }
  }
}
票数 3
EN

Stack Overflow用户

发布于 2009-09-17 16:33:27

不完全是你要的,是here's a project to open a Thumbs.db file

The Wikipedia article has more information关于在Vista & 7中哪里可以找到缩略图。

下面是获取图片的代码:

public byte[] GetThumbData(string filename)
{
    IStorageWrapper wrapper = new IStorageWrapper(_thumbDBFile, false);
    foreach(CatalogItem catItem in _catalogItems)
    {
        if (catItem.filename == filename)
        {
            string streamName = BuildReverseString(catItem.itemID);
            FileObject fileObject = wrapper.OpenUCOMStream(null, streamName);
            byte[] rawJPGData = new byte [fileObject.Length];
            fileObject.Read(rawJPGData, 0, (int)fileObject.Length);
            fileObject.Close();

            // 3 ints of header data need to be removed
            // Don't know what first int is.
            // 2nd int is thumb index
            // 3rd is size of thumbnail data.
            byte[] jpgData = new byte[rawJPGData.Length - 12];
            for (int index = 12; index < jpgData.Length; index++)
            {
                jpgData[index - 12] = rawJPGData[index];
            }
            return jpgData;
        }
    }
    return null;
}

public Image GetThumbnailImage(string filename)
{
    byte[] thumbData = GetThumbData(filename);
    if (null == thumbData)
    {
        return null;
    }
    MemoryStream ms = new MemoryStream(thumbData);
    Image img = Image.FromStream(ms);
    return img;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1439719

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档