using System; using System.Collections.Generic; using System.Runtime.InteropServices; using Vanara.Extensions; using Vanara.PInvoke; using static Vanara.PInvoke.Shell32; namespace Vanara.Windows.Shell { /// Defines options for filtering folder items. public enum LibraryFolderFilter { /// Return only file system items. FileSystemOnly = LIBRARYFOLDERFILTER.LFF_FORCEFILESYSTEM, /// Return items that can be bound to an IStorage object. StorageObjects = LIBRARYFOLDERFILTER.LFF_STORAGEITEMS, /// Return all items. AllItems = LIBRARYFOLDERFILTER.LFF_ALLITEMS } /// Defines the type of view assigned to a library folder. public enum LibraryViewTemplate { /// Introduced in Windows 8.1. The folder does not fall under one of the other categories. General = FOLDERTYPEID.FOLDERTYPEID_StorageProviderGeneric, /// Introduced in Windows 8.1. The folder contains document files. These can be of mixed format—.doc, .txt, and others. Documents = FOLDERTYPEID.FOLDERTYPEID_StorageProviderDocuments, /// Introduced in Windows 8.1. The folder contains image files, such as .jpg, .tif, or .png files. Pictures = FOLDERTYPEID.FOLDERTYPEID_StorageProviderPictures, /// Introduced in Windows 8.1. The folder contains audio files, such as .mp3 and .wma files. Music = FOLDERTYPEID.FOLDERTYPEID_StorageProviderMusic, /// Introduced in Windows 8.1. The folder contains video files. These can be of mixed format—.wmv, .mov, and others. Videos = FOLDERTYPEID.FOLDERTYPEID_StorageProviderVideos, /// A custom template defined in the registry. Use for the identifier. Custom = -1, } /// Shell library encapsulation. /// public class ShellLibrary : ShellFolder { //private const string ext = ".library-ms"; internal IShellLibrary lib; private ShellLibraryFolders folders; private string name; /// Initializes a new instance of the class. /// The known folder identifier. /// if set to true [read only]. public ShellLibrary(KNOWNFOLDERID knownFolderId, bool readOnly = false) { lib = new IShellLibrary(); lib.LoadLibraryFromKnownFolder(knownFolderId.Guid(), readOnly ? STGM.STGM_READ : STGM.STGM_READWRITE); Init(knownFolderId.GetIShellItem()); } /// Initializes a new instance of the class. /// Name of the library. /// The known folder identifier. /// if set to true [overwrite]. public ShellLibrary(string libraryName, KNOWNFOLDERID kf = KNOWNFOLDERID.FOLDERID_Libraries, bool overwrite = false) { lib = new IShellLibrary(); name = libraryName; lib.SaveInKnownFolder(kf.Guid(), libraryName, overwrite ? LIBRARYSAVEFLAGS.LSF_OVERRIDEEXISTING : LIBRARYSAVEFLAGS.LSF_FAILIFTHERE); } /// Initializes a new instance of the class. /// Name of the library. /// The parent. /// if set to true [overwrite]. public ShellLibrary(string libraryName, ShellFolder parent, bool overwrite = false) { lib = new IShellLibrary(); name = libraryName; lib.Save(parent.iShellItem, libraryName, overwrite ? LIBRARYSAVEFLAGS.LSF_OVERRIDEEXISTING : LIBRARYSAVEFLAGS.LSF_FAILIFTHERE); } /// Initializes a new instance of the class. /// The i item. /// if set to true [read only]. internal ShellLibrary(IShellItem iItem, bool readOnly = false) : base(iItem) { lib = new IShellLibrary(); lib.LoadLibraryFromItem(iItem, readOnly ? STGM.STGM_READ : STGM.STGM_READWRITE); } /// Gets or sets the default target folder the library uses for save operations. /// The default save folder. public ShellItem DefaultSaveFolder { get => Open(lib.GetDefaultSaveFolder(DEFAULTSAVEFOLDERTYPE.DSFT_DETECT)); set => lib.SetDefaultSaveFolder(DEFAULTSAVEFOLDERTYPE.DSFT_DETECT, value.iShellItem); } /// Gets the set of child folders that are contained in the library. /// A containing the child folders. public ShellLibraryFolders Folders => folders ?? (folders = GetFilteredFolders()); /// /// Gets or sets a string that describes the location of the default icon. The string must be formatted as /// ModuleFileName,ResourceIndex or ModuleFileName,-ResourceID. /// /// The default icon location. public IconLocation IconLocation { get { IconLocation.TryParse(lib.GetIcon(), out var l); return l; } set => lib.SetIcon(value.ToString()); } /// Gets the name relative to the parent for the item. public override string Name { get => name; protected set => name = value; } /// Gets or sets a value indicating whether to pin the library to the navigation pane. /// true if pinned to the navigation pane; otherwise, false. public bool PinnedToNavigationPane { get => lib.GetOptions().IsFlagSet(LIBRARYOPTIONFLAGS.LOF_PINNEDTONAVPANE); set => lib.SetOptions(LIBRARYOPTIONFLAGS.LOF_PINNEDTONAVPANE, value ? LIBRARYOPTIONFLAGS.LOF_PINNEDTONAVPANE : 0); } /// Gets or sets the library's View Template. /// The View Template. public LibraryViewTemplate ViewTemplate { get => (LibraryViewTemplate)ShlGuidExt.Lookup(ViewTemplateId); set { if (value != LibraryViewTemplate.Custom) ViewTemplateId = ((FOLDERTYPEID)value).Guid(); } } /// Gets or sets the library's View Template identifier. /// The View Template identifier. public Guid ViewTemplateId { get => lib.GetFolderType(); set => lib.SetFolderType(value); } /// Commits library updates. public void Commit() => lib.Commit(); /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. public override void Dispose() { lib = null; base.Dispose(); } /// Gets the set of child folders that are contained in the library. /// A value that determines the folders to get. /// A containing the child folders. public ShellLibraryFolders GetFilteredFolders(LibraryFolderFilter filter = LibraryFolderFilter.AllItems) => new(lib, lib.GetFolders((LIBRARYFOLDERFILTER)filter)); /// Resolves the target location of a library folder, even if the folder has been moved or renamed. /// A ShellItem object that represents the library folder to locate. /// /// The maximum time the method will attempt to locate the folder before returning. If the folder could not be located before the /// specified time elapses, an error is returned. /// /// The resulting target location. public ShellItem ResolveFolder(ShellItem item, TimeSpan timeout) => Open(lib.ResolveFolder(item.iShellItem, Convert.ToUInt32(timeout.TotalMilliseconds))); /// Shows the library management dialog box, which enables users to manage the library folders and default save location. /// /// The handle for the window that owns the library management dialog box. The value of this parameter can be NULL. /// /// /// The title for the library management dialog. To display the generic title string, set the value of this parameter to NULL. /// /// /// The help string to display below the title string in the library management dialog box. To display the generic help string, set /// the value of this parameter to NULL. /// /// /// if set to true do not display a warning dialog to the user in collisions that concern network locations that cannot be indexed. /// public void ShowLibraryManagementDialog(HWND parentWindow = default, string title = null, string instruction = null, bool allowUnindexableLocations = false) { SHShowManageLibraryUI(iShellItem, parentWindow, title, instruction, allowUnindexableLocations ? LIBRARYMANAGEDIALOGOPTIONS.LMD_ALLOWUNINDEXABLENETWORKLOCATIONS : LIBRARYMANAGEDIALOGOPTIONS.LMD_DEFAULT).ThrowIfFailed(); } /// Folders of a . /// /// public class ShellLibraryFolders : ShellItemArray, ICollection { private IShellLibrary lib; /// Initializes a new instance of the class. /// The library. /// The shell item array. internal ShellLibraryFolders(IShellLibrary lib, IShellItemArray shellItemArray) : base(shellItemArray) => this.lib = lib; /// Gets a value indicating whether the is read-only. bool ICollection.IsReadOnly => false; /// Adds the specified location. /// The location. /// location public void Add(ShellItem location) { if (location == null) throw new ArgumentNullException(nameof(location)); lib.AddFolder(location.iShellItem); } /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. public override void Dispose() { lib = null; base.Dispose(); } /// Removes the specified location. /// The location. /// true on success. /// location public bool Remove(ShellItem location) { if (location == null) throw new ArgumentNullException(nameof(location)); try { lib.RemoveFolder(location.iShellItem); return true; } catch { return false; } } /// Removes all items from the . /// void ICollection.Clear() => throw new NotImplementedException(); } } }