| File: System\Drawing\SystemIcons.cs | Web Access |
| Project: src\winforms\src\System.Drawing.Common\src\System.Drawing.Common.csproj (System.Drawing.Common) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; using Windows.Win32.UI.Shell; namespace System.Drawing; public static class SystemIcons { private static Icon? s_application; private static Icon? s_asterisk; private static Icon? s_error; private static Icon? s_exclamation; private static Icon? s_hand; private static Icon? s_information; private static Icon? s_question; private static Icon? s_warning; private static Icon? s_winlogo; private static Icon? s_shield; public static Icon Application => GetIcon(ref s_application, PInvokeCore.IDI_APPLICATION); public static Icon Asterisk => GetIcon(ref s_asterisk, PInvokeCore.IDI_ASTERISK); public static Icon Error => GetIcon(ref s_error, PInvokeCore.IDI_ERROR); public static Icon Exclamation => GetIcon(ref s_exclamation, PInvokeCore.IDI_EXCLAMATION); public static Icon Hand => GetIcon(ref s_hand, PInvokeCore.IDI_HAND); public static Icon Information => GetIcon(ref s_information, PInvokeCore.IDI_INFORMATION); public static Icon Question => GetIcon(ref s_question, PInvokeCore.IDI_QUESTION); public static Icon Warning => GetIcon(ref s_warning, PInvokeCore.IDI_WARNING); public static Icon WinLogo => GetIcon(ref s_winlogo, PInvokeCore.IDI_WINLOGO); public static Icon Shield => s_shield ??= new Icon(typeof(SystemIcons), "ShieldIcon.ico"); private static Icon GetIcon(ref Icon? icon, PCWSTR iconId) => icon ??= new Icon(PInvokeCore.LoadIcon(HINSTANCE.Null, iconId)); #if NET8_0_OR_GREATER /// <summary> /// Gets the specified Windows shell stock icon. /// </summary> /// <param name="stockIcon">The stock icon to retrieve.</param> /// <param name="options">Options for retrieving the icon.</param> /// <returns>The requested <see cref="Icon"/>.</returns> /// <remarks> /// <para> /// Unlike the static icon properties in <see cref="SystemIcons"/>, this API returns icons that are themed /// for the running version of Windows. Additionally, the returned <see cref="Icon"/> is not cached and /// should be disposed when no longer needed. /// </para> /// </remarks> /// <exception cref="ArgumentException"><paramref name="stockIcon"/> is an invalid <see cref="StockIconId"/>.</exception> public static unsafe Icon GetStockIcon(StockIconId stockIcon, StockIconOptions options = StockIconOptions.Default) { // Note that we don't explicitly check for invalid StockIconId to allow for accessing newer ids introduced // in later OSes. The HRESULT returned for undefined ids gets converted to an ArgumentException. SHSTOCKICONINFO info = new() { cbSize = (uint)sizeof(SHSTOCKICONINFO), }; HRESULT result = PInvoke.SHGetStockIconInfo( (SHSTOCKICONID)stockIcon, (SHGSI_FLAGS)options | SHGSI_FLAGS.SHGSI_ICON, &info); // This only throws if there is an error. Marshal.ThrowExceptionForHR((int)result); return new Icon(info.hIcon, takeOwnership: true); } /// <inheritdoc cref="GetStockIcon(StockIconId, StockIconOptions)"/> /// <param name="size"> /// The desired size. If the specified size does not exist, an existing size will be resampled to give the /// requested size. /// </param> public static unsafe Icon GetStockIcon(StockIconId stockIcon, int size) { // Note that we don't explicitly check for invalid StockIconId to allow for accessing newer ids introduced // in later OSes. The HRESULT returned for undefined ids gets converted to an ArgumentException. SHSTOCKICONINFO info = new() { cbSize = (uint)sizeof(SHSTOCKICONINFO), }; HRESULT result = PInvoke.SHGetStockIconInfo( (SHSTOCKICONID)stockIcon, SHGSI_FLAGS.SHGSI_ICONLOCATION, &info); // This only throws if there is an error. Marshal.ThrowExceptionForHR((int)result); HICON hicon; result = PInvoke.SHDefExtractIcon( info.szPath, info.iIcon, 0, &hicon, null, (uint)(ushort)size << 16 | (ushort)size); Marshal.ThrowExceptionForHR((int)result); return new Icon(hicon, takeOwnership: true); } #endif }