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 { /// Exposes methods that get images related to shell items. public class ShellItemImages { private readonly ShellItem shellItem; /// Initializes a new instance of the class. /// The instance. public ShellItemImages(ShellItem shellItem) => this.shellItem = shellItem; /// /// 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. /// /// A structure that specifies the size of the image to be received. /// One or more of the option flags. /// If set to , ignore the use post vista interfaces like . /// The resulting image. /// public SafeHBITMAP GetImage(SIZE size, ShellItemGetImageOptions flags = 0, bool forcePreVista = false) { SafeHBITMAP hbmp = SafeHBITMAP.Null; 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."); if (hr.Succeeded) return hbmp; } //hr = LoadImageFromThumbnailProvider(shellItem.IShellItem, ref sz, out hbmp); } // If before Vista, or if Vista interfaces failed, try using IExtractImage and IExtractIcon 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) { if (!flags.IsFlagSet(ShellItemGetImageOptions.ThumbnailOnly)) { LoadIconFromExtractIcon(isf, shellItem.PIDL.LastId, ref sz, out SafeHICON hIcon).ThrowIfFailed(); using (hIcon) hbmp = hIcon.ToHBITMAP(); } else { throw hr.GetException()!; } } // If you got a bitmap, resize based on flags if (sz == size.Width || sz > size.Width && flags.IsFlagSet(ShellItemGetImageOptions.BiggerSizeOk)) return hbmp; if (sz > size.Width && flags.IsFlagSet(ShellItemGetImageOptions.ResizeToFit) || sz < size.Width && flags.IsFlagSet(ShellItemGetImageOptions.ScaleUp)) { 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; } /// /// 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. /// /// A structure that specifies the size of the image to be received. /// One or more of the option flags. /// If set to , ignore the use post vista interfaces like . /// The resulting image. /// public async Task GetImageAsync(SIZE size, ShellItemGetImageOptions flags = 0, bool forcePreVista = false) => await TaskAgg.Run(() => GetImage(size, flags, forcePreVista), System.Threading.CancellationToken.None); } }