using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Vanara.Extensions;
using Vanara.PInvoke;
using static Vanara.PInvoke.Shell32;
// ReSharper disable UnusedMember.Global
// ReSharper disable MemberCanBePrivate.Global
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 kf.
/// 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, typeof(IShellItem).GUID));
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.StringValue);
}
/// 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()
{
if (lib != null)
{
Marshal.ReleaseComObject(lib);
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 ShellLibraryFolders(lib, lib.GetFolders((LIBRARYFOLDERFILTER)filter, typeof(IShellItemArray).GUID));
/// 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), typeof(IShellItem).GUID));
/// 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(IWin32Window parentWindow = null, string title = null, string instruction = null, bool allowUnindexableLocations = false)
{
SHShowManageLibraryUI(iShellItem, parentWindow?.Handle ?? IntPtr.Zero, 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()
{
if (lib != null)
{
Marshal.ReleaseComObject(lib);
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();
}
}
}