@@ -228,9 +228,31 @@ private class IconAndOverlayCacheEntry
228
228
229
229
private static readonly object _lock = new object ( ) ;
230
230
231
- public static ( byte [ ] ? icon , byte [ ] ? overlay ) GetFileIconAndOverlay ( string path , int thumbnailSize , bool isFolder , bool getIconOnly , bool getOverlay = true , bool onlyGetOverlay = false )
231
+ /// <summary>
232
+ /// Returns an icon when a thumbnail isn't available or if getIconOnly is true
233
+ /// Returns an icon overlay when getOverlay is true
234
+ /// Returns a boolean indicating if the icon/thumbnail is cached
235
+ /// </summary>
236
+ /// <param name="path"></param>
237
+ /// <param name="thumbnailSize"></param>
238
+ /// <param name="isFolder"></param>
239
+ /// <param name="getIconOnly"></param>
240
+ /// <param name="getOverlay"></param>
241
+ /// <param name="onlyGetOverlay"></param>
242
+ /// <returns></returns>
243
+ public static ( byte [ ] ? icon , byte [ ] ? overlay , bool isIconCached ) GetFileIconAndOverlay
244
+ (
245
+ string path ,
246
+ int thumbnailSize ,
247
+ bool isFolder ,
248
+ bool getIconOnly ,
249
+ bool getOverlay = true ,
250
+ bool onlyGetOverlay = false
251
+ )
232
252
{
233
253
byte [ ] ? iconData = null , overlayData = null ;
254
+ bool isIconCached = false ;
255
+
234
256
var entry = _iconAndOverlayCache . GetOrAdd ( path , _ => new ( ) ) ;
235
257
236
258
if ( entry . TryGetValue ( thumbnailSize , out var cacheEntry ) )
@@ -242,34 +264,36 @@ public static (byte[]? icon, byte[]? overlay) GetFileIconAndOverlay(string path,
242
264
( ! getOverlay && iconData is not null ) ||
243
265
( overlayData is not null && iconData is not null ) )
244
266
{
245
- return ( iconData , overlayData ) ;
267
+ return ( iconData , overlayData , true ) ;
246
268
}
247
269
}
248
270
249
271
try
250
272
{
251
- if ( ! onlyGetOverlay )
252
- {
253
- using var shellItem = SafetyExtensions . IgnoreExceptions ( ( )
254
- => ShellFolderExtensions . GetShellItemFromPathOrPIDL ( path ) ) ;
273
+ // Attempt to get file icon/thumbnail using IShellItemImageFactory GetImage
274
+ using var shellItem = SafetyExtensions . IgnoreExceptions ( ( )
275
+ => ShellFolderExtensions . GetShellItemFromPathOrPIDL ( path ) ) ;
255
276
256
- if ( shellItem is not null && shellItem . IShellItem is Shell32 . IShellItemImageFactory fctry )
257
- {
258
- var flags = Shell32 . SIIGBF . SIIGBF_BIGGERSIZEOK ;
277
+ if ( shellItem is not null && shellItem . IShellItem is Shell32 . IShellItemImageFactory shellFactory )
278
+ {
279
+ var flags = Shell32 . SIIGBF . SIIGBF_BIGGERSIZEOK ;
259
280
260
- if ( getIconOnly )
261
- flags |= Shell32 . SIIGBF . SIIGBF_ICONONLY ;
281
+ if ( getIconOnly )
282
+ flags |= Shell32 . SIIGBF . SIIGBF_ICONONLY ;
283
+ else
284
+ flags |= Shell32 . SIIGBF . SIIGBF_THUMBNAILONLY ;
262
285
263
- var hres = fctry . GetImage ( new SIZE ( thumbnailSize , thumbnailSize ) , flags , out var hbitmap ) ;
264
- if ( hres == HRESULT . S_OK )
265
- {
266
- using var image = GetBitmapFromHBitmap ( hbitmap ) ;
267
- if ( image is not null )
268
- iconData = ( byte [ ] ? ) new ImageConverter ( ) . ConvertTo ( image , typeof ( byte [ ] ) ) ;
269
- }
286
+ var hres = shellFactory . GetImage ( new SIZE ( thumbnailSize , thumbnailSize ) , flags , out var hbitmap ) ;
287
+ if ( hres == HRESULT . S_OK )
288
+ {
289
+ using var image = GetBitmapFromHBitmap ( hbitmap ) ;
290
+ if ( image is not null )
291
+ iconData = ( byte [ ] ? ) new ImageConverter ( ) . ConvertTo ( image , typeof ( byte [ ] ) ) ;
270
292
271
- //Marshal.ReleaseComObject(fctry) ;
293
+ isIconCached = true ;
272
294
}
295
+
296
+ Marshal . ReleaseComObject ( shellFactory ) ;
273
297
}
274
298
275
299
if ( getOverlay || ( ! onlyGetOverlay && iconData is null ) )
@@ -284,7 +308,7 @@ public static (byte[]? icon, byte[]? overlay) GetFileIconAndOverlay(string path,
284
308
Shell32 . SHGetFileInfo ( pidl , 0 , ref shfi , Shell32 . SHFILEINFO . Size , Shell32 . SHGFI . SHGFI_PIDL | flags ) :
285
309
Shell32 . SHGetFileInfo ( path , isFolder ? FileAttributes . Directory : 0 , ref shfi , Shell32 . SHFILEINFO . Size , flags | ( useFileAttibutes ? Shell32 . SHGFI . SHGFI_USEFILEATTRIBUTES : 0 ) ) ;
286
310
if ( ret == IntPtr . Zero )
287
- return ( iconData , null ) ;
311
+ return ( iconData , null , isIconCached ) ;
288
312
289
313
User32 . DestroyIcon ( shfi . hIcon ) ;
290
314
@@ -299,7 +323,7 @@ public static (byte[]? icon, byte[]? overlay) GetFileIconAndOverlay(string path,
299
323
lock ( _lock )
300
324
{
301
325
if ( ! Shell32 . SHGetImageList ( imageListSize , typeof ( ComCtl32 . IImageList ) . GUID , out var imageListOut ) . Succeeded )
302
- return ( iconData , null ) ;
326
+ return ( iconData , null , isIconCached ) ;
303
327
304
328
var imageList = ( ComCtl32 . IImageList ) imageListOut ;
305
329
@@ -352,11 +376,11 @@ public static (byte[]? icon, byte[]? overlay) GetFileIconAndOverlay(string path,
352
376
Marshal . ReleaseComObject ( imageList ) ;
353
377
}
354
378
355
- return ( iconData , overlayData ) ;
379
+ return ( iconData , overlayData , isIconCached ) ;
356
380
}
357
381
else
358
382
{
359
- return ( iconData , null ) ;
383
+ return ( iconData , null , isIconCached ) ;
360
384
}
361
385
}
362
386
finally
0 commit comments