mirror of https://github.com/dahall/Vanara.git
Updated moved classes so they do not depend on System.Windows.Forms. There are lots of breaking changes when compared to Vanara.Windows.Shell, mostly around the use of IWin32Window.
parent
34c31238fd
commit
f17ed396f2
|
@ -2,7 +2,6 @@
|
|||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Windows.Forms;
|
||||
using Vanara.InteropServices;
|
||||
using Vanara.PInvoke;
|
||||
using static Vanara.PInvoke.Ole32;
|
||||
|
@ -73,7 +72,7 @@ namespace Vanara.Windows.Shell
|
|||
public class FileInUseHandler : IFileIsInUse, IDisposable
|
||||
{
|
||||
private bool disposedValue;
|
||||
private string filePath;
|
||||
private string appName, filePath;
|
||||
private IMoniker moniker;
|
||||
private uint regId;
|
||||
|
||||
|
@ -81,11 +80,12 @@ namespace Vanara.Windows.Shell
|
|||
/// <param name="filePath">The file path.</param>
|
||||
/// <param name="parent">The parent.</param>
|
||||
/// <param name="usageType">Type of the usage.</param>
|
||||
public FileInUseHandler(string filePath, IWin32Window parent = null, FileUsageType usageType = FileUsageType.Generic)
|
||||
public FileInUseHandler(string filePath, HWND parent = default, FileUsageType usageType = FileUsageType.Generic)
|
||||
{
|
||||
ActivationWindow = parent;
|
||||
FileUsageType = usageType;
|
||||
FilePath = filePath;
|
||||
appName = DefAppName;
|
||||
}
|
||||
|
||||
/// <summary>Finalizes an instance of the <see cref="FileInUseHandler"/> class.</summary>
|
||||
|
@ -109,7 +109,14 @@ namespace Vanara.Windows.Shell
|
|||
/// value is <see langword="null"/>, then the calling application will be told that it cannot activate the file's owning application.
|
||||
/// </summary>
|
||||
/// <value>The activation window.</value>
|
||||
public IWin32Window ActivationWindow { get; set; }
|
||||
public HWND ActivationWindow { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the name of the application using the file.</summary>
|
||||
/// <value>
|
||||
/// The name of the application that can be passed to the user in a dialog box so that the user knows the source of the conflict and
|
||||
/// can act accordingly. For instance "File.txt is in use by Litware.".
|
||||
/// </value>
|
||||
public string AppName { get => appName; set => appName = value; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the full path to the file that is in use by this application. Setting this value will revoke any prior file's
|
||||
|
@ -165,7 +172,7 @@ namespace Vanara.Windows.Shell
|
|||
|
||||
HRESULT IFileIsInUse.GetAppName(out string ppszName)
|
||||
{
|
||||
ppszName = System.Windows.Forms.Application.ProductName;
|
||||
ppszName = appName;
|
||||
return HRESULT.S_OK;
|
||||
}
|
||||
|
||||
|
@ -173,13 +180,13 @@ namespace Vanara.Windows.Shell
|
|||
{
|
||||
var cancelArgs = new CancelEventArgs(false);
|
||||
CloseRequested?.Invoke(this, cancelArgs);
|
||||
pdwCapFlags = (!cancelArgs.Cancel ? OF_CAP.OF_CAP_CANCLOSE : 0) | (ActivationWindow is null ? 0 : OF_CAP.OF_CAP_CANSWITCHTO);
|
||||
pdwCapFlags = (!cancelArgs.Cancel ? OF_CAP.OF_CAP_CANCLOSE : 0) | (ActivationWindow.IsNull ? 0 : OF_CAP.OF_CAP_CANSWITCHTO);
|
||||
return HRESULT.S_OK;
|
||||
}
|
||||
|
||||
HRESULT IFileIsInUse.GetSwitchToHWND(out HWND phwnd)
|
||||
{
|
||||
phwnd = ActivationWindow is null ? default : ActivationWindow.Handle;
|
||||
phwnd = ActivationWindow;
|
||||
return HRESULT.S_OK;
|
||||
}
|
||||
|
||||
|
@ -206,6 +213,22 @@ namespace Vanara.Windows.Shell
|
|||
}
|
||||
}
|
||||
|
||||
private string DefAppName
|
||||
{
|
||||
get
|
||||
{
|
||||
var asm = System.Reflection.Assembly.GetEntryAssembly();
|
||||
if (asm is not null)
|
||||
{
|
||||
object[] attrs = asm.GetCustomAttributes(typeof(System.Reflection.AssemblyProductAttribute), false);
|
||||
if (attrs != null && attrs.Length > 0)
|
||||
return ((System.Reflection.AssemblyProductAttribute)attrs[0]).Product;
|
||||
return System.IO.Path.GetFileNameWithoutExtension(asm.Location);
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterInROT()
|
||||
{
|
||||
GetRunningObjectTable(0, out var rot).ThrowIfFailed();
|
||||
|
|
|
@ -3,13 +3,13 @@ using System.Collections.Generic;
|
|||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using Vanara.Extensions;
|
||||
using Vanara.InteropServices;
|
||||
using Vanara.PInvoke;
|
||||
|
@ -20,6 +20,25 @@ using IComDataObject = System.Runtime.InteropServices.ComTypes.IDataObject;
|
|||
|
||||
namespace Vanara.Windows.Shell
|
||||
{
|
||||
/// <summary>Specifies the text data formats that can be used to query, get and set text data format with Clipboard.</summary>
|
||||
public enum TextDataFormat
|
||||
{
|
||||
/// <summary>Specifies the standard ANSI text format.</summary>
|
||||
Text,
|
||||
|
||||
/// <summary>Specifies the standard Windows Unicode text format.</summary>
|
||||
UnicodeText,
|
||||
|
||||
/// <summary>Specifies text consisting of Rich Text Format (RTF) data.</summary>
|
||||
Rtf,
|
||||
|
||||
/// <summary>Specifies text consisting of HTML data.</summary>
|
||||
Html,
|
||||
|
||||
/// <summary>Specifies a comma-separated value (CSV) format, which is a common interchange format used by spreadsheets.</summary>
|
||||
CommaSeparatedValue,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes and closes a session using the Clipboard calling <see cref="OpenClipboard"/> and then <see cref="CloseClipboard"/> on
|
||||
/// disposal. This can be called multiple times in nested calls and will ensure the Clipboard is only opened and closed at the highest scope.
|
||||
|
@ -27,13 +46,16 @@ namespace Vanara.Windows.Shell
|
|||
/// <seealso cref="System.IDisposable"/>
|
||||
public class NativeClipboard : IDisposable
|
||||
{
|
||||
private readonly bool dontClose = false;
|
||||
private static readonly object objectLock = new();
|
||||
private static int HdrLen = 0;
|
||||
private static Dictionary<uint, string> knownIds;
|
||||
private static ListenerWindow listener;
|
||||
|
||||
[ThreadStatic]
|
||||
private static bool open = false;
|
||||
|
||||
private readonly bool dontClose = false;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="NativeClipboard"/> class.</summary>
|
||||
/// <param name="empty">If set to <see langword="true"/>, <see cref="EmptyClipboard"/> is called to clear the Clipboard.</param>
|
||||
/// <param name="hWndNewOwner">
|
||||
|
@ -80,17 +102,32 @@ namespace Vanara.Windows.Shell
|
|||
|
||||
/// <summary>Retrieves the currently supported clipboard formats.</summary>
|
||||
/// <value>A sequence of the currently supported formats.</value>
|
||||
public static IEnumerable<DataFormats.Format> CurrentlySupportedFormats
|
||||
public static IEnumerable<uint> CurrentlySupportedFormats
|
||||
{
|
||||
get
|
||||
{
|
||||
GetUpdatedClipboardFormats(null, 0, out var cnt);
|
||||
var fmts = new uint[cnt];
|
||||
Win32Error.ThrowLastErrorIfFalse(GetUpdatedClipboardFormats(fmts, (uint)fmts.Length, out cnt));
|
||||
return fmts.Take((int)cnt).Select(u => DataFormats.GetFormat(unchecked((int)u))).ToArray();
|
||||
return fmts.Take((int)cnt).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets a <see cref="IComDataObject"/> instance from the Windows Clipboard.</summary>
|
||||
/// <value>A <see cref="IComDataObject"/> instance.</value>
|
||||
public static IComDataObject DataObject
|
||||
{
|
||||
get
|
||||
{
|
||||
OleGetClipboard(out var idata).ThrowIfFailed();
|
||||
return idata;
|
||||
}
|
||||
set => OleSetClipboard(value).ThrowIfFailed();
|
||||
}
|
||||
|
||||
/// <summary>Carries out the clipboard shutdown sequence. It also releases any IDataObject instances that were placed on the clipboard.</summary>
|
||||
public static void Flush() => OleFlushClipboard().ThrowIfFailed();
|
||||
|
||||
/// <summary>Retrieves the window handle of the current owner of the clipboard.</summary>
|
||||
/// <returns>
|
||||
/// <para>If the function succeeds, the return value is the handle to the window that owns the clipboard.</para>
|
||||
|
@ -100,7 +137,7 @@ namespace Vanara.Windows.Shell
|
|||
/// <para>The clipboard can still contain data even if the clipboard is not currently owned.</para>
|
||||
/// <para>In general, the clipboard owner is the window that last placed data in clipboard.</para>
|
||||
/// </remarks>
|
||||
public static IntPtr GetClipboardOwner() => (IntPtr)User32.GetClipboardOwner();
|
||||
public static HWND GetClipboardOwner() => User32.GetClipboardOwner();
|
||||
|
||||
/// <summary>Retrieves the first available clipboard format in the specified list.</summary>
|
||||
/// <param name="idList">The clipboard formats, in priority order.</param>
|
||||
|
@ -111,6 +148,32 @@ namespace Vanara.Windows.Shell
|
|||
/// </returns>
|
||||
public static int GetFirstFormatAvailable(params int[] idList) => GetPriorityClipboardFormat(Array.ConvertAll(idList, i => (uint)i), idList.Length);
|
||||
|
||||
/// <summary>Retrieves from the clipboard the name of the specified registered format.</summary>
|
||||
/// <param name="formatId">The type of format to be retrieved.</param>
|
||||
/// <returns>The format name.</returns>
|
||||
public static string GetFormatName(uint formatId)
|
||||
{
|
||||
EnsureKnownIds();
|
||||
if (knownIds.TryGetValue(formatId, out var value))
|
||||
return value;
|
||||
|
||||
// Ask sysetm for the registered name
|
||||
StringBuilder sb = new(80);
|
||||
int ret;
|
||||
while (0 != (ret = GetClipboardFormatName(formatId, sb, sb.Capacity)))
|
||||
{
|
||||
if (ret < sb.Capacity - 1)
|
||||
{
|
||||
knownIds.Add(formatId, sb.ToString());
|
||||
return sb.ToString();
|
||||
}
|
||||
sb.Capacity *= 2;
|
||||
}
|
||||
|
||||
// Failing all elsewhere, return value as hex string
|
||||
return string.Format(CultureInfo.InvariantCulture, "0x{0:X4}", formatId);
|
||||
}
|
||||
|
||||
/// <summary>Retrieves the handle to the window that currently has the clipboard open.</summary>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is the handle to the window that has the clipboard open. If no window has the
|
||||
|
@ -120,17 +183,42 @@ namespace Vanara.Windows.Shell
|
|||
/// If an application or DLL specifies a <c>NULL</c> window handle when calling the OpenClipboard function, the clipboard is opened
|
||||
/// but is not associated with a window. In such a case, <c>GetOpenClipboardWindow</c> returns <c>IntPtr.Zero</c>.
|
||||
/// </remarks>
|
||||
public static IntPtr GetOpenClipboardWindow() => (IntPtr)User32.GetOpenClipboardWindow();
|
||||
public static HWND GetOpenClipboardWindow() => User32.GetOpenClipboardWindow();
|
||||
|
||||
/// <summary>Determines whether the clipboard contains data in the specified format.</summary>
|
||||
/// <param name="format">The name of a standard or registered clipboard format.</param>
|
||||
/// <returns>If the clipboard format is available, the return value is <see langword="true"/>; otherwise <see langword="false"/>.</returns>
|
||||
public static bool IsFormatAvailable(string format) => IsClipboardFormatAvailable((uint)DataFormats.GetFormat(format).Id);
|
||||
/// <summary>Determines whether the data object pointer previously placed on the clipboard is still on the clipboard.</summary>
|
||||
/// <param name="dataObject">
|
||||
/// The IDataObject interface on the data object containing clipboard data of interest, which the caller previously placed on the clipboard.
|
||||
/// </param>
|
||||
/// <returns><see langword="true"/> on success; otherwise, <see langword="false"/>.</returns>
|
||||
public static bool IsCurrentDataObject(IComDataObject dataObject) => OleIsCurrentClipboard(dataObject) == HRESULT.S_OK;
|
||||
|
||||
/// <summary>Determines whether the clipboard contains data in the specified format.</summary>
|
||||
/// <param name="id">A standard or registered clipboard format.</param>
|
||||
/// <returns>If the clipboard format is available, the return value is <see langword="true"/>; otherwise <see langword="false"/>.</returns>
|
||||
public static bool IsFormatAvailable(int id) => IsClipboardFormatAvailable((uint)id);
|
||||
public static bool IsFormatAvailable(uint id) => IsClipboardFormatAvailable(id);
|
||||
|
||||
/// <summary>Registers a new clipboard format. This format can then be used as a valid clipboard format.</summary>
|
||||
/// <param name="format">The name of the new format.</param>
|
||||
/// <returns>The registered clipboard format identifier.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">format</exception>
|
||||
/// <remarks>
|
||||
/// If a registered format with the specified name already exists, a new format is not registered and the return value identifies the
|
||||
/// existing format. This enables more than one application to copy and paste data using the same registered clipboard format. Note
|
||||
/// that the format name comparison is case-insensitive.
|
||||
/// </remarks>
|
||||
public static uint RegisterFormat(string format)
|
||||
{
|
||||
if (format is null) throw new ArgumentNullException(nameof(format));
|
||||
|
||||
EnsureKnownIds();
|
||||
var id = knownIds.FirstOrDefault(p => p.Value == format).Key;
|
||||
if (id != 0)
|
||||
return id;
|
||||
|
||||
id = Win32Error.ThrowLastErrorIf(RegisterClipboardFormat(format), v => v == 0);
|
||||
knownIds.Add(id, format);
|
||||
return id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves data from the clipboard in a specified format. The clipboard must have been opened previously and this pointer cannot
|
||||
|
@ -153,38 +241,11 @@ namespace Vanara.Windows.Shell
|
|||
/// <para>
|
||||
/// The system performs implicit data format conversions between certain clipboard formats when an application calls the
|
||||
/// <c>GetClipboardData</c> function. For example, if the CF_OEMTEXT format is on the clipboard, a window can retrieve data in the
|
||||
/// CF_TEXT format. The format on the clipboard is converted to the requested format on demand. For more information, see
|
||||
/// Synthesized Clipboard Formats.
|
||||
/// CF_TEXT format. The format on the clipboard is converted to the requested format on demand. For more information, see Synthesized
|
||||
/// Clipboard Formats.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public IntPtr DanagerousGetData(int formatId) => GetClipboardData((uint)formatId);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves data from the clipboard in a specified format. The clipboard must have been opened previously and this pointer cannot
|
||||
/// be used once <see cref="NativeClipboard"/> goes out of scope.
|
||||
/// </summary>
|
||||
/// <param name="format">A clipboard format. For a description of the standard clipboard formats, see Standard Clipboard Formats.</param>
|
||||
/// <returns>
|
||||
/// <para>If the function succeeds, the return value is the handle to a clipboard object in the specified format.</para>
|
||||
/// <para>If the function fails, the return value is <c>IntPtr.Zero</c>. To get extended error information, call GetLastError.</para>
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <para><c>Caution</c> Clipboard data is not trusted. Parse the data carefully before using it in your application.</para>
|
||||
/// <para>An application can enumerate the available formats in advance by using the EnumClipboardFormats function.</para>
|
||||
/// <para>
|
||||
/// The clipboard controls the handle that the <c>GetClipboardData</c> function returns, not the application. The application should
|
||||
/// copy the data immediately. The application must not free the handle nor leave it locked. The application must not use the handle
|
||||
/// after the <see cref="Empty"/> method is called, after <see cref="NativeClipboard"/> is disposed, or after any of the
|
||||
/// <c>Set...</c> methods are called with the same clipboard format.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The system performs implicit data format conversions between certain clipboard formats when an application calls the
|
||||
/// <c>GetClipboardData</c> function. For example, if the CF_OEMTEXT format is on the clipboard, a window can retrieve data in the
|
||||
/// CF_TEXT format. The format on the clipboard is converted to the requested format on demand. For more information, see
|
||||
/// Synthesized Clipboard Formats.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public IntPtr DanagerousGetData(string format) => GetClipboardData((uint)DataFormats.GetFormat(format).Id);
|
||||
public IntPtr DanagerousGetData(uint formatId) => GetClipboardData(formatId);
|
||||
|
||||
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
|
||||
public void Dispose()
|
||||
|
@ -214,39 +275,26 @@ namespace Vanara.Windows.Shell
|
|||
/// enumerates the specified format, then enumerates the formats to which it can be converted.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public IEnumerable<DataFormats.Format> EnumAvailableFormats() => EnumClipboardFormats().Select(i => DataFormats.GetFormat((int)i));
|
||||
|
||||
/// <summary>Gets a <see cref="ShellDataObject"/> instance from the Windows Clipboard.</summary>
|
||||
/// <returns>A <see cref="ShellDataObject"/> instance from the Windows Clipboard.</returns>
|
||||
public ShellDataObject GetShellDataObject() => new ShellDataObject(Clipboard.GetDataObject());
|
||||
public IEnumerable<uint> EnumAvailableFormats() => EnumClipboardFormats();
|
||||
|
||||
/// <summary>Gets the text from the native Clipboard in the specified format.</summary>
|
||||
/// <param name="format">The format.</param>
|
||||
/// <param name="formatId">A clipboard format. For a description of the standard clipboard formats, see Standard Clipboard Formats.</param>
|
||||
/// <returns>The string value or <see langword="null"/> if the format is not available.</returns>
|
||||
public string GetText(TextDataFormat format)
|
||||
public string GetText(TextDataFormat formatId) => formatId switch
|
||||
{
|
||||
return format switch
|
||||
{
|
||||
TextDataFormat.Text => StringHelper.GetString(GetClipboardData(CLIPFORMAT.CF_TEXT), CharSet.Ansi),
|
||||
TextDataFormat.UnicodeText => StringHelper.GetString(GetClipboardData(CLIPFORMAT.CF_UNICODETEXT), CharSet.Unicode),
|
||||
TextDataFormat.Rtf => StringHelper.GetString(DanagerousGetData(DataFormats.Rtf), CharSet.Ansi),
|
||||
TextDataFormat.Html => GetHtml(DanagerousGetData(DataFormats.Html)),
|
||||
TextDataFormat.CommaSeparatedValue => StringHelper.GetString(DanagerousGetData(DataFormats.CommaSeparatedValue), CharSet.Ansi),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>Places data on the clipboard in a specified clipboard format.</summary>
|
||||
/// <param name="format">The clipboard format. This parameter can be a registered format or any of the standard clipboard formats.</param>
|
||||
/// <param name="data">The binary data in the specified format.</param>
|
||||
/// <exception cref="System.ArgumentNullException">data</exception>
|
||||
public void SetBinaryData(string format, byte[] data) => SetBinaryData(DataFormats.GetFormat(format).Id, data);
|
||||
TextDataFormat.Text => StringHelper.GetString(GetClipboardData(CLIPFORMAT.CF_TEXT), CharSet.Ansi),
|
||||
TextDataFormat.UnicodeText => StringHelper.GetString(GetClipboardData(CLIPFORMAT.CF_UNICODETEXT), CharSet.Unicode),
|
||||
TextDataFormat.Rtf => StringHelper.GetString(DanagerousGetData(RegisterFormat(ShellClipboardFormat.CF_RTF)), CharSet.Ansi),
|
||||
TextDataFormat.Html => GetHtml(DanagerousGetData(RegisterFormat(ShellClipboardFormat.CF_HTML))),
|
||||
TextDataFormat.CommaSeparatedValue => StringHelper.GetString(DanagerousGetData(RegisterFormat(ShellClipboardFormat.CF_CSV)), CharSet.Ansi),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
/// <summary>Places data on the clipboard in a specified clipboard format.</summary>
|
||||
/// <param name="formatId">The clipboard format. This parameter can be a registered format or any of the standard clipboard formats.</param>
|
||||
/// <param name="data">The binary data in the specified format.</param>
|
||||
/// <exception cref="System.ArgumentNullException">data</exception>
|
||||
public void SetBinaryData(int formatId, byte[] data)
|
||||
public void SetBinaryData(uint formatId, byte[] data)
|
||||
{
|
||||
using var pMem = new SafeMoveableHGlobalHandle(data);
|
||||
Win32Error.ThrowLastErrorIfInvalid(pMem);
|
||||
|
@ -256,7 +304,7 @@ namespace Vanara.Windows.Shell
|
|||
/// <summary>Places data on the clipboard in a specified clipboard format.</summary>
|
||||
/// <param name="formatId">The clipboard format. This parameter can be a registered format or any of the standard clipboard formats.</param>
|
||||
/// <param name="data">The data in the format dictated by <paramref name="formatId"/>.</param>
|
||||
public void SetData<T>(int formatId, T data)
|
||||
public void SetData<T>(uint formatId, T data)
|
||||
{
|
||||
using var pMem = SafeMoveableHGlobalHandle.CreateFromStructure(data);
|
||||
Win32Error.ThrowLastErrorIfInvalid(pMem);
|
||||
|
@ -266,7 +314,7 @@ namespace Vanara.Windows.Shell
|
|||
/// <summary>Places data on the clipboard in a specified clipboard format.</summary>
|
||||
/// <param name="formatId">The clipboard format. This parameter can be a registered format or any of the standard clipboard formats.</param>
|
||||
/// <param name="values">The data in the format dictated by <paramref name="formatId"/>.</param>
|
||||
public void SetData<T>(int formatId, IEnumerable<T> values) where T : struct
|
||||
public void SetData<T>(uint formatId, IEnumerable<T> values) where T : struct
|
||||
{
|
||||
using var pMem = SafeMoveableHGlobalHandle.CreateFromList(values);
|
||||
Win32Error.ThrowLastErrorIfInvalid(pMem);
|
||||
|
@ -278,7 +326,7 @@ namespace Vanara.Windows.Shell
|
|||
/// <param name="values">The list of strings.</param>
|
||||
/// <param name="packing">The packing type for the strings.</param>
|
||||
/// <param name="charSet">The character set to use for the strings.</param>
|
||||
public void SetData(int formatId, IEnumerable<string> values, StringListPackMethod packing = StringListPackMethod.Concatenated, CharSet charSet = CharSet.Auto)
|
||||
public void SetData(uint formatId, IEnumerable<string> values, StringListPackMethod packing = StringListPackMethod.Concatenated, CharSet charSet = CharSet.Auto)
|
||||
{
|
||||
using var pMem = SafeMoveableHGlobalHandle.CreateFromStringList(values, packing, charSet);
|
||||
Win32Error.ThrowLastErrorIfInvalid(pMem);
|
||||
|
@ -294,7 +342,7 @@ namespace Vanara.Windows.Shell
|
|||
if (text is null && htmlText is null && rtfText is null) return;
|
||||
SetText(text, TextDataFormat.Text);
|
||||
SetText(text, TextDataFormat.UnicodeText);
|
||||
SetBinaryData(DataFormats.Locale, BitConverter.GetBytes(CultureInfo.CurrentCulture.LCID));
|
||||
SetBinaryData(RegisterFormat("Locale"), BitConverter.GetBytes(CultureInfo.CurrentCulture.LCID));
|
||||
if (htmlText != null) SetText(htmlText, TextDataFormat.Html);
|
||||
if (rtfText != null) SetText(rtfText, TextDataFormat.Rtf);
|
||||
}
|
||||
|
@ -304,13 +352,13 @@ namespace Vanara.Windows.Shell
|
|||
/// <param name="format">The clipboard text format to set.</param>
|
||||
public void SetText(string value, TextDataFormat format)
|
||||
{
|
||||
(byte[] bytes, int fmt) = format switch
|
||||
(byte[] bytes, uint fmt) = format switch
|
||||
{
|
||||
TextDataFormat.Text => (Encoding.ASCII.GetBytes(value + '\0'), (int)CLIPFORMAT.CF_TEXT),
|
||||
TextDataFormat.UnicodeText => (Encoding.Unicode.GetBytes(value + '\0'), (int)CLIPFORMAT.CF_UNICODETEXT),
|
||||
TextDataFormat.Rtf => (Encoding.ASCII.GetBytes(value + '\0'), DataFormats.GetFormat(DataFormats.Rtf).Id),
|
||||
TextDataFormat.Html => (MakeClipHtml(value), DataFormats.GetFormat(DataFormats.Html).Id),
|
||||
TextDataFormat.CommaSeparatedValue => (Encoding.ASCII.GetBytes(value + '\0'), DataFormats.GetFormat(DataFormats.CommaSeparatedValue).Id),
|
||||
TextDataFormat.Text => (Encoding.ASCII.GetBytes(value + '\0'), (uint)CLIPFORMAT.CF_TEXT),
|
||||
TextDataFormat.UnicodeText => (Encoding.Unicode.GetBytes(value + '\0'), (uint)CLIPFORMAT.CF_UNICODETEXT),
|
||||
TextDataFormat.Rtf => (Encoding.ASCII.GetBytes(value + '\0'), RegisterFormat(ShellClipboardFormat.CF_RTF)),
|
||||
TextDataFormat.Html => (MakeClipHtml(value), RegisterFormat(ShellClipboardFormat.CF_HTML)),
|
||||
TextDataFormat.CommaSeparatedValue => (Encoding.ASCII.GetBytes(value + '\0'), RegisterFormat(ShellClipboardFormat.CF_CSV)),
|
||||
_ => default,
|
||||
};
|
||||
SetBinaryData(fmt, bytes);
|
||||
|
@ -325,34 +373,8 @@ namespace Vanara.Windows.Shell
|
|||
if (url is null) throw new ArgumentNullException(nameof(url));
|
||||
SetText(url, $"<a href=\"{url}\">{title ?? url}</a>", null);
|
||||
var textUrl = url + (title is null ? "" : ('\n' + title)) + '\0';
|
||||
SetBinaryData(ShellClipboardFormat.CFSTR_INETURLA, Encoding.ASCII.GetBytes(textUrl));
|
||||
SetBinaryData(ShellClipboardFormat.CFSTR_INETURLW, Encoding.Unicode.GetBytes(textUrl));
|
||||
}
|
||||
|
||||
internal static StringCollection ToSC(IEnumerable<string> e)
|
||||
{
|
||||
var sc = new StringCollection();
|
||||
if (e != null)
|
||||
sc.AddRange(e.ToArray());
|
||||
return sc;
|
||||
}
|
||||
|
||||
private static T GetComData<T>(DataObject dobj, string fmt, Func<IntPtr, T> convert, T defValue = default)
|
||||
{
|
||||
T ret = defValue;
|
||||
if (dobj is IComDataObject cdo)
|
||||
{
|
||||
var fc = new FORMATETC { cfFormat = (short)DataFormats.GetFormat(fmt).Id, dwAspect = DVASPECT.DVASPECT_CONTENT, lindex = -1, tymed = TYMED.TYMED_HGLOBAL };
|
||||
try
|
||||
{
|
||||
cdo.GetData(ref fc, out var medium);
|
||||
if (medium.unionmember != default)
|
||||
ret = convert(medium.unionmember);
|
||||
ReleaseStgMedium(medium);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
return ret;
|
||||
SetBinaryData(RegisterFormat(ShellClipboardFormat.CFSTR_INETURLA), Encoding.ASCII.GetBytes(textUrl));
|
||||
SetBinaryData(RegisterFormat(ShellClipboardFormat.CFSTR_INETURLW), Encoding.Unicode.GetBytes(textUrl));
|
||||
}
|
||||
|
||||
internal static string GetHtml(IntPtr ptr)
|
||||
|
@ -383,6 +405,37 @@ namespace Vanara.Windows.Shell
|
|||
return Encoding.UTF8.GetString(bytes, startFrag, endFrag - startFrag);
|
||||
}
|
||||
|
||||
internal static StringCollection ToSC(IEnumerable<string> e)
|
||||
{
|
||||
var sc = new StringCollection();
|
||||
if (e != null)
|
||||
sc.AddRange(e.ToArray());
|
||||
return sc;
|
||||
}
|
||||
|
||||
private static void EnsureKnownIds()
|
||||
{
|
||||
if (knownIds is not null)
|
||||
return;
|
||||
var type = typeof(CLIPFORMAT);
|
||||
knownIds = type.GetFields(BindingFlags.Static | BindingFlags.Public).Where(f => f.FieldType == type && f.IsInitOnly).ToDictionary(f => (uint)f.GetValue(null), f => f.Name);
|
||||
}
|
||||
|
||||
private static T GetComData<T>(IComDataObject cdo, uint fmt, Func<IntPtr, T> convert, T defValue = default)
|
||||
{
|
||||
T ret = defValue;
|
||||
var fc = new FORMATETC { cfFormat = (short)fmt, dwAspect = DVASPECT.DVASPECT_CONTENT, lindex = -1, tymed = TYMED.TYMED_HGLOBAL };
|
||||
try
|
||||
{
|
||||
cdo.GetData(ref fc, out var medium);
|
||||
if (medium.unionmember != default)
|
||||
ret = convert(medium.unionmember);
|
||||
ReleaseStgMedium(medium);
|
||||
}
|
||||
catch { }
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static byte[] MakeClipHtml(string value)
|
||||
{
|
||||
const string Header = "Version:0.9\r\nStartHTML:{0:0000000000}\r\nEndHTML:{1:0000000000}\r\nStartFragment:{2:0000000000}\r\nEndFragment:{3:0000000000}\r\nStartSelection:{4:0000000000}\r\nEndSelection:{5:0000000000}\r\n";
|
||||
|
@ -449,60 +502,28 @@ namespace Vanara.Windows.Shell
|
|||
thread.Join();
|
||||
}
|
||||
|
||||
/*private class ListenerWindow : BasicMessageWindow //SystemEventHandler
|
||||
private class ListenerWindow : SystemEventHandler
|
||||
{
|
||||
public ListenerWindow() : base(MessageFilterProc)
|
||||
{
|
||||
Win32Error.ThrowLastErrorIfFalse(AddClipboardFormatListener(Handle));
|
||||
}
|
||||
|
||||
//protected override void OnMessageWindowHandleCreated()
|
||||
//{
|
||||
// Win32Error.ThrowLastErrorIfFalse(AddClipboardFormatListener(MessageWindowHandle));
|
||||
// base.OnMessageWindowHandleCreated();
|
||||
//}
|
||||
|
||||
//protected override
|
||||
static bool MessageFilterProc(HWND hwnd, uint msg, IntPtr wParam, IntPtr lParam, out IntPtr lReturn)
|
||||
protected override bool MessageFilter(HWND hwnd, uint msg, IntPtr wParam, IntPtr lParam, out IntPtr lReturn)
|
||||
{
|
||||
lReturn = default;
|
||||
switch (msg)
|
||||
{
|
||||
case (uint)ClipboardNotificationMessage.WM_CLIPBOARDUPDATE:
|
||||
InternalClipboardUpdate?.Invoke(null, EventArgs.Empty);
|
||||
return true;
|
||||
case (uint)WindowMessage.WM_DESTROY:
|
||||
RemoveClipboardFormatListener(hwnd);
|
||||
RemoveClipboardFormatListener(MessageWindowHandle);
|
||||
break;
|
||||
|
||||
case (uint)ClipboardNotificationMessage.WM_CLIPBOARDUPDATE:
|
||||
InternalClipboardUpdate?.Invoke(this, EventArgs.Empty);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
|
||||
private class ListenerWindow : NativeWindow, IDisposable
|
||||
{
|
||||
public ListenerWindow()
|
||||
protected override void OnMessageWindowHandleCreated()
|
||||
{
|
||||
var cp = new CreateParams { Style = 0, ExStyle = 0, ClassStyle = 0, Parent = IntPtr.Zero, Caption = GetType().Name };
|
||||
CreateHandle(cp);
|
||||
AddClipboardFormatListener(Handle);
|
||||
}
|
||||
|
||||
void IDisposable.Dispose() => base.DestroyHandle();
|
||||
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
switch (m.Msg)
|
||||
{
|
||||
case (int)WindowMessage.WM_DESTROY:
|
||||
RemoveClipboardFormatListener(Handle);
|
||||
break;
|
||||
|
||||
case (int)ClipboardNotificationMessage.WM_CLIPBOARDUPDATE:
|
||||
InternalClipboardUpdate?.Invoke(this, EventArgs.Empty);
|
||||
break;
|
||||
}
|
||||
base.WndProc(ref m);
|
||||
base.OnMessageWindowHandleCreated();
|
||||
AddClipboardFormatListener(MessageWindowHandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -309,11 +309,11 @@ namespace Vanara.Windows.Shell
|
|||
|
||||
if (items.Length == 1)
|
||||
{
|
||||
ComInterface.Invoke(new ShellDataObject(items)).ThrowIfFailed();
|
||||
ComInterface.Invoke(items[0].DataObject).ThrowIfFailed();
|
||||
}
|
||||
else
|
||||
{
|
||||
ComInterface.CreateInvoker(new ShellDataObject(items), out var invoker).ThrowIfFailed();
|
||||
ComInterface.CreateInvoker(CreateDataObj(items), out var invoker).ThrowIfFailed();
|
||||
using var pInvoker = ComReleaserFactory.Create(invoker);
|
||||
var hr = invoker.SupportsSelection();
|
||||
if (hr == HRESULT.S_FALSE)
|
||||
|
@ -328,6 +328,16 @@ namespace Vanara.Windows.Shell
|
|||
/// <para>A string that contains the display name of the application.</para>
|
||||
/// </param>
|
||||
public void MakeDefault(string description) => ComInterface.MakeDefault(description).ThrowIfFailed();
|
||||
|
||||
private static System.Runtime.InteropServices.ComTypes.IDataObject CreateDataObj(IEnumerable<ShellItem> items)
|
||||
{
|
||||
if ((items?.Count() ?? 0) == 0)
|
||||
throw new ArgumentNullException(nameof(items));
|
||||
|
||||
if (items is not ShellItemArray litems)
|
||||
litems = new ShellItemArray(items);
|
||||
return litems.ToDataObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,8 +29,8 @@ namespace Vanara.Windows.Shell
|
|||
|
||||
/// <summary>Gets the CLSID for the specified type.</summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>The CLSID value for the type. Calls <see cref="Marshal.GenerateGuidForType"/> to get the value.</returns>
|
||||
public static Guid CLSID(this Type type) => Marshal.GenerateGuidForType(type);
|
||||
/// <returns>The CLSID value for the type. Calls <see cref="Type.GUID"/> to get the value.</returns>
|
||||
public static Guid CLSID(this Type type) => type.GUID;
|
||||
|
||||
/// <summary>Determines if the specified type is registered as a COM Local Server.</summary>
|
||||
/// <typeparam name="TComObject">The type of the COM object.</typeparam>
|
||||
|
@ -58,7 +58,7 @@ namespace Vanara.Windows.Shell
|
|||
return true;
|
||||
}
|
||||
|
||||
#if !(NETCOREAPP3_0 || NETCOREAPP3_1 || NET5_0_OR_GREATER)
|
||||
#if NETFRAMEWORK
|
||||
|
||||
/// <summary>Registers the specified type as a COM Local Server.</summary>
|
||||
/// <typeparam name="TComObject">The type of the COM object.</typeparam>
|
||||
|
|
|
@ -240,46 +240,4 @@ namespace Vanara.Windows.Shell
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
internal static class TaskAgg
|
||||
{
|
||||
public static Task CompletedTask
|
||||
{
|
||||
get
|
||||
{
|
||||
#if NET20 || NET35 || NET40 || NET45
|
||||
return TaskExEx.CompletedTask;
|
||||
#else
|
||||
return Task.CompletedTask;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static Task Run(Action action, CancellationToken cancellationToken)
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
return TaskEx.Run(action, cancellationToken);
|
||||
#else
|
||||
return Task.Run(action, cancellationToken);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Task<T> Run<T>(Func<T> action, CancellationToken cancellationToken)
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
return TaskEx.Run(action, cancellationToken);
|
||||
#else
|
||||
return Task.Run(action, cancellationToken);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Task WhenAll(IEnumerable<Task> tasks)
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
return TaskEx.WhenAll(tasks);
|
||||
#else
|
||||
return Task.WhenAll(tasks);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Vanara.Windows.Shell
|
||||
{
|
||||
internal static class TaskAgg
|
||||
{
|
||||
public static Task CompletedTask
|
||||
{
|
||||
get
|
||||
{
|
||||
#if NET20 || NET35 || NET40 || NET45
|
||||
return TaskExEx.CompletedTask;
|
||||
#else
|
||||
return Task.CompletedTask;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static Task Run(Action action, CancellationToken cancellationToken)
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
return TaskEx.Run(action, cancellationToken);
|
||||
#else
|
||||
return Task.Run(action, cancellationToken);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Task<T> Run<T>(Func<T> action, CancellationToken cancellationToken)
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
return TaskEx.Run(action, cancellationToken);
|
||||
#else
|
||||
return Task.Run(action, cancellationToken);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Task WhenAll(IEnumerable<Task> tasks)
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
return TaskEx.WhenAll(tasks);
|
||||
#else
|
||||
return Task.WhenAll(tasks);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,7 +40,6 @@ namespace Vanara.Windows.Shell
|
|||
/// need to implement your own interfaces. The IClassFactory implementation can get any derived interfaces through casting for calls to
|
||||
/// its QueryInterface method. If you want more control, override the QueryInterface method in this class.
|
||||
/// </summary>
|
||||
/// <remarks>See <see cref="ShellDropTarget"/> for an example of how to use this class to create a local COM server.</remarks>
|
||||
/// <seealso cref="IDisposable"/>
|
||||
/// <seealso cref="IObjectWithSite"/>
|
||||
public abstract class ComObject : IComObject, IDisposable, IObjectWithSite
|
||||
|
|
|
@ -141,7 +141,7 @@ namespace Vanara.Windows.Shell
|
|||
|
||||
/// <summary>Gets the shell item attributes.</summary>
|
||||
/// <value>The shell item attributes.</value>
|
||||
public ShellItemAttribute ShellAttributes { get; private set; }
|
||||
public SFGAO ShellAttributes { get; private set; }
|
||||
|
||||
/// <summary>Gets the small icon for the file.</summary>
|
||||
public Icon SmallIcon => GetIcon(ShellIconType.Small);
|
||||
|
@ -178,7 +178,7 @@ namespace Vanara.Windows.Shell
|
|||
var ret = SHGetFileInfo(FullPath, 0, ref shfi, SHFILEINFO.Size, SHGFI.SHGFI_DISPLAYNAME | SHGFI.SHGFI_TYPENAME | SHGFI.SHGFI_ATTRIBUTES);
|
||||
if (ret != IntPtr.Zero)
|
||||
{
|
||||
ShellAttributes = (ShellItemAttribute)shfi.dwAttributes;
|
||||
ShellAttributes = (SFGAO)shfi.dwAttributes;
|
||||
TypeName = shfi.szTypeName.Clone().ToString();
|
||||
DisplayName = shfi.szDisplayName.Clone().ToString();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using Vanara.PInvoke;
|
||||
using static Vanara.PInvoke.Shell32;
|
||||
|
||||
namespace Vanara.Windows.Shell
|
||||
|
@ -287,11 +287,10 @@ namespace Vanara.Windows.Shell
|
|||
/// <param name="owner">
|
||||
/// A value that represents the window of the owner window for the common dialog box. This value can be <see langword="null"/>.
|
||||
/// </param>
|
||||
public void Start(IWin32Window owner)
|
||||
public void Start(HWND owner = default)
|
||||
{
|
||||
if (owner is null) owner = Form.ActiveForm;
|
||||
iProgressDialog = new IOperationsProgressDialog();
|
||||
iProgressDialog.StartProgressDialog(owner?.Handle ?? default, DialogFlags);
|
||||
iProgressDialog.StartProgressDialog(owner, DialogFlags);
|
||||
iProgressDialog.SetOperation((SPACTION)operation);
|
||||
iProgressDialog.SetMode((PDMODE)mode);
|
||||
UpdateLocations();
|
||||
|
|
|
@ -3,7 +3,6 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using Vanara.Collections;
|
||||
using Vanara.InteropServices;
|
||||
using Vanara.PInvoke;
|
||||
|
@ -22,16 +21,16 @@ namespace Vanara.Windows.Shell
|
|||
private bool disposedValue = false;
|
||||
private IFileOperation op;
|
||||
private OperationFlags opFlags = defaultOptions;
|
||||
private IWin32Window owner;
|
||||
private HWND owner;
|
||||
private IFileOperationProgressSink sink;
|
||||
private uint sinkCookie;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="ShellFileOperations"/> class.</summary>
|
||||
/// <param name="owner">The window that owns the modal dialog. This value can be <see langword="null"/>.</param>
|
||||
public ShellFileOperations(IWin32Window owner = null)
|
||||
public ShellFileOperations(HWND owner = default)
|
||||
{
|
||||
op = new IFileOperation();
|
||||
if (owner != null) op.SetOwnerWindow(owner.Handle);
|
||||
if (owner != default) op.SetOwnerWindow(owner);
|
||||
sink = new OpSink(this);
|
||||
sinkCookie = op.Advise(sink);
|
||||
}
|
||||
|
@ -105,10 +104,10 @@ namespace Vanara.Windows.Shell
|
|||
|
||||
/// <summary>Gets or sets the parent or owner window for progress and dialog windows.</summary>
|
||||
/// <value>The owner window of the operation. This window will receive error messages.</value>
|
||||
public IWin32Window OwnerWindow
|
||||
public HWND OwnerWindow
|
||||
{
|
||||
get => owner;
|
||||
set => op.SetOwnerWindow((owner = value)?.Handle ?? default);
|
||||
set => op.SetOwnerWindow(owner = value);
|
||||
}
|
||||
|
||||
/// <summary>Gets the number of queued operations.</summary>
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace Vanara.Windows.Shell
|
|||
public static SafeHICON GetSystemIconHandle(int index, ShellImageSize iconSize = ShellImageSize.Large)
|
||||
{
|
||||
SHGetImageList((SHIL)iconSize, typeof(IImageList).GUID, out var il).ThrowIfFailed();
|
||||
return il.GetIcon(index, IMAGELISTDRAWFLAGS.ILD_TRANSPARENT);
|
||||
return ((IImageList)il).GetIcon(index, IMAGELISTDRAWFLAGS.ILD_TRANSPARENT);
|
||||
}
|
||||
|
||||
/// <summary>Given a pixel size, return the ShellImageSize value with the closest size.</summary>
|
||||
|
|
|
@ -3,8 +3,6 @@ using System.ComponentModel;
|
|||
using System.Drawing.Design;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Forms.Design;
|
||||
using Vanara.Extensions;
|
||||
using Vanara.PInvoke;
|
||||
using static Vanara.PInvoke.User32;
|
||||
|
@ -245,7 +243,7 @@ namespace Vanara.Windows.Shell
|
|||
|
||||
/// <summary>Gets or sets the path of the shell item to watch.</summary>
|
||||
/// <value>The path of the shell item to monitor. The default is <see langword="null"/>.</value>
|
||||
[DefaultValue(null), Category("Data"), Description("The shell item to watch."), Editor(typeof(FileNameEditor), typeof(UITypeEditor))]
|
||||
[DefaultValue(null), Category("Data"), Description("The shell item to watch.")]//, Editor(typeof(FileNameEditor), typeof(UITypeEditor))]
|
||||
public string Path
|
||||
{
|
||||
get => item is null ? null : (item.IsFileSystem ? item.FileSystemPath : item.GetDisplayName(ShellItemDisplayString.DesktopAbsoluteParsing));
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
#if !(NET5_0_OR_GREATER || NETCOREAPP3_1_OR_GREATER)
|
||||
#define HASMENU
|
||||
#endif
|
||||
|
||||
// Credit due to Gong-Shell from which this was largely taken.
|
||||
// Credit due to Gong-Shell from which this was largely taken.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using Vanara.Extensions;
|
||||
using Vanara.InteropServices;
|
||||
using Vanara.PInvoke;
|
||||
|
@ -24,17 +18,15 @@ namespace Vanara.Windows.Shell
|
|||
/// be shown.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// To display a shell context menu in a Form's main menu, call the <c>Populate</c> or <see cref="GetItems"/> methods to populate the
|
||||
/// menu. In addition, you must intercept a number of special messages that will be sent to the menu's parent form. To do this, you
|
||||
/// must override <see cref="Form.WndProc"/> like so:
|
||||
/// To display a shell context menu in a Form's main menu, call the <see cref="GetItems"/> methods to populate the menu. In addition,
|
||||
/// you must intercept a number of special messages that will be sent to the menu's parent form by hooking its message loop as in the
|
||||
/// following WinForms example:
|
||||
/// </para>
|
||||
/// <code>
|
||||
///protected override void WndProc(ref Message m) {
|
||||
///if ((m_ContextMenu == null) || (!m_ContextMenu.HandleMenuMessage(ref m))) {
|
||||
///base.WndProc(ref m);
|
||||
///}
|
||||
///}
|
||||
/// </code>
|
||||
/// <code>protected override void WndProc(ref Message m) {
|
||||
/// if ((m_ContextMenu == null) || (!m_ContextMenu.HandleMenuMessage(ref m))) {
|
||||
/// base.WndProc(ref m);
|
||||
/// }
|
||||
/// }</code>
|
||||
/// <para>Where m_ContextMenu is the <see cref="ShellContextMenu"/> being shown.</para>
|
||||
/// Standard menu commands can also be invoked from this class, for example <see cref="InvokeDelete"/> and <see cref="InvokeRename"/>.
|
||||
/// </remarks>
|
||||
|
@ -317,7 +309,7 @@ namespace Vanara.Windows.Shell
|
|||
return ComInterface.GetCommandString((IntPtr)command, stringType, default, mStr, (uint)mStr.Capacity).Succeeded ? mStr : null;
|
||||
}
|
||||
|
||||
#if HASMENU
|
||||
#if WINFORMS && HASMENU
|
||||
/// <summary>Populates a <see cref="Menu"/> with the context menu items for a shell item.</summary>
|
||||
/// <param name="menu">The menu to populate.</param>
|
||||
/// <param name="menuOptions">The flags to pass to <see cref="IContextMenu.QueryContextMenu"/>.</param>
|
||||
|
|
|
@ -180,9 +180,9 @@ namespace Vanara.Windows.Shell
|
|||
/// <param name="filter">A filter for the types of children to enumerate.</param>
|
||||
/// <param name="parentWindow">The parent window.</param>
|
||||
/// <returns>An enumerated list of children matching the filter.</returns>
|
||||
public IEnumerable<ShellItem> EnumerateChildren(FolderItemFilter filter /*= FolderItemFilter.Folders | FolderItemFilter.IncludeHidden | FolderItemFilter.NonFolders | FolderItemFilter.IncludeSuperHidden */, System.Windows.Forms.IWin32Window parentWindow = null)
|
||||
public IEnumerable<ShellItem> EnumerateChildren(FolderItemFilter filter /*= FolderItemFilter.Folders | FolderItemFilter.IncludeHidden | FolderItemFilter.NonFolders | FolderItemFilter.IncludeSuperHidden */, HWND parentWindow = default)
|
||||
{
|
||||
if (iShellFolder.EnumObjects(IWin2Ptr(parentWindow, false), (SHCONTF)filter, out var eo).Failed)
|
||||
if (iShellFolder.EnumObjects(parentWindow, (SHCONTF)filter, out var eo).Failed)
|
||||
Debug.WriteLine($"Unable to enum children in folder.");
|
||||
foreach (var p in eo.Enumerate(20))
|
||||
{
|
||||
|
@ -198,10 +198,10 @@ namespace Vanara.Windows.Shell
|
|||
/// <param name="parentWindow">The owner window that the client should specify if it displays a dialog box or message box..</param>
|
||||
/// <param name="children">The file objects or subfolders relative to the parent folder for which to get the interface.</param>
|
||||
/// <returns>The interface pointer requested.</returns>
|
||||
public TInterface GetChildrenUIObjects<TInterface>(System.Windows.Forms.IWin32Window parentWindow, params ShellItem[] children) where TInterface : class
|
||||
public TInterface GetChildrenUIObjects<TInterface>(HWND parentWindow, params ShellItem[] children) where TInterface : class
|
||||
{
|
||||
if (children is null || children.Length == 0 || children.Any(i => i is null || !IsChild(i))) throw new ArgumentException("At least one child ShellItem instances is null or is not a child of this folder.");
|
||||
return iShellFolder.GetUIObjectOf<TInterface>(IWin2Ptr(parentWindow), Array.ConvertAll(children, i => (IntPtr)i.PIDL.LastId));
|
||||
return iShellFolder.GetUIObjectOf<TInterface>(parentWindow, Array.ConvertAll(children, i => (IntPtr)i.PIDL.LastId));
|
||||
}
|
||||
|
||||
/// <summary>Returns an enumerator that iterates through the collection.</summary>
|
||||
|
@ -212,8 +212,8 @@ namespace Vanara.Windows.Shell
|
|||
/// <typeparam name="TInterface">The interface to retrieve, typically IShellView.</typeparam>
|
||||
/// <param name="parentWindow">The owner window.</param>
|
||||
/// <returns>The interface pointer requested.</returns>
|
||||
public TInterface GetViewObject<TInterface>(System.Windows.Forms.IWin32Window parentWindow) where TInterface : class =>
|
||||
iShellFolder.CreateViewObject<TInterface>(IWin2Ptr(parentWindow));
|
||||
public TInterface GetViewObject<TInterface>(HWND parentWindow) where TInterface : class =>
|
||||
iShellFolder.CreateViewObject<TInterface>(parentWindow);
|
||||
|
||||
/// <summary>Determines if the supplied <see cref="ShellItem"/> is an immediate descendant of this folder.</summary>
|
||||
/// <param name="item">The child item to test.</param>
|
||||
|
@ -226,9 +226,9 @@ namespace Vanara.Windows.Shell
|
|||
/// <param name="displayType">The display type.</param>
|
||||
/// <param name="parentWindow">The parent window to use if any messages need to be shown the user.</param>
|
||||
/// <returns>A reference to the newly named item.</returns>
|
||||
public ShellItem RenameChild(PIDL relativeChildPidl, string newName, ShellItemDisplayString displayType, System.Windows.Forms.IWin32Window parentWindow)
|
||||
public ShellItem RenameChild(PIDL relativeChildPidl, string newName, ShellItemDisplayString displayType, HWND parentWindow)
|
||||
{
|
||||
iShellFolder.SetNameOf(IWin2Ptr(parentWindow), relativeChildPidl, newName, (SHGDNF)displayType, out PIDL newPidl);
|
||||
iShellFolder.SetNameOf(parentWindow, relativeChildPidl, newName, (SHGDNF)displayType, out PIDL newPidl);
|
||||
return this[newPidl];
|
||||
}
|
||||
|
||||
|
@ -236,8 +236,6 @@ namespace Vanara.Windows.Shell
|
|||
/// <returns>An <see cref="System.Collections.IEnumerator"/> object that can be used to iterate through the collection.</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
internal static HWND IWin2Ptr(System.Windows.Forms.IWin32Window wnd, bool desktopIfNull = true) => wnd?.Handle ?? (desktopIfNull ? User32.FindWindow("Progman", null) : default);
|
||||
|
||||
private IShellFolder GetInstance() => iShellItem.BindToHandler<IShellFolder>(null, BHID.BHID_SFObject.Guid());
|
||||
}
|
||||
}
|
|
@ -463,8 +463,8 @@ namespace Vanara.Windows.Shell
|
|||
/// <value>The context menu.</value>
|
||||
public ShellContextMenu ContextMenu => menu ??= new ShellContextMenu(this);
|
||||
|
||||
/// <summary>Returns a <see cref="System.Windows.Forms.DataObject"/> representing the item. This object is used in drag and drop operations.</summary>
|
||||
public System.Windows.Forms.DataObject DataObject => new(GetHandler<IDataObject>(BHID.BHID_SFUIObject));
|
||||
/// <summary>Returns a <see cref="IDataObject"/> representing the item. This object is used in drag and drop operations.</summary>
|
||||
public IDataObject DataObject => GetHandler<IDataObject>(BHID.BHID_SFUIObject);
|
||||
|
||||
/// <summary>Gets the <see cref="ShellFileInfo"/> corresponding to this instance.</summary>
|
||||
public ShellFileInfo FileInfo => IsFileSystem ? new ShellFileInfo(PIDL) : null;
|
||||
|
@ -734,7 +734,7 @@ namespace Vanara.Windows.Shell
|
|||
if (qi is null)
|
||||
try
|
||||
{
|
||||
qi = (Parent ?? ShellFolder.Desktop).GetChildrenUIObjects<IQueryInfo>(null, this);
|
||||
qi = (Parent ?? ShellFolder.Desktop).GetChildrenUIObjects<IQueryInfo>(default, this);
|
||||
}
|
||||
catch { }
|
||||
if (qi is null) return "";
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
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;
|
||||
|
@ -184,9 +183,9 @@ namespace Vanara.Windows.Shell
|
|||
/// <param name="allowUnindexableLocations">
|
||||
/// if set to <c>true</c> do not display a warning dialog to the user in collisions that concern network locations that cannot be indexed.
|
||||
/// </param>
|
||||
public void ShowLibraryManagementDialog(IWin32Window parentWindow = null, string title = null, string instruction = null, bool allowUnindexableLocations = false)
|
||||
public void ShowLibraryManagementDialog(HWND parentWindow = default, string title = null, string instruction = null, bool allowUnindexableLocations = false)
|
||||
{
|
||||
SHShowManageLibraryUI(iShellItem, parentWindow?.Handle ?? IntPtr.Zero, title, instruction,
|
||||
SHShowManageLibraryUI(iShellItem, parentWindow, title, instruction,
|
||||
allowUnindexableLocations ? LIBRARYMANAGEDIALOGOPTIONS.LMD_ALLOWUNINDEXABLENETWORKLOCATIONS : LIBRARYMANAGEDIALOGOPTIONS.LMD_DEFAULT).ThrowIfFailed();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Permissions;
|
||||
using System.Windows.Forms;
|
||||
using Vanara.Extensions;
|
||||
using Vanara.InteropServices;
|
||||
using Vanara.PInvoke;
|
||||
|
@ -101,8 +98,8 @@ namespace Vanara.Windows.Shell
|
|||
/// <param name="resolveFlags">The resolve flags.</param>
|
||||
/// <param name="timeOut">The time out.</param>
|
||||
/// <exception cref="System.ArgumentNullException">linkFile</exception>
|
||||
public ShellLink(string linkFile, LinkResolution resolveFlags = LinkResolution.NoUI, IWin32Window window = null, TimeSpan timeOut = default) : base(linkFile) =>
|
||||
LoadAndResolve(linkFile, (SLR_FLAGS)resolveFlags, ShellFolder.IWin2Ptr(window), (ushort)timeOut.TotalMilliseconds);
|
||||
public ShellLink(string linkFile, LinkResolution resolveFlags = LinkResolution.NoUI, HWND window = default, TimeSpan timeOut = default) : base(linkFile) =>
|
||||
LoadAndResolve(linkFile, (SLR_FLAGS)resolveFlags, window, (ushort)timeOut.TotalMilliseconds);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ShellLink"/> class and sets many properties. This link is not saved as a file.
|
||||
|
@ -147,10 +144,38 @@ namespace Vanara.Windows.Shell
|
|||
}
|
||||
|
||||
/// <summary>Gets/sets the HotKey to start the shortcut (if any).</summary>
|
||||
public Keys HotKey
|
||||
/// <value>
|
||||
/// <para>
|
||||
/// The keyboard shortcut. The virtual key code is in the low-order byte, and the modifier flags are in the high-order byte. The
|
||||
/// modifier flags can be a combination of the following values.
|
||||
/// </para>
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Value</term>
|
||||
/// <term>Meaning</term>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term><c>HOTKEYF_ALT</c> 0x04</term>
|
||||
/// <term>ALT key</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term><c>HOTKEYF_CONTROL</c> 0x02</term>
|
||||
/// <term>CTRL key</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term><c>HOTKEYF_EXT</c> 0x08</term>
|
||||
/// <term>Extended key</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term><c>HOTKEYF_SHIFT</c> 0x01</term>
|
||||
/// <term>SHIFT key</term>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </value>
|
||||
public ushort HotKey
|
||||
{
|
||||
get { var hk = link.GetHotKey(); return (Keys)MAKELONG(LOBYTE(hk), HIBYTE(hk)); }
|
||||
set { link.SetHotKey(MAKEWORD((byte)LOWORD((uint)value), (byte)HIWORD((uint)value))); Save(); }
|
||||
get => link.GetHotKey();
|
||||
set { link.SetHotKey(value); Save(); }
|
||||
}
|
||||
|
||||
/// <summary>Gets the index of this icon within the icon path's resources.</summary>
|
||||
|
@ -202,10 +227,10 @@ namespace Vanara.Windows.Shell
|
|||
|
||||
/// <summary>Gets or sets the show command for a Shell link object.</summary>
|
||||
/// <value>The show command for a Shell link object.</value>
|
||||
public FormWindowState ShowState
|
||||
public ShowWindowCommand ShowState
|
||||
{
|
||||
get => (FormWindowState)link.GetShowCmd() - 1;
|
||||
set { link.SetShowCmd((ShowWindowCommand)value + 1); Save(); }
|
||||
get => link.GetShowCmd() - 1;
|
||||
set { link.SetShowCmd(value + 1); Save(); }
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the target with a <see cref="ShellItem"/> instance.</summary>
|
||||
|
@ -360,8 +385,9 @@ namespace Vanara.Windows.Shell
|
|||
|
||||
if (resolveFlags.IsFlagSet(SLR_FLAGS.SLR_NO_UI) && timeOut != 0)
|
||||
resolveFlags = (SLR_FLAGS)MAKELONG((ushort)resolveFlags, timeOut);
|
||||
|
||||
#if !NETSTANDARD
|
||||
new FileIOPermission(FileIOPermissionAccess.Read, fullPath).Demand();
|
||||
#endif
|
||||
((IPersistFile)link).Load(fullPath, (int)STGM.STGM_DIRECT);
|
||||
link.Resolve(hWin, resolveFlags);
|
||||
|
||||
|
|
|
@ -3,24 +3,23 @@
|
|||
<PropertyGroup>
|
||||
<Description>Common classes for Windows Shell items derived from the Vanara PInvoke libraries. Includes shell items, files, icons, links, and taskbar lists.</Description>
|
||||
<AssemblyTitle>$(AssemblyName)</AssemblyTitle>
|
||||
<TargetFrameworks>net20;net35;net40;net45;net5.0;net6.0;netcoreapp3.0;netcoreapp3.1</TargetFrameworks>
|
||||
<AssemblyName>Vanara.Windows.Shell</AssemblyName>
|
||||
<TargetFrameworks>net20;net35;net40;net45;net5.0;net6.0;netstandard2.0;netcoreapp2.0;netcoreapp2.1;netcoreapp3.0;netcoreapp3.1</TargetFrameworks>
|
||||
<AssemblyName>Vanara.Windows.Shell.Common</AssemblyName>
|
||||
<PackageId>$(AssemblyName)</PackageId>
|
||||
<PackageTags>pinvoke;vanara;net-extensions;interop</PackageTags>
|
||||
<RootNamespace>Vanara.Windows.Shell</RootNamespace>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" Condition=" $(TargetFramework.StartsWith('netcore')) Or $(TargetFramework.StartsWith('netcore')) " />
|
||||
<PackageReference Include="Theraot.Core" Version="3.2.9" Condition=" $(TargetFramework.StartsWith('net2')) Or $(TargetFramework.StartsWith('net3')) Or $(TargetFramework.StartsWith('net4')) " />
|
||||
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" Condition=" $(TargetFramework.StartsWith('netcore')) Or $(TargetFramework.StartsWith('netstandard')) Or $(TargetFramework.StartsWith('net5')) Or $(TargetFramework.StartsWith('net6')) " />
|
||||
<PackageReference Include="System.Security.Permissions" Version="4.4.0" Condition=" $(TargetFramework.StartsWith('netcore')) Or $(TargetFramework.StartsWith('net5')) Or $(TargetFramework.StartsWith('net6')) " />
|
||||
<PackageReference Include="Theraot.Core" Version="3.2.11" Condition=" $(TargetFramework.StartsWith('net2')) Or $(TargetFramework.StartsWith('net3')) Or $(TargetFramework.StartsWith('net4')) " />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Core\Vanara.Core.csproj" />
|
||||
<ProjectReference Include="..\PInvoke\Shared\Vanara.PInvoke.Shared.csproj" />
|
||||
<ProjectReference Include="..\PInvoke\ComCtl32\Vanara.PInvoke.ComCtl32.csproj" />
|
||||
<ProjectReference Include="..\PInvoke\Ole\Vanara.PInvoke.Ole.csproj" />
|
||||
<ProjectReference Include="..\PInvoke\Shell32\Vanara.PInvoke.Shell32.csproj" />
|
||||
<ProjectReference Include="..\PInvoke\User32\Vanara.PInvoke.User32.csproj" />
|
||||
<ProjectReference Include="..\PInvoke\SearchApi\Vanara.PInvoke.SearchApi.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue