WindowsThumbnailProvider.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Runtime.InteropServices;
  6. using System.Windows;
  7. using System.Windows.Media.Imaging;
  8. using System.Windows.Media;
  9. using System.Diagnostics;
  10. using System.Drawing;
  11. namespace GeekDesk.Util
  12. {
  13. public class WindowsThumbnailProvider
  14. {
  15. private struct RECT
  16. {
  17. public int Left;
  18. public int Top;
  19. public int Right;
  20. public int Bottom;
  21. }
  22. private struct POINT
  23. {
  24. public int x;
  25. public int y;
  26. }
  27. // Constants that we need in the function call
  28. private const int SHGFI_ICON = 0x100;
  29. private const int SHGFI_SMALLICON = 0x1;
  30. private const int SHGFI_LARGEICON = 0x0;
  31. private const int SHIL_JUMBO = 0x4;
  32. private const int SHIL_EXTRALARGE = 0x2;
  33. // This structure will contain information about the file
  34. public struct SHFILEINFO
  35. {
  36. // Handle to the icon representing the file
  37. public IntPtr hIcon;
  38. // Index of the icon within the image list
  39. public int iIcon;
  40. // Various attributes of the file
  41. public uint dwAttributes;
  42. // Path to the file
  43. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
  44. public string szDisplayName;
  45. // File type
  46. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
  47. public string szTypeName;
  48. };
  49. [System.Runtime.InteropServices.DllImport("Kernel32.dll")]
  50. public static extern Boolean CloseHandle(IntPtr handle);
  51. private struct IMAGELISTDRAWPARAMS
  52. {
  53. public int cbSize;
  54. public IntPtr himl;
  55. public int i;
  56. public IntPtr hdcDst;
  57. public int x;
  58. public int y;
  59. public int cx;
  60. public int cy;
  61. public int xBitmap; // x offest from the upperleft of bitmap
  62. public int yBitmap; // y offset from the upperleft of bitmap
  63. public int rgbBk;
  64. public int rgbFg;
  65. public int fStyle;
  66. public int dwRop;
  67. public int fState;
  68. public int Frame;
  69. public int crEffect;
  70. }
  71. [StructLayout(LayoutKind.Sequential)]
  72. private struct IMAGEINFO
  73. {
  74. public IntPtr hbmImage;
  75. public IntPtr hbmMask;
  76. public int Unused1;
  77. public int Unused2;
  78. public RECT rcImage;
  79. }
  80. #region Private ImageList COM Interop (XP)
  81. [ComImportAttribute()]
  82. [GuidAttribute("46EB5926-582E-4017-9FDF-E8998DAA0950")]
  83. [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
  84. //helpstring("Image List"),
  85. interface IImageList
  86. {
  87. [PreserveSig]
  88. int Add(
  89. IntPtr hbmImage,
  90. IntPtr hbmMask,
  91. ref int pi);
  92. [PreserveSig]
  93. int ReplaceIcon(
  94. int i,
  95. IntPtr hicon,
  96. ref int pi);
  97. [PreserveSig]
  98. int SetOverlayImage(
  99. int iImage,
  100. int iOverlay);
  101. [PreserveSig]
  102. int Replace(
  103. int i,
  104. IntPtr hbmImage,
  105. IntPtr hbmMask);
  106. [PreserveSig]
  107. int AddMasked(
  108. IntPtr hbmImage,
  109. int crMask,
  110. ref int pi);
  111. [PreserveSig]
  112. int Draw(
  113. ref IMAGELISTDRAWPARAMS pimldp);
  114. [PreserveSig]
  115. int Remove(
  116. int i);
  117. [PreserveSig]
  118. int GetIcon(
  119. int i,
  120. int flags,
  121. ref IntPtr picon);
  122. [PreserveSig]
  123. int GetImageInfo(
  124. int i,
  125. ref IMAGEINFO pImageInfo);
  126. [PreserveSig]
  127. int Copy(
  128. int iDst,
  129. IImageList punkSrc,
  130. int iSrc,
  131. int uFlags);
  132. [PreserveSig]
  133. int Merge(
  134. int i1,
  135. IImageList punk2,
  136. int i2,
  137. int dx,
  138. int dy,
  139. ref Guid riid,
  140. ref IntPtr ppv);
  141. [PreserveSig]
  142. int Clone(
  143. ref Guid riid,
  144. ref IntPtr ppv);
  145. [PreserveSig]
  146. int GetImageRect(
  147. int i,
  148. ref RECT prc);
  149. [PreserveSig]
  150. int GetIconSize(
  151. ref int cx,
  152. ref int cy);
  153. [PreserveSig]
  154. int SetIconSize(
  155. int cx,
  156. int cy);
  157. [PreserveSig]
  158. int GetImageCount(
  159. ref int pi);
  160. [PreserveSig]
  161. int SetImageCount(
  162. int uNewCount);
  163. [PreserveSig]
  164. int SetBkColor(
  165. int clrBk,
  166. ref int pclr);
  167. [PreserveSig]
  168. int GetBkColor(
  169. ref int pclr);
  170. [PreserveSig]
  171. int BeginDrag(
  172. int iTrack,
  173. int dxHotspot,
  174. int dyHotspot);
  175. [PreserveSig]
  176. int EndDrag();
  177. [PreserveSig]
  178. int DragEnter(
  179. IntPtr hwndLock,
  180. int x,
  181. int y);
  182. [PreserveSig]
  183. int DragLeave(
  184. IntPtr hwndLock);
  185. [PreserveSig]
  186. int DragMove(
  187. int x,
  188. int y);
  189. [PreserveSig]
  190. int SetDragCursorImage(
  191. ref IImageList punk,
  192. int iDrag,
  193. int dxHotspot,
  194. int dyHotspot);
  195. [PreserveSig]
  196. int DragShowNolock(
  197. int fShow);
  198. [PreserveSig]
  199. int GetDragImage(
  200. ref POINT ppt,
  201. ref POINT pptHotspot,
  202. ref Guid riid,
  203. ref IntPtr ppv);
  204. [PreserveSig]
  205. int GetItemFlags(
  206. int i,
  207. ref int dwFlags);
  208. [PreserveSig]
  209. int GetOverlayImage(
  210. int iOverlay,
  211. ref int piIndex);
  212. };
  213. #endregion
  214. ///
  215. /// SHGetImageList is not exported correctly in XP. See KB316931
  216. /// http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q316931
  217. /// Apparently (and hopefully) ordinal 727 isn't going to change.
  218. ///
  219. [DllImport("shell32.dll", EntryPoint = "#727")]
  220. private extern static int SHGetImageList(
  221. int iImageList,
  222. ref Guid riid,
  223. out IImageList ppv
  224. );
  225. // The signature of SHGetFileInfo (located in Shell32.dll)
  226. [DllImport("Shell32.dll")]
  227. public static extern int SHGetFileInfo(string pszPath, int dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, uint uFlags);
  228. [DllImport("Shell32.dll")]
  229. public static extern int SHGetFileInfo(IntPtr pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, uint uFlags);
  230. [DllImport("shell32.dll", SetLastError = true)]
  231. static extern int SHGetSpecialFolderLocation(IntPtr hwndOwner, Int32 nFolder,
  232. ref IntPtr ppidl);
  233. [DllImport("user32")]
  234. public static extern int DestroyIcon(IntPtr hIcon);
  235. public struct pair
  236. {
  237. public System.Drawing.Icon icon { get; set; }
  238. public IntPtr iconHandleToDestroy { set; get; }
  239. }
  240. public static int DestroyIcon2(IntPtr hIcon)
  241. {
  242. return DestroyIcon(hIcon);
  243. }
  244. private static BitmapSource bitmap_source_of_icon(System.Drawing.Icon ic)
  245. {
  246. var ic2 = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(ic.Handle,
  247. System.Windows.Int32Rect.Empty,
  248. System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
  249. ic2.Freeze();
  250. return ((BitmapSource)ic2);
  251. }
  252. //public static BitmapSource SystemIcon(bool small, ShellLib.ShellApi.CSIDL csidl)
  253. //{
  254. // IntPtr pidlTrash = IntPtr.Zero;
  255. // int hr = SHGetSpecialFolderLocation(IntPtr.Zero, (int)csidl, ref pidlTrash);
  256. // Debug.Assert(hr == 0);
  257. // SHFILEINFO shinfo = new SHFILEINFO();
  258. // uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
  259. // // Get a handle to the large icon
  260. // uint flags;
  261. // uint SHGFI_PIDL = 0x000000008;
  262. // if (!small)
  263. // {
  264. // flags = SHGFI_PIDL | SHGFI_ICON | SHGFI_LARGEICON | SHGFI_USEFILEATTRIBUTES;
  265. // }
  266. // else
  267. // {
  268. // flags = SHGFI_PIDL | SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES;
  269. // }
  270. // var res = SHGetFileInfo(pidlTrash, 0, ref shinfo, Marshal.SizeOf(shinfo), flags);
  271. // Debug.Assert(res != 0);
  272. // var myIcon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
  273. // Marshal.FreeCoTaskMem(pidlTrash);
  274. // var bs = bitmap_source_of_icon(myIcon);
  275. // myIcon.Dispose();
  276. // bs.Freeze(); // importantissimo se no fa memory leak
  277. // DestroyIcon(shinfo.hIcon);
  278. // CloseHandle(shinfo.hIcon);
  279. // return bs;
  280. //}
  281. public static BitmapSource icon_of_path(string FileName, bool small, bool checkDisk, bool addOverlay)
  282. {
  283. SHFILEINFO shinfo = new SHFILEINFO();
  284. uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
  285. uint SHGFI_LINKOVERLAY = 0x000008000;
  286. uint flags;
  287. if (small)
  288. {
  289. flags = SHGFI_ICON | SHGFI_SMALLICON;
  290. }
  291. else
  292. {
  293. flags = SHGFI_ICON | SHGFI_LARGEICON;
  294. }
  295. if (!checkDisk)
  296. flags |= SHGFI_USEFILEATTRIBUTES;
  297. if (addOverlay)
  298. flags |= SHGFI_LINKOVERLAY;
  299. var res = SHGetFileInfo(FileName, 0, ref shinfo, Marshal.SizeOf(shinfo), flags);
  300. if (res == 0)
  301. {
  302. throw (new System.IO.FileNotFoundException());
  303. }
  304. var myIcon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
  305. var bs = bitmap_source_of_icon(myIcon);
  306. myIcon.Dispose();
  307. bs.Freeze(); // importantissimo se no fa memory leak
  308. DestroyIcon(shinfo.hIcon);
  309. CloseHandle(shinfo.hIcon);
  310. return bs;
  311. }
  312. public static Icon icon_of_path_large(string FileName, bool jumbo, bool checkDisk)
  313. {
  314. SHFILEINFO shinfo = new SHFILEINFO();
  315. uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
  316. uint SHGFI_SYSICONINDEX = 0x4000;
  317. int FILE_ATTRIBUTE_NORMAL = 0x80;
  318. uint flags;
  319. flags = SHGFI_SYSICONINDEX;
  320. if (!checkDisk) // This does not seem to work. If I try it, a folder icon is always returned.
  321. flags |= SHGFI_USEFILEATTRIBUTES;
  322. var res = SHGetFileInfo(FileName, FILE_ATTRIBUTE_NORMAL, ref shinfo, Marshal.SizeOf(shinfo), flags);
  323. if (res == 0)
  324. {
  325. throw (new System.IO.FileNotFoundException());
  326. }
  327. var iconIndex = shinfo.iIcon;
  328. // Get the System IImageList object from the Shell:
  329. Guid iidImageList = new Guid("46EB5926-582E-4017-9FDF-E8998DAA0950");
  330. IImageList iml;
  331. int size = jumbo ? SHIL_JUMBO : SHIL_EXTRALARGE;
  332. var hres = SHGetImageList(size, ref iidImageList, out iml); // writes iml
  333. //if (hres == 0)
  334. //{
  335. // throw (new System.Exception("Error SHGetImageList"));
  336. //}
  337. IntPtr hIcon = IntPtr.Zero;
  338. int ILD_TRANSPARENT = 1;
  339. hres = iml.GetIcon(iconIndex, ILD_TRANSPARENT, ref hIcon);
  340. //if (hres == 0)
  341. //{
  342. // throw (new System.Exception("Error iml.GetIcon"));
  343. //}
  344. var myIcon = System.Drawing.Icon.FromHandle(hIcon);
  345. var bs = bitmap_source_of_icon(myIcon);
  346. myIcon.Dispose();
  347. bs.Freeze(); // very important to avoid memory leak
  348. //DestroyIcon(hIcon);
  349. //CloseHandle(hIcon);
  350. return myIcon;
  351. }
  352. }
  353. }