using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.InteropServices; using Vanara.Extensions; using static Vanara.PInvoke.Ole32; using static Vanara.PInvoke.PropSys; namespace Vanara.Windows.Shell { /// A property store for a . /// public sealed class ShellItemPropertyStore : PropertyStore { /// The shell item private readonly ShellItem shellItem; /// The flags. private GETPROPERTYSTOREFLAGS flags = GETPROPERTYSTOREFLAGS.GPS_DEFAULT; /// Initializes a new instance of the class. /// The ShellItem instance. /// The optional property changed handler. internal ShellItemPropertyStore(ShellItem item, PropertyChangedEventHandler propChangedHandler = null) { shellItem = item; Refresh(); if (propChangedHandler != null) PropertyChanged += propChangedHandler; } /// Gets a property description list object containing descriptions of all properties. /// A complete instance. public PropertyDescriptionList Descriptions => shellItem.PropertyDescriptions; /// Gets or sets a value indicating whether to include slow properties. /// true if including slow properties; otherwise, false. [DefaultValue(false)] public bool IncludeSlow { get => flags.IsFlagSet(GETPROPERTYSTOREFLAGS.GPS_OPENSLOWITEM); set { if (IncludeSlow == value) return; flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_OPENSLOWITEM, value); if (value) flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY | GETPROPERTYSTOREFLAGS.GPS_FASTPROPERTIESONLY, false); Refresh(); } } /// Gets a value indicating whether the is read-only. public override bool IsReadOnly => ReadOnly; /// Gets or sets a value indicating whether to include only properties directly from the property handler. /// true if no inherited properties; otherwise, false. [DefaultValue(false)] public bool NoInheritedProperties { get => flags.IsFlagSet(GETPROPERTYSTOREFLAGS.GPS_HANDLERPROPERTIESONLY); set { if (NoInheritedProperties == value) return; flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_HANDLERPROPERTIESONLY, value); if (value) flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY | GETPROPERTYSTOREFLAGS.GPS_BESTEFFORT | GETPROPERTYSTOREFLAGS.GPS_FASTPROPERTIESONLY, false); Refresh(); } } /// Gets or sets a value indicating whether properties can be read and written. /// true if properties are read/write; otherwise, false. [DefaultValue(true)] public bool ReadOnly { get => !flags.IsFlagSet(GETPROPERTYSTOREFLAGS.GPS_READWRITE); set { if (ReadOnly == value) return; flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_READWRITE, !value); if (!value) flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_DELAYCREATION | GETPROPERTYSTOREFLAGS.GPS_TEMPORARY | GETPROPERTYSTOREFLAGS.GPS_BESTEFFORT | GETPROPERTYSTOREFLAGS.GPS_FASTPROPERTIESONLY, false); else flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_HANDLERPROPERTIESONLY); Refresh(); } } /// /// Gets or sets a value indicating whether this provides a writable store, with no initial properties, that exists /// for the lifetime of the Shell item instance; basically, a property bag attached to the item instance.. /// /// true if temporary; otherwise, false. [DefaultValue(false)] public bool Temporary { get => flags.IsFlagSet(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY); set { if (Temporary == value) return; flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY, value); if (value) { flags = GETPROPERTYSTOREFLAGS.GPS_TEMPORARY; ReadOnly = false; } else { flags = flags.SetFlags(GETPROPERTYSTOREFLAGS.GPS_TEMPORARY, false); Refresh(); } } } /// Gets the CLSID of a supplied property key. /// The property key. /// The CLSID related to the property key. public Guid GetCLSID(PROPERTYKEY propertyKey) { shellItem.ThrowIfNoShellItem2(); return shellItem.iShellItem2.GetCLSID(propertyKey); } /// Refreshes this instance. This call is intended for internal use only and should not need to be called. public void Refresh() { shellItem.ThrowIfNoShellItem2(); if (iprops != null) Marshal.ReleaseComObject(iprops); iprops = shellItem.iShellItem2.GetPropertyStore(flags, typeof(IPropertyStore).GUID); } } }