2020-12-08 12:43:07 -05:00
using System ;
using System.Threading.Tasks ;
using Vanara.Extensions ;
using Vanara.PInvoke ;
using static Vanara . PInvoke . Gdi32 ;
using static Vanara . PInvoke . Shell32 ;
using static Vanara . PInvoke . Shell32 . ShellUtil ;
using static Vanara . PInvoke . User32 ;
namespace Vanara.Windows.Shell
{
/// <summary>Exposes methods that get images related to shell items.</summary>
public class ShellItemImages
{
private readonly ShellItem shellItem ;
/// <summary>Initializes a new instance of the <see cref="ShellItemImages"/> class.</summary>
/// <param name="shellItem">The <see cref="ShellItem"/> instance.</param>
public ShellItemImages ( ShellItem shellItem ) = > this . shellItem = shellItem ;
/// <summary>
/// Gets an image that represents this item. The default behavior is to load a thumbnail. If there is no thumbnail for the current
/// item, it retrieves the icon of the item. The thumbnail or icon is extracted if it is not currently cached.
/// </summary>
/// <param name="size">A structure that specifies the size of the image to be received.</param>
/// <param name="flags">One or more of the option flags.</param>
/// <param name="forcePreVista">If set to <see langword="true"/>, ignore the use post vista interfaces like <see cref="IShellItemImageFactory"/>.</param>
/// <returns>The resulting image.</returns>
/// <exception cref="PlatformNotSupportedException"></exception>
2023-09-12 19:13:27 -04:00
public SafeHBITMAP GetImage ( SIZE size , ShellItemGetImageOptions flags = 0 , bool forcePreVista = false )
2020-12-08 12:43:07 -05:00
{
2023-07-07 17:01:00 -04:00
SafeHBITMAP hbmp = SafeHBITMAP . Null ;
2020-12-08 12:43:07 -05:00
HRESULT hr = HRESULT . E_FAIL ;
var sz = ( uint ) size . Width ;
if ( ! forcePreVista & & ShellItem . IsMinVista )
{
if ( shellItem . IShellItem is IShellItemImageFactory fctry )
{
hr = fctry . GetImage ( size , ( SIIGBF ) flags , out hbmp ) ;
if ( hr = = 0x8004B200 & & flags . IsFlagSet ( ShellItemGetImageOptions . ThumbnailOnly ) )
throw new InvalidOperationException ( "Thumbnails are not supported by this item." ) ;
2021-02-04 16:22:56 -05:00
if ( hr . Succeeded )
return hbmp ;
2020-12-08 12:43:07 -05:00
}
//hr = LoadImageFromThumbnailProvider(shellItem.IShellItem, ref sz, out hbmp);
}
// If before Vista, or if Vista interfaces failed, try using IExtractImage and IExtractIcon
2023-07-07 17:01:00 -04:00
var isf = shellItem . Parent ? . IShellFolder ;
if ( hr ! = HRESULT . S_OK & & ! flags . IsFlagSet ( ShellItemGetImageOptions . IconOnly ) & & isf is not null )
hr = LoadImageFromExtractImage ( isf , shellItem . PIDL . LastId , ref sz , out hbmp ) ;
if ( hr ! = HRESULT . S_OK & & isf is not null )
2020-12-08 12:43:07 -05:00
{
if ( ! flags . IsFlagSet ( ShellItemGetImageOptions . ThumbnailOnly ) )
{
2023-07-07 17:01:00 -04:00
LoadIconFromExtractIcon ( isf , shellItem . PIDL . LastId , ref sz , out SafeHICON hIcon ) . ThrowIfFailed ( ) ;
2020-12-08 12:43:07 -05:00
using ( hIcon )
hbmp = hIcon . ToHBITMAP ( ) ;
}
else
{
2023-09-12 19:13:27 -04:00
throw hr . GetException ( ) ! ;
2020-12-08 12:43:07 -05:00
}
}
// If you got a bitmap, resize based on flags
2023-09-12 19:13:27 -04:00
if ( sz = = size . Width | | sz > size . Width & & flags . IsFlagSet ( ShellItemGetImageOptions . BiggerSizeOk ) )
2020-12-08 12:43:07 -05:00
return hbmp ;
2023-09-12 19:13:27 -04:00
if ( sz > size . Width & & flags . IsFlagSet ( ShellItemGetImageOptions . ResizeToFit ) | | sz < size . Width & & flags . IsFlagSet ( ShellItemGetImageOptions . ScaleUp ) )
2020-12-08 12:43:07 -05:00
{
HANDLE hbmpcp = CopyImage ( hbmp . DangerousGetHandle ( ) , LoadImageType . IMAGE_BITMAP , size . Width , size . Height , CopyImageOptions . LR_CREATEDIBSECTION ) ;
if ( hbmpcp . IsNull ) Win32Error . ThrowLastError ( ) ;
hbmp . Dispose ( ) ;
hbmp = new SafeHBITMAP ( ( IntPtr ) hbmpcp , true ) ;
}
return hbmp ;
2023-09-12 19:13:27 -04:00
}
/// <summary>
/// Gets an image that represents this item. The default behavior is to load a thumbnail. If there is no thumbnail for the current
/// item, it retrieves the icon of the item. The thumbnail or icon is extracted if it is not currently cached.
/// </summary>
/// <param name="size">A structure that specifies the size of the image to be received.</param>
/// <param name="flags">One or more of the option flags.</param>
/// <param name="forcePreVista">If set to <see langword="true"/>, ignore the use post vista interfaces like <see cref="IShellItemImageFactory"/>.</param>
/// <returns>The resulting image.</returns>
/// <exception cref="PlatformNotSupportedException"></exception>
public async Task < SafeHBITMAP > GetImageAsync ( SIZE size , ShellItemGetImageOptions flags = 0 , bool forcePreVista = false ) = > await TaskAgg . Run ( ( ) = >
GetImage ( size , flags , forcePreVista ) , System . Threading . CancellationToken . None ) ;
2020-12-08 12:43:07 -05:00
}
}