using System; using System.Drawing; using Vanara.PInvoke; using static Vanara.PInvoke.Shell32; using static Vanara.PInvoke.User32; namespace Vanara.Windows.Shell { /// Represents a standard system icon. public class StockIcon : IDisposable { private SHGSI curFlags; private SHSTOCKICONID curId; private HICON hIcon; private IconLocation location; private int systemImageIndex; static StockIcon() => FileIconInit(false); /// Creates a new StockIcon instance with the specified identifer and options. /// A value that identifies the icon represented by this instance. /// A value that indicates the size of the stock icon. /// A bool value that indicates whether the icon has a link overlay. /// A bool value that indicates whether the icon is in a selected state. public StockIcon(SHSTOCKICONID id, ShellIconType size = ShellIconType.Large, bool isLinkOverlay = false, bool isSelected = false) { Identifier = id; LinkOverlay = isLinkOverlay; Selected = isSelected; Size = size; } /// Finalizes an instance of the class. ~StockIcon() { Dispose(false); } /// Gets the icon image in format. public Bitmap Bitmap { get { Refresh(); return hIcon.IsNull ? null : Bitmap.FromHicon((IntPtr)hIcon); } } /// Gets the icon image in format. public Icon Icon { get { Refresh(); return hIcon.IsNull ? null : Icon.FromHandle((IntPtr)hIcon); } } /// Gets the icon handle. /// The icon handle. public HICON IconHandle => hIcon; /// Gets or sets the Stock Icon identifier associated with this icon. public SHSTOCKICONID Identifier { get; set; } /// Gets or sets a value that cotrols whether to put a link overlay on the icon. /// A value. public bool LinkOverlay { get; set; } /// Gets the icon location, composed of a resource path and the icon's index. /// The icon location. public IconLocation Location { get { Refresh(); return location; } } /// Gets or sets a value indicating whether the icon appears selected. /// A value. public bool Selected { get; set; } /// Gets or sets a value that controls the size of the Stock Icon. /// A value. public ShellIconType Size { get; set; } /// Gets the index of the image in the system icon cache. /// The index of the system image. public int SystemImageIndex { get { Refresh(); return systemImageIndex; } } /// Release the native objects public void Dispose() { Dispose(true); System.GC.SuppressFinalize(this); } /// Release the native and managed objects /// Indicates that this is being called from Dispose(), rather than the finalizer. protected virtual void Dispose(bool disposing) { if (disposing) { // dispose managed resources here } // Unmanaged resources if (hIcon != IntPtr.Zero) DestroyIcon(hIcon); } private SHGSI GetFlags() => SHGSI.SHGSI_ICON | SHGSI.SHGSI_ICONLOCATION | SHGSI.SHGSI_SYSICONINDEX | (SHGSI)Size | (Selected ? SHGSI.SHGSI_SELECTED : 0) | (LinkOverlay ? SHGSI.SHGSI_LINKOVERLAY : 0); private void Refresh() { var flags = GetFlags(); if (curFlags == flags && curId == Identifier) return; if (hIcon != IntPtr.Zero) { DestroyIcon(hIcon); hIcon = default; } var info = SHSTOCKICONINFO.Default; var hr = SHGetStockIconInfo(curId = Identifier, curFlags = flags, ref info); // If we get an error, return null as the icon requested might not be supported on the current system if (hr == HRESULT.E_INVALIDARG) throw new InvalidOperationException("Invalid identifier."); else if (hr.Succeeded) { hIcon = info.hIcon; location = new IconLocation(info.szPath, info.iIcon); systemImageIndex = info.iSysImageIndex; } else { location = null; systemImageIndex = 0; } } } }