From 258cab3ad95ab94c92e1588beaf4259373f708d3 Mon Sep 17 00:00:00 2001 From: David Hall Date: Tue, 20 Dec 2022 15:06:37 -0700 Subject: [PATCH] Added NativeClipboard.GetFileNameMap, GetShellItemArray, IsFormatAvailable(string) and SetShellItems methods (#353) --- UnitTests/Windows.Shell/ClipboardTests.cs | 14 +++++++++++ Windows.Shell.Common/NativeClipboard.cs | 41 +++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/UnitTests/Windows.Shell/ClipboardTests.cs b/UnitTests/Windows.Shell/ClipboardTests.cs index e18d02b2..598138f4 100644 --- a/UnitTests/Windows.Shell/ClipboardTests.cs +++ b/UnitTests/Windows.Shell/ClipboardTests.cs @@ -1,8 +1,10 @@ using NUnit.Framework; using System; using System.Linq; +using System.Threading; using System.Windows.Forms; using Vanara.PInvoke; +using Vanara.PInvoke.Tests; using static Vanara.PInvoke.Shell32; using Clipboard = Vanara.Windows.Shell.NativeClipboard; using WFClipboard = System.Windows.Forms.Clipboard; @@ -57,6 +59,18 @@ namespace Vanara.Windows.Shell.Tests Assert.That(Clipboard.GetFirstFormatAvailable(fmts), Is.GreaterThan(0)); } + [Test] + public void GetSetShellItems() + { + //Ole32.OleInitialize(); + //string[] files = { TestCaseSources.SmallFile, TestCaseSources.ImageFile, TestCaseSources.LogFile }; + //ShellItemArray items = new(Array.ConvertAll(files, f => new ShellItem(f))); + //Clipboard.SetShellItems(items); + var shArray = Clipboard.GetShellItemArray(); + Assert.That(shArray.Count, Is.GreaterThan(0)); + //Assert.IsTrue(files.SequenceEqual(shArray.Select(s => s.FileSystemPath))); + } + [Test] public void SetNativeTextHtmlTest() { diff --git a/Windows.Shell.Common/NativeClipboard.cs b/Windows.Shell.Common/NativeClipboard.cs index 47fe2c86..3aec8b6a 100644 --- a/Windows.Shell.Common/NativeClipboard.cs +++ b/Windows.Shell.Common/NativeClipboard.cs @@ -167,6 +167,21 @@ namespace Vanara.Windows.Shell /// The object associated with the request. If no object can be determined, default(T) is returned. public static T GetData(uint formatId, int index = -1) => DataObject.GetData(formatId, index); + /// + /// This is used when a group of files in CF_HDROP (FileDrop) format is being renamed as well as transferred. The data consists of an + /// array that contains a new name for each file, in the same order that the files are listed in the accompanying CF_HDROP format. + /// The format of the character array is the same as that used by CF_HDROP to list the transferred files. + /// + /// A list of strings containing a new name for each file. + public static string[] GetFileNameMap() + { + if (IsFormatAvailable(ShellClipboardFormat.CFSTR_FILENAMEMAPW)) + return DataObject.GetData(RegisterFormat(ShellClipboardFormat.CFSTR_FILENAMEMAPW)) as string[]; + else if (IsFormatAvailable(ShellClipboardFormat.CFSTR_FILENAMEMAPA)) + return DataObject.GetData(RegisterFormat(ShellClipboardFormat.CFSTR_FILENAMEMAPA)) as string[]; + return new string[0]; + } + /// Retrieves the first available clipboard format in the specified list. /// The clipboard formats, in priority order. /// @@ -213,6 +228,10 @@ namespace Vanara.Windows.Shell /// public static HWND GetOpenClipboardWindow() => User32.GetOpenClipboardWindow(); + /// Gets the shell item array associated with the data object, if possible. + /// The associated with the data object, if set. Otherwise, . + public static ShellItemArray GetShellItemArray() => IsFormatAvailable(ShellClipboardFormat.CFSTR_SHELLIDLIST) ? ShellItemArray.FromDataObject(DataObject) : null; + /// Determines whether the data object pointer previously placed on the clipboard is still on the clipboard. /// /// The IDataObject interface on the data object containing clipboard data of interest, which the caller previously placed on the clipboard. @@ -225,6 +244,11 @@ namespace Vanara.Windows.Shell /// If the clipboard format is available, the return value is ; otherwise . public static bool IsFormatAvailable(uint id) => IsClipboardFormatAvailable(id); + /// Determines whether the clipboard contains data in the specified format. + /// A clipboard format string. + /// If the clipboard format is available, the return value is ; otherwise . + public static bool IsFormatAvailable(string id) => IsClipboardFormatAvailable(RegisterFormat(id)); + /// Registers a new clipboard format. This format can then be used as a valid clipboard format. /// The name of the new format. /// The registered clipboard format identifier. @@ -248,6 +272,23 @@ namespace Vanara.Windows.Shell return id; } + /// Puts a list of shell items onto the clipboard. + /// The sequence of shell items. + public static void SetShellItems(IEnumerable shellItems) + { + var pidls = shellItems.Select(i => i.PIDL).ToArray(); + SHCreateDataObject(PIDL.Null, (uint)pidls.Length, Array.ConvertAll(pidls, p => p.DangerousGetHandle()), default, typeof(IComDataObject).GUID, out IComDataObject dataObj).ThrowIfFailed(); + OleSetClipboard(dataObj).ThrowIfFailed(); + //DataObject = dataObj = shellItems is ShellItemArray shia ? shia.ToDataObject() : new ShellItemArray(shellItems).ToDataObject(); + //if (!setAllFormats) return; + //var files = shellItems.Where(i => i.IsFileSystem).Select(i => i.FileSystemPath).ToArray(); + //if (files.Length == 0) return; + //dataObj.SetData(CLIPFORMAT.CF_HDROP, files); + //dataObj.SetData(RegisterFormat(ShellClipboardFormat.CFSTR_FILENAMEA), files[0]); + //dataObj.SetData(RegisterFormat(ShellClipboardFormat.CFSTR_FILENAMEW), files[0]); + //dataObj.SetData(RegisterFormat(ShellClipboardFormat.CFSTR_FILEDESCRIPTORA)); + } + /// Obtains data from a source data object. /// The type of the object being retrieved. /// Specifies the particular clipboard format of interest.