From ac0a1ac301dd4fdea9706688dedf96d596a4908a Mon Sep 17 00:00:00 2001 From: David Hall Date: Sun, 9 Jun 2024 13:09:27 -0600 Subject: [PATCH] Added Windows.Shell.ShellIconExtractor as a threaded way to get all icons for a folder or list of items. --- .../Windows.Shell.Common/ShellIconExtTests.cs | 253 +++++++++++++++++++++ Windows.Shell.Common/ShellIconExtractor.cs | 191 ++++++++++++++++ .../Vanara.Windows.Shell.Common.csproj | 2 +- Windows.Shell.Common/pkgreadme.md | 2 +- Windows.Shell.Common/readme.md | 3 +- 5 files changed, 448 insertions(+), 3 deletions(-) create mode 100644 UnitTests/Windows.Shell.Common/ShellIconExtTests.cs create mode 100644 Windows.Shell.Common/ShellIconExtractor.cs diff --git a/UnitTests/Windows.Shell.Common/ShellIconExtTests.cs b/UnitTests/Windows.Shell.Common/ShellIconExtTests.cs new file mode 100644 index 00000000..27aecd8c --- /dev/null +++ b/UnitTests/Windows.Shell.Common/ShellIconExtTests.cs @@ -0,0 +1,253 @@ +using Microsoft.Win32; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Windows.Forms; +using Vanara.Extensions; +using Vanara.InteropServices; +using Vanara.PInvoke; +using Vanara.PInvoke.Tests; +using static Vanara.PInvoke.Shell32; +using static Vanara.PInvoke.User32; + +namespace Vanara.Windows.Shell.Tests; + +[TestFixture] +public class ShellIconExtTests +{ + [Test] + public void ExtTest() + { + ClearIconCache(); + + //using var psf = new ShellFolder(@"C:\Temp"); + using var psf = new ShellFolder(KNOWNFOLDERID.FOLDERID_SkyDriveDocuments); + ShellIconExtractor extr = new(psf, bmpSize: 96); + var tw = TestContext.Out; + ManualResetEvent evt = new(false); + extr.IconExtracted += (s, e) => tw.WriteLine($"{e.ItemID} = {e.ImageListIndex}"); + extr.Complete += (s, e) => { tw.WriteLine("Done"); evt.Set(); }; + extr.Start(); + Assert.That(evt.WaitOne(5000), Is.True); + } + + private static void ClearIconCache() => Assert.That(SystemVolumeCache.CreateInitializedInstance().Purge(), ResultIs.Successful); + + /*[Test] + public void CreateTest() + { + Ole32.CoInitialize(); + new MyForm().ShowDialog(); + Ole32.CoUninitialize(); + } + + public class MyForm : Form + { + const int icoSz = 64; + readonly Timer timer = new Timer { Interval = 5000 }; + readonly ShellIconExtractor extr; + readonly ShellDataTable data; + private ListView lv; + private readonly System.Threading.CancellationTokenSource cTokSrc = new System.Threading.CancellationTokenSource(); + private readonly List<(string, int)> misses = new List<(string, int)>(); + + public MyForm() + { + SIZE = new SIZE(700, 800); + StartPosition = FormStartPosition.CenterScreen; + TopMost = true; + FormClosing += (s, e) => cTokSrc.Cancel(); + Load += MyForm_Load; + + var fld = new ShellFolder(TestCaseSources.TempDir); + data = new ShellDataTable(fld); + extr = new ShellIconExtractor(fld) { ImageSize = icoSz }; + Controls.Add(lv = new ListView() { Dock = DockStyle.Fill, LargeImageList = extr.ImageList, View = View.LargeIcon }); + + data.RowChanged += (s, e) => { if (e.Action == System.Data.DataRowAction.Add) lv.Invoke((MethodInvoker)(() => { lv.Items.Add(new ListViewItem(e.Row[0].ToString()) { Name = data.GetPIDL(e.Row).ToString(SIGDN.SIGDN_DESKTOPABSOLUTEPARSING) }); })); }; + extr.IconExtracted += (s, e) => lv.Invoke((MethodInvoker)(() => + { + var str = e.ItemID.ToString(SIGDN.SIGDN_DESKTOPABSOLUTEPARSING); + var lvi = lv.Items[str]; + if (lvi != null) + { + lvi.ImageIndex = e.ImageListIndex; + lv.Refresh(); + } + else + misses.Add((str, e.ImageListIndex)); + })); + timer.Tick += (s, e) => { timer.Enabled = false; Close(); }; + //timer.Enabled = true; + } + + private async void MyForm_Load(object sender, EventArgs e) + { + await data.RefreshAsync(cTokSrc.Token); + //await System.Threading.Tasks.Task.Delay(500); + await extr.GetIconsAsync(cTokSrc.Token); + foreach (var i in misses) + lv.Items[i.Item1].ImageIndex = i.Item2; + misses.Clear(); + lv.Refresh(); + } + + //protected override void OnPaint(PaintEventArgs e) + //{ + // using var psf = new ShellFolder(TestCaseSources.TempDir); + // var isf = psf.IShellFolder; + // var pt = e.ClipRectangle.Location; + // var span = icoSz + padSz; + // foreach (var pidl in isf.EnumObjects(SHCONTF.SHCONTF_FOLDERS | SHCONTF.SHCONTF_NONFOLDERS | SHCONTF.SHCONTF_INCLUDEHIDDEN)) + // { + // try + // { + // var lsz = icoSz; + // using var hlbmp = ShellIconExtractor.LoadThumbnail(isf, pidl, ref lsz); + // var ssz = icoSz2; + // using var hsbmp = ShellIconExtractor.LoadThumbnail(isf, pidl, ref ssz); + + // if (hlbmp != null) + // { + // var bmp = hlbmp.ToBitmap(); + // e.Graphics.DrawImage(bmp, new Rectangle(pt.X + padSz, pt.Y + padSz, bmp.Width, bmp.Height), new Rectangle(POINT.Empty, bmp.Size)); + // } + // if (hsbmp != null) + // { + // var bmp = hsbmp.ToBitmap(); + // e.Graphics.DrawImage(bmp, new Rectangle(pt.X + padSz * 2 + (int)icoSz, pt.Y + padSz, bmp.Width, bmp.Height), new Rectangle(POINT.Empty, bmp.Size)); + // } + // } + // catch + // { + // } + // var x = pt.X + span; + // pt = x > (e.ClipRectangle.Right - span) ? new POINT(e.ClipRectangle.Left, pt.Y + (int)icoSz + (padSz * 2)) : new POINT(x, pt.Y); + // } + //} + } + + [Test] + public void GetIconLocationTest() + { + //using var psf = ShellItem.Open("shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}") as ShellFolder; + using var psf = new ShellFolder(TestCaseSources.TempDir); + var isf = psf.IShellFolder; + var list = new List(); + foreach (var pidl in isf.EnumObjects(SHCONTF.SHCONTF_FOLDERS | SHCONTF.SHCONTF_NONFOLDERS | SHCONTF.SHCONTF_INCLUDEHIDDEN)) + { + var watch = Stopwatch.StartNew(); + var (hr, file, iIdx, wFlags) = GetIconLocation(isf, pidl); + watch.Stop(); + list.Add(watch.ElapsedMilliseconds); + TestContext.WriteLine($"{watch.ElapsedMilliseconds,4} = {pidl}; {hr.ToString().TrimEnd('\r', '\n')}; {file},{iIdx}; {wFlags}"); + } + } + + [Test] + public void ExtractTest() + { + //using var psf = ShellItem.Open("shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}") as ShellFolder; + using var psf = new ShellFolder(TestCaseSources.TempDir); + var isf = psf.IShellFolder; + var list = new List(); + foreach (var pidl in isf.EnumObjects(SHCONTF.SHCONTF_FOLDERS | SHCONTF.SHCONTF_NONFOLDERS | SHCONTF.SHCONTF_INCLUDEHIDDEN)) + { + var watch = Stopwatch.StartNew(); + var loc = GetIconLocation(isf, pidl); + if (loc.hr.Failed) { watch.Stop(); continue; } + var hr = ExtractIcons(isf, pidl, loc.file, loc.iIdx, 32, 16, out var ilg, out var ism); + watch.Stop(); + list.Add(watch.ElapsedMilliseconds); + TestContext.WriteLine($"{watch.ElapsedMilliseconds,4} = {pidl}; {hr.ToString().TrimEnd('\r', '\n')};"); + ilg?.Dispose(); ism?.Dispose(); + } + } + + static (HRESULT hr, string file, int iIdx, GetIconLocationResultFlags wFlags) GetIconLocation(IShellFolder psf, PIDL pidl, GetIconLocationFlags flags = GetIconLocationFlags.GIL_FORSHELL) + { + var szIconFile = new StringBuilder(Kernel32.MAX_PATH); + HRESULT hr; + if (psf.GetUIObjectOf(HWND.NULL, 1, new[] { (IntPtr)pidl }, typeof(IExtractIconW).GUID, default, out var eiw).Succeeded) + { + try + { + hr = ((IExtractIconW)eiw).GetIconLocation(flags, szIconFile, szIconFile.Capacity, out var piTempIcon, out var wFlags); + return (hr, hr.Succeeded ? szIconFile.ToString() : null, piTempIcon, wFlags); + } + finally + { + Marshal.ReleaseComObject(eiw); + } + } + else if ((hr = psf.GetUIObjectOf(default, 1, new[] { (IntPtr)pidl }, typeof(IExtractIconA).GUID, default, out var ei)).Succeeded) + { + try + { + hr = ((IExtractIconA)ei).GetIconLocation(flags, szIconFile, szIconFile.Capacity, out var piTempIcon, out var wFlags); + return (hr, hr.Succeeded ? szIconFile.ToString() : null, piTempIcon, wFlags); + } + finally + { + Marshal.ReleaseComObject(ei); + } + } + return (hr, null, 0, 0); + } + + static HRESULT ExtractIcons(IShellFolder psf, PIDL pidl, string szIconFile, int iIndex, ushort lg, ushort sm, out SafeHICON hIcoLg, out SafeHICON hIcoSm) + { + HRESULT hr; + + //// Try IShellIcon first to get icon from system + //if (psf is IShellIcon shi) + //{ + // hr = shi.GetIconOf(pidl, flags, out var iIndex); + // if (hr.Succeeded) + // { + // SHGetImageList((SHIL)iconSize, typeof(IImageList).GUID, out var il).ThrowIfFailed(); + // return il.GetIcon(index, IMAGELISTDRAWFLAGS.ILD_TRANSPARENT); + // } + //} + + // Try IExtractIcon(A&W) next to extract icons + if (psf.GetUIObjectOf(default, 1, new[] { (IntPtr)pidl }, typeof(IExtractIconW).GUID, default, out var eiw).Succeeded) + { + try + { + return ((IExtractIconW)eiw).Extract(szIconFile, (uint)iIndex, lg, out hIcoLg, sm, out hIcoSm); + } + finally + { + Marshal.ReleaseComObject(eiw); + } + } + else if ((hr = psf.GetUIObjectOf(default, 1, new[] { (IntPtr)pidl }, typeof(IExtractIconA).GUID, default, out var ei)).Succeeded) + { + try + { + return ((IExtractIconA)ei).Extract(szIconFile, (uint)iIndex, lg, out hIcoLg, sm, out hIcoSm); + } + finally + { + Marshal.ReleaseComObject(ei); + } + } + + //// Try SHGetFileInfo last + //if (SHGetIDListFromObject(psf, out var fpidl).Succeeded) + //{ + // var shfi = new SHFILEINFO(); + // var ptr = SHGetFileInfo(PIDL.Combine(fpidl, pidl), 0, ref shfi, SHFILEINFO.Size, SHGFI.SHGFI_ICON | SHGFI.SHGFI_ADDOVERLAYS | SHGFI.SHGFI_PIDL); + //} + hIcoLg = hIcoSm = null; + return hr; + } + }*/ +} \ No newline at end of file diff --git a/Windows.Shell.Common/ShellIconExtractor.cs b/Windows.Shell.Common/ShellIconExtractor.cs new file mode 100644 index 00000000..5aa2e84e --- /dev/null +++ b/Windows.Shell.Common/ShellIconExtractor.cs @@ -0,0 +1,191 @@ +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Vanara.PInvoke; +using static Vanara.PInvoke.Shell32; +using static Vanara.PInvoke.Shell32.ShellUtil; + +namespace Vanara.Windows.Shell +{ + /// Event arguments that expose an ID list and associated image. + /// + public class ShellIconExtractedEventArgs(PIDL pidl, int idx) : EventArgs + { + /// Gets the retrieved icon. + /// The icon. + public int ImageListIndex { get; } = idx; + + /// Gets the item ID list. + /// The item ID list. + public PIDL ItemID { get; } = pidl; + } + + /// Class that simplifies extracting icons from items in a Shell Folder. + public class ShellIconExtractor + { + private const int defSize = 32; + private readonly List images = []; + private readonly object imgLock = new(), lookLock = new(); + private readonly FolderItemFilter itemFilter; + private readonly Dictionary lookup = []; + private readonly ShellFolder? parent = null; + private int imageSize = defSize; + private IEnumerable? items = null; + private CancellationTokenSource? lastCanceler; + private List lastRunThreads = []; + + static ShellIconExtractor() + { + if (!FileIconInit(false)) FileIconInit(true); + } + + /// Initializes a new instance of the class to fetch icons for all items in a folder. + /// The folder. + /// The filter to determine which child items of the folder are enumerated. + /// The width and height of the bitmaps to fetch. + public ShellIconExtractor(ShellFolder folder, + FolderItemFilter filter = FolderItemFilter.Folders | FolderItemFilter.NonFolders, + int bmpSize = defSize) + { + parent = folder; + itemFilter = filter; + imageSize = bmpSize; + } + + /// Initializes a new instance of the class. + /// The items. + /// The width and height of the bitmaps to fetch. + public ShellIconExtractor(IEnumerable items, int bmpSize = defSize) : + this(items.Select(i => i.PIDL), bmpSize) + { } + + /// Initializes a new instance of the class. + /// The items. + /// The width and height of the bitmaps to fetch. + public ShellIconExtractor(IEnumerable items, int bmpSize = defSize) + { + this.items = items.ToArray(); + imageSize = bmpSize; + } + + /// Occurs when all icons has been added to . + public event EventHandler? Complete; + + /// Occurs when an updated icon has been added to . + public event EventHandler? IconExtracted; + + /// Gets the list of all images. + /// The list of all images. + public IReadOnlyList ImageList => images; + + /// Gets or sets the width and height of the image. + /// The size of the image. + [DefaultValue(defSize)] + public int ImageSize + { + get => imageSize; + set + { + if (imageSize == value) + return; + imageSize = value; + Refresh(); + } + } + + /// Signals the process to end image retrieval. + public void Cancel() => lastCanceler?.Cancel(); + + /// Refreshes the list of images. + public void Refresh() + { + lastCanceler?.Cancel(); + items ??= parent?.IShellFolder.EnumObjects((SHCONTF)itemFilter); + + if (items is not null) + { + lock (lookLock) lookup.Clear(); + lock (imgLock) images.Clear(); + lastCanceler = new(); + lastRunThreads = []; + + HRESULT hr; + foreach (var i in items) + { + // Get IShellFolder for item + var info = new Info(parent?.IShellFolder, i, imageSize, lastCanceler.Token); + + // Try to get the fast icon from IExtractIcon and then IExtractImage + if ((hr = LoadImageFromImageFactory(info.pidl, ref info.sz, SIIGBF.SIIGBF_INCACHEONLY, out var hbmp)).Succeeded && hbmp != null) + { + using (hbmp) AddBmp(hbmp.ToBitmap(), c => { lock (lookLock) lookup.Add(i, c); IconExtracted?.Invoke(this, new(i, c)); }); ; + } + else + { + // Spin up thread to get the real one + lastRunThreads.Add(Task.Factory.StartNew(GetImageThread, info, lastCanceler.Token)); + } + } + + Task.WhenAll(lastRunThreads).ContinueWith(t => + { + if (!t.IsCanceled) + Complete?.Invoke(this, EventArgs.Empty); + }, lastCanceler.Token); + + void AddBmp(Bitmap bmp, Action? action = null) { lock (imgLock) images.Add(bmp); action?.Invoke(images.Count - 1); } + + void GetImageThread(object? o) + { + var c = (Info)o!; + if (c.ct.IsCancellationRequested) return; + + try + { + var hr = LoadImageFromImageFactory(c.pidl, ref c.sz, 0, out var hbmp); + if (hr.Failed || c.ct.IsCancellationRequested) + return; + AddBmp(hbmp!.ToBitmap(), cnt => { lock (lookLock) lookup[c.pidl] = cnt; IconExtracted?.Invoke(this, new(c.pidl, cnt)); }); + } + finally + { + c.Dispose(); + } + } + } + } + + /// Starts this instance. + public void Start() => Refresh(); + + private class Info(IShellFolder? parent, PIDL pidl, int sz, CancellationToken ct) : IDisposable + { +#if DEBUG + public readonly string name = pidl.ToString(SIGDN.SIGDN_PARENTRELATIVE); +#endif + public readonly CancellationToken ct = ct; + public readonly PIDL pidl = pidl; + public SIZE sz = new(sz, sz); + private bool? isDir = null; + private IShellFolder? isf = parent; + + public bool IsDir => isDir ?? (isDir = IsFolder()).Value; + public IShellFolder parent => isf ??= SHBindToParent(pidl)!; + + public void Dispose() => isf = null; + + private bool IsFolder() + { + if (isf is null) + { + SHFILEINFO sfi = new() { dwAttributes = (int)SFGAO.SFGAO_FOLDER }; + return SHGetFileInfo(pidl, System.IO.FileAttributes.Directory, ref sfi, SHFILEINFO.Size, SHGFI.SHGFI_ATTRIBUTES | SHGFI.SHGFI_ATTR_SPECIFIED) != IntPtr.Zero && sfi.dwAttributes != 0; + } + return (SHGetDataFromIDList(isf, pidl, SHGetDataFormat.SHGDFIL_FINDDATA).dwFileAttributes & System.IO.FileAttributes.Directory) != 0; + } + } + } +} \ No newline at end of file diff --git a/Windows.Shell.Common/Vanara.Windows.Shell.Common.csproj b/Windows.Shell.Common/Vanara.Windows.Shell.Common.csproj index 41f0377a..15ac0c6f 100644 --- a/Windows.Shell.Common/Vanara.Windows.Shell.Common.csproj +++ b/Windows.Shell.Common/Vanara.Windows.Shell.Common.csproj @@ -11,7 +11,7 @@ Currently implements: Classes -AddExtenderEventArgs, AppRegistration, AppSettingsFileListStorage, BindContext, ComClassFactory, CommandVerb, CommandVerbDictionary, ComObject, ComObjWrapper<T>, ControlPanel, DragEventArgs, ExtenderProviderBase<T>, FileInUseHandler, FileTypeAssociation, IconLocation, JumpList, JumpListDestination, JumpListItem, JumpListSeparator, JumpListTask, MemoryPropertyStore, MenuItemInfo, MessageEventArgs, MessageLoop, MRUManager, NativeClipboard, ProgId, PropertyBag, PropertyDescription, PropertyDescriptionList, PropertyStore, PropertyType, PropertyTypeList, ReadOnlyPropertyStore, RecycleBin, RegBasedDictionary<T>, RegBasedSettings, RegistryFileListStorage, SearchCondition, ShellAssociation, ShellAssociationHandler, ShellCommand, ShellContextMenu, ShellDataTable, ShellDropTarget, ShellExecuteCommand, ShellFileInfo, ShellFileNewOpEventArgs, ShellFileOperationDialog, ShellFileOperations, ShellFileOpEventArgs, ShellFolder, ShellFolderCategorizer, ShellFolderCategory, ShellImageList, ShellItem, ShellItemArray, ShellItemChangeEventArgs, ShellItemChangeWatcher, ShellItemImages, ShellItemPropertyStore, ShellItemPropertyUpdates, ShellLibrary, ShellLibraryFolders, ShellLink, ShellNavigationHistory, ShellRegistrar, ShellSearch, ShellSearchViewSettings, StockIcon, Taskbar, TaskbarList, TrayIcon, Utils, WallpaperManager, WallpaperMonitor, WallpaperSlideshow +AddExtenderEventArgs, AppRegistration, AppSettingsFileListStorage, BindContext, ComClassFactory, CommandVerb, CommandVerbDictionary, ComObject, ComObjWrapper<T>, ControlPanel, DragEventArgs, ExtenderProviderBase<T>, FileInUseHandler, FileTypeAssociation, IconLocation, JumpList, JumpListDestination, JumpListItem, JumpListSeparator, JumpListTask, MemoryPropertyStore, MenuItemInfo, MessageEventArgs, MessageLoop, MRUManager, NativeClipboard, ProgId, PropertyBag, PropertyDescription, PropertyDescriptionList, PropertyStore, PropertyType, PropertyTypeList, ReadOnlyPropertyStore, RecycleBin, RegBasedDictionary<T>, RegBasedSettings, RegistryFileListStorage, SearchCondition, ShellAssociation, ShellAssociationHandler, ShellCommand, ShellContextMenu, ShellDataTable, ShellDropTarget, ShellExecuteCommand, ShellFileInfo, ShellFileNewOpEventArgs, ShellFileOperationDialog, ShellFileOperations, ShellFileOpEventArgs, ShellFolder, ShellFolderCategorizer, ShellFolderCategory, ShellIconExtractedEventArgs, ShellIconExtractor, ShellImageList, ShellItem, ShellItemArray, ShellItemChangeEventArgs, ShellItemChangeWatcher, ShellItemImages, ShellItemPropertyStore, ShellItemPropertyUpdates, ShellLibrary, ShellLibraryFolders, ShellLink, ShellNavigationHistory, ShellRegistrar, ShellSearch, ShellSearchViewSettings, StockIcon, Taskbar, TaskbarList, TrayIcon, Utils, WallpaperManager, WallpaperMonitor, WallpaperSlideshow Enumerations ChangeFilters, DialogStatus, ExecutableType, FileUsageType, FolderItemFilter, LibraryFolderFilter, LibraryViewTemplate, LinkResolution, MenuPlacement, OperationFlags, OperationMode, OperationType, ShellIconType, ShellImageSize, ShellItemAttribute, ShellItemComparison, ShellItemDisplayString, ShellItemGetImageOptions, ShellItemToolTipOptions, TaskbarButtonProgressState, TransferFlags, VerbMultiSelectModel, VerbPosition, VerbSelectionModel, WallpaperFit diff --git a/Windows.Shell.Common/pkgreadme.md b/Windows.Shell.Common/pkgreadme.md index d54357bb..ff494656 100644 --- a/Windows.Shell.Common/pkgreadme.md +++ b/Windows.Shell.Common/pkgreadme.md @@ -18,4 +18,4 @@ If you're still running into problems, file an [issue](https://github.com/dahall Classes | Enumerations | Interfaces --- | --- | --- -AddExtenderEventArgs AppRegistration AppSettingsFileListStorage BindContext ComClassFactory CommandVerb CommandVerbDictionary ComObject ComObjWrapper ControlPanel DragEventArgs ExtenderProviderBase FileInUseHandler FileTypeAssociation IconLocation JumpList JumpListDestination JumpListItem JumpListSeparator JumpListTask MemoryPropertyStore MenuItemInfo MessageEventArgs MessageLoop MRUManager NativeClipboard ProgId PropertyBag PropertyDescription PropertyDescriptionList PropertyStore PropertyType PropertyTypeList ReadOnlyPropertyStore RecycleBin RegBasedDictionary RegBasedSettings RegistryFileListStorage SearchCondition ShellAssociation ShellAssociationHandler ShellCommand ShellContextMenu ShellDataTable ShellDropTarget ShellExecuteCommand ShellFileInfo ShellFileNewOpEventArgs ShellFileOperationDialog ShellFileOperations ShellFileOpEventArgs ShellFolder ShellFolderCategorizer ShellFolderCategory ShellImageList ShellItem ShellItemArray ShellItemChangeEventArgs ShellItemChangeWatcher ShellItemImages ShellItemPropertyStore ShellItemPropertyUpdates ShellLibrary ShellLibraryFolders ShellLink ShellNavigationHistory ShellRegistrar ShellSearch ShellSearchViewSettings StockIcon Taskbar TaskbarList TrayIcon Utils WallpaperManager WallpaperMonitor WallpaperSlideshow | ChangeFilters DialogStatus ExecutableType FileUsageType FolderItemFilter LibraryFolderFilter LibraryViewTemplate LinkResolution MenuPlacement OperationFlags OperationMode OperationType ShellIconType ShellImageSize ShellItemAttribute ShellItemComparison ShellItemDisplayString ShellItemGetImageOptions ShellItemToolTipOptions TaskbarButtonProgressState TransferFlags VerbMultiSelectModel VerbPosition VerbSelectionModel WallpaperFit | IComObject IFileListStorage IJumpListItem IMenuBuilder +AddExtenderEventArgs AppRegistration AppSettingsFileListStorage BindContext ComClassFactory CommandVerb CommandVerbDictionary ComObject ComObjWrapper ControlPanel DragEventArgs ExtenderProviderBase FileInUseHandler FileTypeAssociation IconLocation JumpList JumpListDestination JumpListItem JumpListSeparator JumpListTask MemoryPropertyStore MenuItemInfo MessageEventArgs MessageLoop MRUManager NativeClipboard ProgId PropertyBag PropertyDescription PropertyDescriptionList PropertyStore PropertyType PropertyTypeList RecycleBin RegBasedDictionary RegBasedSettings RegistryFileListStorage SearchCondition ShellAssociation ShellAssociationHandler ShellCommand ShellContextMenu ShellDataTable ShellDropTarget ShellExecuteCommand ShellFileInfo ShellFileNewOpEventArgs ShellFileOperationDialog ShellFileOperations ShellFileOpEventArgs ShellFolder ShellFolderCategorizer ShellFolderCategory ShellIconExtractedEventArgs ShellIconExtractor ShellImageList ShellItem ShellItemArray ShellItemChangeEventArgs ShellItemChangeWatcher ShellItemImages ShellItemPropertyStore ShellItemPropertyUpdates ShellLibrary ShellLibraryFolders ShellLink ShellNavigationHistory ShellRegistrar ShellSearch ShellSearchViewSettings StockIcon Taskbar TaskbarList TrayIcon Utils WallpaperManager WallpaperMonitor WallpaperSlideshow | ChangeFilters DialogStatus ExecutableType FileUsageType FolderItemFilter LibraryFolderFilter LibraryViewTemplate LinkResolution MenuPlacement OperationFlags OperationMode OperationType ShellIconType ShellImageSize ShellItemAttribute ShellItemComparison ShellItemDisplayString ShellItemGetImageOptions ShellItemToolTipOptions TaskbarButtonProgressState TransferFlags VerbMultiSelectModel VerbPosition VerbSelectionModel WallpaperFit | IComObject IFileListStorage IJumpListItem IMenuBuilder diff --git a/Windows.Shell.Common/readme.md b/Windows.Shell.Common/readme.md index 3ada3da5..9c9eac2a 100644 --- a/Windows.Shell.Common/readme.md +++ b/Windows.Shell.Common/readme.md @@ -71,7 +71,6 @@ Class | Description [Vanara.Windows.Shell.PropertyStore](https://github.com/dahall/Vanara/search?l=C%23&q=PropertyStore) | Encapsulates the IPropertyStore object. [Vanara.Windows.Shell.PropertyType](https://github.com/dahall/Vanara/search?l=C%23&q=PropertyType) | Exposes methods that extract data from enumeration information. [Vanara.Windows.Shell.PropertyTypeList](https://github.com/dahall/Vanara/search?l=C%23&q=PropertyTypeList) | Exposes methods that enumerate the possible values for a property. -[Vanara.Windows.Shell.ReadOnlyPropertyStore](https://github.com/dahall/Vanara/search?l=C%23&q=ReadOnlyPropertyStore) | Encapsulates the IPropertyStore object. [Vanara.Windows.Shell.RecycleBin](https://github.com/dahall/Vanara/search?l=C%23&q=RecycleBin) | A static object that represents the system Recycle Bin. [Vanara.Windows.Shell.RegBasedDictionary](https://github.com/dahall/Vanara/search?l=C%23&q=RegBasedDictionary) | A virtual dictionary that is based on values in the Windows Registry. [Vanara.Windows.Shell.RegBasedSettings](https://github.com/dahall/Vanara/search?l=C%23&q=RegBasedSettings) | Base class for registry based settings. @@ -92,6 +91,8 @@ Class | Description [Vanara.Windows.Shell.ShellFolder](https://github.com/dahall/Vanara/search?l=C%23&q=ShellFolder) | A folder or container of `Vanara.Windows.Shell.ShellItem` instances. [Vanara.Windows.Shell.ShellFolderCategorizer](https://github.com/dahall/Vanara/search?l=C%23&q=ShellFolderCategorizer) | Exposes a list of categorizers registered on an IShellFolder. [Vanara.Windows.Shell.ShellFolderCategory](https://github.com/dahall/Vanara/search?l=C%23&q=ShellFolderCategory) | A shell folder category object. +[Vanara.Windows.Shell.ShellIconExtractedEventArgs](https://github.com/dahall/Vanara/search?l=C%23&q=ShellIconExtractedEventArgs) | Event arguments that expose an ID list and associated image. +[Vanara.Windows.Shell.ShellIconExtractor](https://github.com/dahall/Vanara/search?l=C%23&q=ShellIconExtractor) | Class that simplifies extracting icons from items in a Shell Folder. [Vanara.Windows.Shell.ShellImageList](https://github.com/dahall/Vanara/search?l=C%23&q=ShellImageList) | Represents the System Image List holding images for all shell icons. [Vanara.Windows.Shell.ShellItem](https://github.com/dahall/Vanara/search?l=C%23&q=ShellItem) | Encapsulates an item in the Windows Shell. [Vanara.Windows.Shell.ShellItemArray](https://github.com/dahall/Vanara/search?l=C%23&q=ShellItemArray) | A folder or container of `Vanara.Windows.Shell.ShellItem` instances.