Refactored for new C# language optimizations

master
David Hall 2024-06-06 11:19:40 -06:00
parent dcdfe3f215
commit 05c6710389
25 changed files with 122 additions and 207 deletions

View File

@ -1,5 +1,4 @@
#pragma warning disable IL2050 // Correctness of COM interop cannot be guaranteed after trimming. Interfaces and interface members might be removed. using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices.ComTypes; using System.Runtime.InteropServices.ComTypes;
using System.Security; using System.Security;
@ -459,7 +458,7 @@ public static partial class Shell32
private class ManualParentAndItem : IParentAndItem, IDisposable private class ManualParentAndItem : IParentAndItem, IDisposable
{ {
private readonly PIDL pChild; private readonly PIDL pChild;
private IShellFolder psf; private readonly IShellFolder psf;
public ManualParentAndItem(IShellItem psi) public ManualParentAndItem(IShellItem psi)
{ {
@ -469,10 +468,7 @@ public static partial class Shell32
pItem.Dispose(); pItem.Dispose();
} }
void IDisposable.Dispose() void IDisposable.Dispose() => pChild.Dispose();
{
pChild.Dispose();
}
HRESULT IParentAndItem.GetParentAndItem(out PIDL ppidlParent, out IShellFolder ppsf, out PIDL ppidlChild) HRESULT IParentAndItem.GetParentAndItem(out PIDL ppidlParent, out IShellFolder ppsf, out PIDL ppidlChild)
{ {

View File

@ -115,7 +115,7 @@ public static class GdiObjExtensions2
pen = new Pen(lpen.elpColor) { DashStyle = (DashStyle)lpen.Style }; pen = new Pen(lpen.elpColor) { DashStyle = (DashStyle)lpen.Style };
if (pen.DashStyle == DashStyle.Custom && lpen.elpNumEntries > 0) if (pen.DashStyle == DashStyle.Custom && lpen.elpNumEntries > 0)
{ {
uint[] styleArray = lpen.elpStyleEntry.ToArray<uint>((int)lpen.elpNumEntries) ?? new uint[0]; uint[] styleArray = lpen.elpStyleEntry.ToArray<uint>((int)lpen.elpNumEntries) ?? [];
pen.DashPattern = Array.ConvertAll(styleArray, i => (float)i); pen.DashPattern = Array.ConvertAll(styleArray, i => (float)i);
} }
break; break;
@ -213,18 +213,11 @@ public static class GdiObjExtensions2
/// <summary>A self-releasing pattern for IDeviceContext.GetHdc and ReleaseHdc.</summary> /// <summary>A self-releasing pattern for IDeviceContext.GetHdc and ReleaseHdc.</summary>
/// <seealso cref="System.IDisposable"/> /// <seealso cref="System.IDisposable"/>
public class SafeTempHDC : IDisposable, IGraphicsObjectHandle /// <remarks>Initializes a new instance of the <see cref="SafeTempHDC"/> class with an <see cref="IDeviceContext"/>.</remarks>
/// <param name="dc">The <see cref="IDeviceContext"/> instance.</param>
public class SafeTempHDC(IDeviceContext? dc) : IDisposable, IGraphicsObjectHandle
{ {
private readonly IDeviceContext? dc; private readonly IntPtr hdc = dc?.GetHdc() ?? default;
private readonly IntPtr hdc;
/// <summary>Initializes a new instance of the <see cref="SafeTempHDC"/> class with an <see cref="IDeviceContext"/>.</summary>
/// <param name="dc">The <see cref="IDeviceContext"/> instance.</param>
public SafeTempHDC(IDeviceContext? dc)
{
this.dc = dc;
hdc = dc?.GetHdc() ?? default;
}
/// <summary>Gets a value indicating whether this instance has a NULL handle.</summary> /// <summary>Gets a value indicating whether this instance has a NULL handle.</summary>
/// <value><see langword="true"/> if this has a NULL handle; otherwise, <see langword="false"/>.</value> /// <value><see langword="true"/> if this has a NULL handle; otherwise, <see langword="false"/>.</value>
@ -239,5 +232,9 @@ public class SafeTempHDC : IDisposable, IGraphicsObjectHandle
public IntPtr DangerousGetHandle() => hdc; public IntPtr DangerousGetHandle() => hdc;
/// <summary>Releases claimed HDC.</summary> /// <summary>Releases claimed HDC.</summary>
public void Dispose() => dc?.ReleaseHdc(); public void Dispose()
{
dc?.ReleaseHdc();
GC.SuppressFinalize(this);
}
} }

View File

@ -87,7 +87,7 @@ public static partial class GdiExtension
throw new ArgumentNullException(nameof(destination)); throw new ArgumentNullException(nameof(destination));
if (source.IsEmpty) if (source.IsEmpty)
throw new ArgumentNullException(nameof(source)); throw new ArgumentNullException(nameof(source));
if (transparency < 0 || transparency > 1.0f) if (transparency is < 0 or > 1.0f)
throw new ArgumentNullException(nameof(transparency)); throw new ArgumentNullException(nameof(transparency));
var imageRectangle = GetRectangleFromAlignment(alignment, destination, source.Size); var imageRectangle = GetRectangleFromAlignment(alignment, destination, source.Size);
@ -333,7 +333,7 @@ public static partial class GdiExtension
private class Enumertor : IEnumerator<Color> private class Enumertor : IEnumerator<Color>
{ {
private SmartBitmapLock bmpLock; private readonly SmartBitmapLock bmpLock;
private int idx = -1; private int idx = -1;
internal Enumertor(SmartBitmapLock bmp) => bmpLock = bmp; internal Enumertor(SmartBitmapLock bmp) => bmpLock = bmp;

View File

@ -161,7 +161,7 @@ public class BindContext : IDisposable, IBindCtxV, IBindCtx
/// in a return value of E_NOTIMPL. /// in a return value of E_NOTIMPL.
/// </para> /// </para>
/// </remarks> /// </remarks>
public IEnumerable<string> EnumObjectParam() => ((IBindCtxV)this).EnumObjectParam(out var ppenum).Succeeded ? ppenum.Enum().ToArray() : new string[0]; public IEnumerable<string> EnumObjectParam() => ((IBindCtxV)this).EnumObjectParam(out var ppenum).Succeeded ? ppenum.Enum().ToArray() : [];
/// <summary> /// <summary>
/// Retrieves an interface pointer to the object associated with the specified key in the bind context's string-keyed table of pointers. /// Retrieves an interface pointer to the object associated with the specified key in the bind context's string-keyed table of pointers.
@ -892,13 +892,9 @@ public class BindContext : IDisposable, IBindCtxV, IBindCtx
} }
[ComVisible(true)] [ComVisible(true)]
private class CDummyUnknown : IPersist private class CDummyUnknown(Guid clsid) : IPersist
{ {
private readonly Guid _clsid; public Guid GetClassID() => clsid;
public CDummyUnknown(in Guid clsid) => _clsid = clsid;
public Guid GetClassID() => _clsid;
} }
[ComVisible(true)] [ComVisible(true)]

View File

@ -71,7 +71,7 @@ internal class IconLocationTypeConverter : ExpandableObjectConverter
public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? info, object? value, Type destType) public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? info, object? value, Type destType)
{ {
if (destType == typeof(InstanceDescriptor)) if (destType == typeof(InstanceDescriptor))
return new InstanceDescriptor(typeof(IconLocation).GetConstructor(new Type[0]), null, false); return new InstanceDescriptor(typeof(IconLocation).GetConstructor([]), null, false);
if (destType == typeof(string) && value is IconLocation s) if (destType == typeof(string) && value is IconLocation s)
return s.ToString(); return s.ToString();
return base.ConvertTo(context, info, value, destType); return base.ConvertTo(context, info, value, destType);

View File

@ -450,11 +450,9 @@ public class MRUManager : Component
private SafeRegKey GetKey() => new(Registry.CurrentUser, SubKeyName ?? throw new InvalidOperationException("Invalid assembly name."), RegistryKeyPermissionCheck.ReadWriteSubTree); private SafeRegKey GetKey() => new(Registry.CurrentUser, SubKeyName ?? throw new InvalidOperationException("Invalid assembly name."), RegistryKeyPermissionCheck.ReadWriteSubTree);
private class SafeRegKey : IDisposable private class SafeRegKey(RegistryKey root, string subKeyName, RegistryKeyPermissionCheck opt) : IDisposable
{ {
public readonly RegistryKey Key; public readonly RegistryKey Key = root.CreateSubKey(subKeyName, opt);
public SafeRegKey(RegistryKey root, string subKeyName, RegistryKeyPermissionCheck opt) => Key = root.CreateSubKey(subKeyName, opt);
public static implicit operator RegistryKey(SafeRegKey k) => k.Key; public static implicit operator RegistryKey(SafeRegKey k) => k.Key;

View File

@ -62,7 +62,7 @@ public static class RecycleBin
/// The <see cref="ShellItem"/> of the deleted item in the Recycle Bin. This cannot be a reference to an undeleted shell item. /// The <see cref="ShellItem"/> of the deleted item in the Recycle Bin. This cannot be a reference to an undeleted shell item.
/// </param> /// </param>
/// <param name="hideUI"><see langword="true"/> to hide all user interface interactions; <see langword="false"/> to allow them.</param> /// <param name="hideUI"><see langword="true"/> to hide all user interface interactions; <see langword="false"/> to allow them.</param>
public static void Restore(ShellItem deletedItem, bool hideUI = false) => Restore(new[] { deletedItem }, hideUI); public static void Restore(ShellItem deletedItem, bool hideUI = false) => Restore([deletedItem], hideUI);
/// <summary>Restores the specified deleted items to their original location.</summary> /// <summary>Restores the specified deleted items to their original location.</summary>
/// <param name="deletedItems"> /// <param name="deletedItems">

View File

@ -347,10 +347,7 @@ public class AppRegistration : RegBasedSettings
return new AppRegistration(ska, sk, readOnly); return new AppRegistration(ska, sk, readOnly);
} }
private class PathSubKey : RegBasedSettings private class PathSubKey(RegistryKey key, bool readOnly) : RegBasedSettings(key, readOnly)
{ {
public PathSubKey(RegistryKey key, bool readOnly) : base(key, readOnly)
{
}
} }
} }

View File

@ -25,7 +25,7 @@ public class CommandVerbDictionary : RegBasedDictionary<CommandVerb>
/// <summary>Get the filtered list of keys under the base.</summary> /// <summary>Get the filtered list of keys under the base.</summary>
[Browsable(false)] [Browsable(false)]
public override IEnumerable<string> Keys => key?.GetSubKeyNames() ?? new string[0]; public override IEnumerable<string> Keys => key?.GetSubKeyNames() ?? [];
/// <summary>Gets or sets the order of the command verbs.</summary> /// <summary>Gets or sets the order of the command verbs.</summary>
/// <value>The ordered list of command verbs.</value> /// <value>The ordered list of command verbs.</value>

View File

@ -10,25 +10,19 @@ namespace Vanara.Windows.Shell;
/// <summary>A virtual dictionary that is based on values in the Windows Registry.</summary> /// <summary>A virtual dictionary that is based on values in the Windows Registry.</summary>
/// <typeparam name="T">Type used to capture multiple values within the registry.</typeparam> /// <typeparam name="T">Type used to capture multiple values within the registry.</typeparam>
/// <seealso cref="VirtualReadOnlyDictionary{TKey, TValue}"/> /// <seealso cref="VirtualReadOnlyDictionary{TKey, TValue}"/>
public abstract class RegBasedDictionary<T> : VirtualReadOnlyDictionary<string, T> /// <remarks>Initializes a new instance of the <see cref="RegBasedDictionary{T}"/> class.</remarks>
/// <param name="baseKey">The base registry key.</param>
/// <param name="readOnly">if set to <see langword="true"/> render this dictionary read-only.</param>
public abstract class RegBasedDictionary<T>(RegistryKey? baseKey, bool readOnly) : VirtualReadOnlyDictionary<string, T>
{ {
/// <summary>Read-only flag.</summary> /// <summary>Read-only flag.</summary>
protected readonly bool readOnly; protected readonly bool readOnly = readOnly;
/// <summary>The base registry key for this dictionary.</summary> /// <summary>The base registry key for this dictionary.</summary>
protected RegistryKey? key; protected RegistryKey? key = baseKey;
/// <summary>Initializes a new instance of the <see cref="RegBasedDictionary{T}"/> class.</summary>
/// <param name="baseKey">The base registry key.</param>
/// <param name="readOnly">if set to <see langword="true"/> render this dictionary read-only.</param>
protected RegBasedDictionary(RegistryKey? baseKey, bool readOnly)
{
key = baseKey;
this.readOnly = readOnly;
}
/// <summary>Get the filtered list of keys under the base.</summary> /// <summary>Get the filtered list of keys under the base.</summary>
public override IEnumerable<string> Keys => key?.GetSubKeyNames().Where(SubKeyFilter) ?? new string[0]; public override IEnumerable<string> Keys => key?.GetSubKeyNames().Where(SubKeyFilter) ?? [];
/// <summary>Determines if a specified key is in the filtered list of keys under the base.</summary> /// <summary>Determines if a specified key is in the filtered list of keys under the base.</summary>
/// <param name="key">The name of the key to check.</param> /// <param name="key">The name of the key to check.</param>
@ -43,12 +37,8 @@ public abstract class RegBasedDictionary<T> : VirtualReadOnlyDictionary<string,
protected virtual bool SubKeyFilter(string keyName) => true; protected virtual bool SubKeyFilter(string keyName) => true;
} }
internal class AppDictionary : RegBasedDictionary<AppRegistration> internal class AppDictionary(bool readOnly) : RegBasedDictionary<AppRegistration>(Registry.ClassesRoot.OpenSubKey(AppRegistration.appsSubKey, !readOnly), readOnly)
{ {
public AppDictionary(bool readOnly) : base(Registry.ClassesRoot.OpenSubKey(AppRegistration.appsSubKey, !readOnly), readOnly)
{
}
public override bool TryGetValue(string key, [MaybeNullWhen(false)] out AppRegistration value) public override bool TryGetValue(string key, [MaybeNullWhen(false)] out AppRegistration value)
{ {
value = null; value = null;
@ -58,12 +48,8 @@ internal class AppDictionary : RegBasedDictionary<AppRegistration>
} }
} }
internal class FileTypeDictionary : RegBasedDictionary<FileTypeAssociation> internal class FileTypeDictionary(bool readOnly) : RegBasedDictionary<FileTypeAssociation>(Registry.ClassesRoot, readOnly)
{ {
public FileTypeDictionary(bool readOnly) : base(Registry.ClassesRoot, readOnly)
{
}
public override bool TryGetValue(string key, [MaybeNullWhen(false)] out FileTypeAssociation value) public override bool TryGetValue(string key, [MaybeNullWhen(false)] out FileTypeAssociation value)
{ {
value = null; value = null;
@ -75,21 +61,17 @@ internal class FileTypeDictionary : RegBasedDictionary<FileTypeAssociation>
protected override bool SubKeyFilter(string keyName) => keyName.StartsWith("."); protected override bool SubKeyFilter(string keyName) => keyName.StartsWith(".");
} }
internal class ProgIdDictionary : RegBasedDictionary<ProgId> internal class ProgIdDictionary(bool readOnly) : RegBasedDictionary<ProgId>(Registry.ClassesRoot, readOnly)
{ {
private static readonly string[] badKeys = private static readonly string[] badKeys =
{ [
"*", "AllFileSystemObjects", "AppID", "Applications", "AudioCD", "Briefcase", "CID", "CID.Local", "*", "AllFileSystemObjects", "AppID", "Applications", "AudioCD", "Briefcase", "CID", "CID.Local",
"CLSID", "CompressedFolder", "ConflictFolder", "DVD", "DVDFile", "DesktopBackground", "DirectShow", "CLSID", "CompressedFolder", "ConflictFolder", "DVD", "DVDFile", "DesktopBackground", "DirectShow",
"Directory", "Drive", "ExplorerCLSIDFlags", "Folder", "Interface", "LibraryFolder", "Local Settings", "Directory", "Drive", "ExplorerCLSIDFlags", "Folder", "Interface", "LibraryFolder", "Local Settings",
"MIME", "Media Servers", "Media Type", "MediaFoundation", "NetServer", "NetShare", "Network", "MIME", "Media Servers", "Media Type", "MediaFoundation", "NetServer", "NetShare", "Network",
"Printers", "Stack", "SystemFileAssociations", "TypeLib", "Unknown", "UserLibraryFolder", "Printers", "Stack", "SystemFileAssociations", "TypeLib", "Unknown", "UserLibraryFolder",
"VideoClipContainers", "VirtualStore" "VideoClipContainers", "VirtualStore"
}; ];
public ProgIdDictionary(bool readOnly) : base(Registry.ClassesRoot, readOnly)
{
}
public override bool TryGetValue(string key, [MaybeNullWhen(false)] out ProgId value) public override bool TryGetValue(string key, [MaybeNullWhen(false)] out ProgId value)
{ {
@ -103,12 +85,8 @@ internal class ProgIdDictionary : RegBasedDictionary<ProgId>
!keyName.StartsWith("Kind.") && Array.BinarySearch(badKeys, keyName, StringComparer.OrdinalIgnoreCase) < 0; !keyName.StartsWith("Kind.") && Array.BinarySearch(badKeys, keyName, StringComparer.OrdinalIgnoreCase) < 0;
} }
internal class ShellAssociationDictionary : RegBasedDictionary<ShellAssociation> internal class ShellAssociationDictionary(bool readOnly) : RegBasedDictionary<ShellAssociation>(Registry.ClassesRoot, readOnly)
{ {
public ShellAssociationDictionary(bool readOnly) : base(Registry.ClassesRoot, readOnly)
{
}
public override bool TryGetValue(string key, [MaybeNullWhen(false)] out ShellAssociation value) public override bool TryGetValue(string key, [MaybeNullWhen(false)] out ShellAssociation value)
{ {
value = null; value = null;

View File

@ -51,7 +51,7 @@ internal class RegBasedKeyCollection : ICollection<string>, IDisposable
/// <summary>Gets the enumerator.</summary> /// <summary>Gets the enumerator.</summary>
/// <returns></returns> /// <returns></returns>
public IEnumerator<string> GetEnumerator() => (key?.GetValueNames().Cast<string>() ?? new string[0]).GetEnumerator(); public IEnumerator<string> GetEnumerator() => (key?.GetValueNames().Cast<string>() ?? []).GetEnumerator();
/// <summary>Removes the specified item.</summary> /// <summary>Removes the specified item.</summary>
/// <param name="item">The item.</param> /// <param name="item">The item.</param>

View File

@ -3,26 +3,20 @@
namespace Vanara.Windows.Shell; namespace Vanara.Windows.Shell;
/// <summary>Base class for registry based settings.</summary> /// <summary>Base class for registry based settings.</summary>
public abstract class RegBasedSettings : IDisposable, IEquatable<RegBasedSettings>, IComparable<RegBasedSettings> /// <remarks>Initializes a new instance of the <see cref="RegBasedSettings"/> class.</remarks>
/// <param name="key">The key to use as the base key for queries.</param>
/// <param name="readOnly">if set to <c>true</c> the supplied <paramref name="key"/> was opened read-only.</param>
public abstract class RegBasedSettings(RegistryKey key, bool readOnly) : IDisposable, IEquatable<RegBasedSettings>, IComparable<RegBasedSettings>
{ {
/// <summary>The base key from which to perform all queries.</summary> /// <summary>The base key from which to perform all queries.</summary>
protected internal RegistryKey key; protected internal RegistryKey key = key ?? throw new ArgumentNullException(nameof(key));
/// <summary>Initializes a new instance of the <see cref="RegBasedSettings"/> class.</summary>
/// <param name="key">The key to use as the base key for queries.</param>
/// <param name="readOnly">if set to <c>true</c> the supplied <paramref name="key"/> was opened read-only.</param>
protected RegBasedSettings(RegistryKey key, bool readOnly)
{
this.key = key ?? throw new ArgumentNullException(nameof(key));
ReadOnly = readOnly;
}
/// <summary>Gets a value indicating whether this instance is system wide.</summary> /// <summary>Gets a value indicating whether this instance is system wide.</summary>
/// <value><see langword="true"/> if this instance is system wide; otherwise, <see langword="false"/>.</value> /// <value><see langword="true"/> if this instance is system wide; otherwise, <see langword="false"/>.</value>
public bool IsSystemWide => !key.Name.StartsWith("HKEY_CURRENT_USER"); public bool IsSystemWide => !key.Name.StartsWith("HKEY_CURRENT_USER");
/// <summary>Gets or sets a value indicating whether these settings are read-only.</summary> /// <summary>Gets or sets a value indicating whether these settings are read-only.</summary>
public bool ReadOnly { get; } public bool ReadOnly { get; } = readOnly;
/// <summary>Gets the absolute (qualified) name of the key.</summary> /// <summary>Gets the absolute (qualified) name of the key.</summary>
public string RegPath => key.Name; public string RegPath => key.Name;

View File

@ -14,42 +14,33 @@ namespace Vanara.Windows.Shell;
/// A DragEventArgs object specifies any data associated with drag/drop events; the current state of the SHIFT, CTRL, and ALT keys; the /// A DragEventArgs object specifies any data associated with drag/drop events; the current state of the SHIFT, CTRL, and ALT keys; the
/// location of the mouse pointer; and the drag-and-drop effects allowed by the source and target of the drag event. /// location of the mouse pointer; and the drag-and-drop effects allowed by the source and target of the drag event.
/// </remarks> /// </remarks>
public class DragEventArgs : EventArgs /// <remarks>Initializes a new instance of the <see cref="DragEventArgs"/> class.</remarks>
/// <param name="data">The data associated with this event.</param>
/// <param name="keyState">The current state of the SHIFT, CTRL, and ALT keys.</param>
/// <param name="x">The x-coordinate of the mouse cursor in pixels.</param>
/// <param name="y">The y-coordinate of the mouse cursor in pixels.</param>
/// <param name="allowedEffect">One of the DROPEFFECT values.</param>
/// <param name="lastEffect">One of the DROPEFFECT values.</param>
public class DragEventArgs(IDataObject? data, MouseButtonState keyState, int x, int y, Ole32.DROPEFFECT allowedEffect, Ole32.DROPEFFECT lastEffect) : EventArgs
{ {
/// <summary>Initializes a new instance of the <see cref="DragEventArgs"/> class.</summary>
/// <param name="data">The data associated with this event.</param>
/// <param name="keyState">The current state of the SHIFT, CTRL, and ALT keys.</param>
/// <param name="x">The x-coordinate of the mouse cursor in pixels.</param>
/// <param name="y">The y-coordinate of the mouse cursor in pixels.</param>
/// <param name="allowedEffect">One of the DROPEFFECT values.</param>
/// <param name="lastEffect">One of the DROPEFFECT values.</param>
public DragEventArgs(IDataObject? data, MouseButtonState keyState, int x, int y, DROPEFFECT allowedEffect, DROPEFFECT lastEffect)
{
Data = data;
KeyState = keyState;
X = x;
Y = y;
AllowedEffect = allowedEffect;
Effect = lastEffect;
}
/// <summary>Gets which drag-and-drop operations are allowed by the originator (or source) of the drag event.</summary> /// <summary>Gets which drag-and-drop operations are allowed by the originator (or source) of the drag event.</summary>
public DROPEFFECT AllowedEffect { get; } public DROPEFFECT AllowedEffect { get; } = allowedEffect;
/// <summary>Gets the IDataObject that contains the data associated with this event.</summary> /// <summary>Gets the IDataObject that contains the data associated with this event.</summary>
public IDataObject? Data { get; } public IDataObject? Data { get; } = data;
/// <summary>Gets or sets the target drop effect in a drag-and-drop operation.</summary> /// <summary>Gets or sets the target drop effect in a drag-and-drop operation.</summary>
public DROPEFFECT Effect { get; set; } public DROPEFFECT Effect { get; set; } = lastEffect;
/// <summary>Gets the current state of the SHIFT, CTRL, and ALT keys, as well as the state of the mouse buttons.</summary> /// <summary>Gets the current state of the SHIFT, CTRL, and ALT keys, as well as the state of the mouse buttons.</summary>
public MouseButtonState KeyState { get; } public MouseButtonState KeyState { get; } = keyState;
/// <summary>Gets the x-coordinate of the mouse pointer, in screen coordinates.</summary> /// <summary>Gets the x-coordinate of the mouse pointer, in screen coordinates.</summary>
public int X { get; } public int X { get; } = x;
/// <summary>Gets the y-coordinate of the mouse pointer, in screen coordinates.</summary> /// <summary>Gets the y-coordinate of the mouse pointer, in screen coordinates.</summary>
public int Y { get; } public int Y { get; } = y;
} }
/// <summary> /// <summary>

View File

@ -461,52 +461,48 @@ public partial class ShellFileOperations : IDisposable
private ShellItemArray GetSHArray(IEnumerable<ShellItem> items) => items is ShellItemArray a ? a : new ShellItemArray(items); private ShellItemArray GetSHArray(IEnumerable<ShellItem> items) => items is ShellItemArray a ? a : new ShellItemArray(items);
private class OpSink : IFileOperationProgressSink private class OpSink(ShellFileOperations ops) : IFileOperationProgressSink
{ {
private readonly ShellFileOperations parent; public HRESULT FinishOperations(HRESULT hrResult) => CallChkErr(() => ops.FinishOperations?.Invoke(ops, new ShellFileOpEventArgs(0, null, null, null, null, hrResult)));
public OpSink(ShellFileOperations ops) => parent = ops;
public HRESULT FinishOperations(HRESULT hrResult) => CallChkErr(() => parent.FinishOperations?.Invoke(parent, new ShellFileOpEventArgs(0, null, null, null, null, hrResult)));
public HRESULT PauseTimer() => HRESULT.E_NOTIMPL; public HRESULT PauseTimer() => HRESULT.E_NOTIMPL;
public HRESULT PostCopyItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName, HRESULT hrCopy, IShellItem psiNewlyCreated) => public HRESULT PostCopyItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName, HRESULT hrCopy, IShellItem psiNewlyCreated) =>
CallChkErr(() => parent.PostCopyItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, psiDestinationFolder, psiNewlyCreated, pszNewName, hrCopy))); CallChkErr(() => ops.PostCopyItem?.Invoke(ops, new ShellFileOpEventArgs(dwFlags, psiItem, psiDestinationFolder, psiNewlyCreated, pszNewName, hrCopy)));
public HRESULT PostDeleteItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, HRESULT hrDelete, IShellItem? psiNewlyCreated) => public HRESULT PostDeleteItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, HRESULT hrDelete, IShellItem? psiNewlyCreated) =>
CallChkErr(() => parent.PostDeleteItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, null, psiNewlyCreated, null, hrDelete))); CallChkErr(() => ops.PostDeleteItem?.Invoke(ops, new ShellFileOpEventArgs(dwFlags, psiItem, null, psiNewlyCreated, null, hrDelete)));
public HRESULT PostMoveItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName, HRESULT hrMove, IShellItem psiNewlyCreated) => public HRESULT PostMoveItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName, HRESULT hrMove, IShellItem psiNewlyCreated) =>
CallChkErr(() => parent.PostMoveItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, psiDestinationFolder, psiNewlyCreated, pszNewName, hrMove))); CallChkErr(() => ops.PostMoveItem?.Invoke(ops, new ShellFileOpEventArgs(dwFlags, psiItem, psiDestinationFolder, psiNewlyCreated, pszNewName, hrMove)));
public HRESULT PostNewItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName, [MarshalAs(UnmanagedType.LPWStr)] string? pszTemplateName, uint dwFileAttributes, HRESULT hrNew, IShellItem psiNewItem) => public HRESULT PostNewItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName, [MarshalAs(UnmanagedType.LPWStr)] string? pszTemplateName, uint dwFileAttributes, HRESULT hrNew, IShellItem psiNewItem) =>
CallChkErr(() => parent.PostNewItem?.Invoke(parent, new ShellFileNewOpEventArgs(dwFlags, null, psiDestinationFolder, psiNewItem, pszNewName, hrNew, pszTemplateName, dwFileAttributes))); CallChkErr(() => ops.PostNewItem?.Invoke(ops, new ShellFileNewOpEventArgs(dwFlags, null, psiDestinationFolder, psiNewItem, pszNewName, hrNew, pszTemplateName, dwFileAttributes)));
public HRESULT PostRenameItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName, HRESULT hrRename, IShellItem psiNewlyCreated) => public HRESULT PostRenameItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName, HRESULT hrRename, IShellItem psiNewlyCreated) =>
CallChkErr(() => parent.PostRenameItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, null, psiNewlyCreated, pszNewName, hrRename))); CallChkErr(() => ops.PostRenameItem?.Invoke(ops, new ShellFileOpEventArgs(dwFlags, psiItem, null, psiNewlyCreated, pszNewName, hrRename)));
public HRESULT PreCopyItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string? pszNewName) => public HRESULT PreCopyItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string? pszNewName) =>
CallChkErr(() => parent.PreCopyItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, psiDestinationFolder, null, pszNewName))); CallChkErr(() => ops.PreCopyItem?.Invoke(ops, new ShellFileOpEventArgs(dwFlags, psiItem, psiDestinationFolder, null, pszNewName)));
public HRESULT PreDeleteItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem) => public HRESULT PreDeleteItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem) =>
CallChkErr(() => parent.PreDeleteItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem))); CallChkErr(() => ops.PreDeleteItem?.Invoke(ops, new ShellFileOpEventArgs(dwFlags, psiItem)));
public HRESULT PreMoveItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string? pszNewName) => public HRESULT PreMoveItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string? pszNewName) =>
CallChkErr(() => parent.PreMoveItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, psiDestinationFolder, null, pszNewName))); CallChkErr(() => ops.PreMoveItem?.Invoke(ops, new ShellFileOpEventArgs(dwFlags, psiItem, psiDestinationFolder, null, pszNewName)));
public HRESULT PreNewItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName) => public HRESULT PreNewItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiDestinationFolder, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName) =>
CallChkErr(() => parent.PreNewItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, null, psiDestinationFolder, null, pszNewName))); CallChkErr(() => ops.PreNewItem?.Invoke(ops, new ShellFileOpEventArgs(dwFlags, null, psiDestinationFolder, null, pszNewName)));
public HRESULT PreRenameItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName) => CallChkErr(() => parent.PreRenameItem?.Invoke(parent, new ShellFileOpEventArgs(dwFlags, psiItem, null, null, pszNewName))); public HRESULT PreRenameItem(TRANSFER_SOURCE_FLAGS dwFlags, IShellItem psiItem, [MarshalAs(UnmanagedType.LPWStr)] string pszNewName) => CallChkErr(() => ops.PreRenameItem?.Invoke(ops, new ShellFileOpEventArgs(dwFlags, psiItem, null, null, pszNewName)));
public HRESULT ResetTimer() => HRESULT.E_NOTIMPL; public HRESULT ResetTimer() => HRESULT.E_NOTIMPL;
public HRESULT ResumeTimer() => HRESULT.E_NOTIMPL; public HRESULT ResumeTimer() => HRESULT.E_NOTIMPL;
public HRESULT StartOperations() => CallChkErr(() => parent.StartOperations?.Invoke(parent, EventArgs.Empty)); public HRESULT StartOperations() => CallChkErr(() => ops.StartOperations?.Invoke(ops, EventArgs.Empty));
public HRESULT UpdateProgress(uint iWorkTotal, uint iWorkSoFar) => CallChkErr(() => parent.UpdateProgress?.Invoke(parent, new ProgressChangedEventArgs(iWorkTotal == 0 ? 0 : (int)(iWorkSoFar * 100 / iWorkTotal), null))); public HRESULT UpdateProgress(uint iWorkTotal, uint iWorkSoFar) => CallChkErr(() => ops.UpdateProgress?.Invoke(ops, new ProgressChangedEventArgs(iWorkTotal == 0 ? 0 : (int)(iWorkSoFar * 100 / iWorkTotal), null)));
private HRESULT CallChkErr(Action action) private HRESULT CallChkErr(Action action)
{ {

View File

@ -315,7 +315,7 @@ public class ShellItemChangeWatcher : Component, ISupportInitialize
enabled = true; enabled = true;
if (IsSuspended) return; if (IsSuspended) return;
SHGetIDListFromObject(Item.IShellItem, out PIDL pidlWatch).ThrowIfFailed(); SHGetIDListFromObject(Item.IShellItem, out PIDL pidlWatch).ThrowIfFailed();
SHChangeNotifyEntry[] entries = { new SHChangeNotifyEntry { pidl = pidlWatch.DangerousGetHandle(), fRecursive = IncludeChildren } }; SHChangeNotifyEntry[] entries = [new SHChangeNotifyEntry { pidl = pidlWatch.DangerousGetHandle(), fRecursive = IncludeChildren }];
ulRegister = SHChangeNotifyRegister(hPump.MessageWindowHandle, sources, (SHCNE)NotifyFilter, hPump.MessageId, entries.Length, entries); ulRegister = SHChangeNotifyRegister(hPump.MessageWindowHandle, sources, (SHCNE)NotifyFilter, hPump.MessageId, entries.Length, entries);
if (ulRegister == 0) throw new InvalidOperationException("Unable to register shell notifications."); if (ulRegister == 0) throw new InvalidOperationException("Unable to register shell notifications.");
} }
@ -349,28 +349,20 @@ public class ShellItemChangeWatcher : Component, ISupportInitialize
public ChangeFilters ChangeType { get; } public ChangeFilters ChangeType { get; }
} }
private class WatcherNativeWindow : SystemEventHandler private class WatcherNativeWindow(ShellItemChangeWatcher parent) : SystemEventHandler()
{ {
private readonly ShellItemChangeWatcher p; public uint MessageId { get; set; } = RegisterWindowMessage($"{parent.GetType()}{DateTime.Now.Ticks}");
public WatcherNativeWindow(ShellItemChangeWatcher parent) : base()
{
MessageId = RegisterWindowMessage($"{parent.GetType()}{DateTime.Now.Ticks}");
p = parent;
}
public uint MessageId { get; set; }
protected override bool MessageFilter(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; lReturn = default;
if (msg == MessageId && p.enabled && !p.IsSuspended) if (msg == MessageId && parent.enabled && !parent.IsSuspended)
{ {
HLOCK hNotifyLock = default; HLOCK hNotifyLock = default;
try try
{ {
hNotifyLock = SHChangeNotification_Lock(wParam, (uint)lParam.ToInt32(), out IntPtr rgpidl, out SHCNE lEvent); hNotifyLock = SHChangeNotification_Lock(wParam, (uint)lParam.ToInt32(), out IntPtr rgpidl, out SHCNE lEvent);
if (hNotifyLock != IntPtr.Zero && rgpidl != IntPtr.Zero && p.NotifyFilter.IsFlagSet((ChangeFilters)lEvent)) if (hNotifyLock != IntPtr.Zero && rgpidl != IntPtr.Zero && parent.NotifyFilter.IsFlagSet((ChangeFilters)lEvent))
{ {
ShellItemChangeEventArgs args; ShellItemChangeEventArgs args;
if (NoParamEvent.IsFlagSet(lEvent)) if (NoParamEvent.IsFlagSet(lEvent))
@ -379,7 +371,7 @@ public class ShellItemChangeWatcher : Component, ISupportInitialize
args = new ShellItemChangeEventArgs(lEvent, Marshal.ReadIntPtr(rgpidl, 0), Marshal.ReadIntPtr(rgpidl, IntPtr.Size)); args = new ShellItemChangeEventArgs(lEvent, Marshal.ReadIntPtr(rgpidl, 0), Marshal.ReadIntPtr(rgpidl, IntPtr.Size));
else else
args = new ShellItemChangeEventArgs(lEvent, Marshal.ReadIntPtr(rgpidl, 0)); args = new ShellItemChangeEventArgs(lEvent, Marshal.ReadIntPtr(rgpidl, 0));
p.OnChanged(args); parent.OnChanged(args);
} }
} }
finally finally

View File

@ -8,14 +8,12 @@ namespace Vanara.Windows.Shell;
/// <seealso cref="IEquatable{T}"/> /// <seealso cref="IEquatable{T}"/>
/// <seealso cref="IEquatable{T}"/> /// <seealso cref="IEquatable{T}"/>
/// <seealso cref="INotifyPropertyChanged"/> /// <seealso cref="INotifyPropertyChanged"/>
public abstract class ComObjWrapper<TObj, TComType> : IDisposable, IEquatable<TComType>, INotifyPropertyChanged where TObj : ComObjWrapper<TObj, TComType> where TComType : class /// <remarks>Initializes a new instance of the <see cref="ComObjWrapper{TObj, TComType}"/> class.</remarks>
/// <param name="baseInterface">The base interface.</param>
public abstract class ComObjWrapper<TObj, TComType>(TComType baseInterface) : IDisposable, IEquatable<TComType>, INotifyPropertyChanged where TObj : ComObjWrapper<TObj, TComType> where TComType : class
{ {
/// <summary>The internal reference to the COM object.</summary> /// <summary>The internal reference to the COM object.</summary>
protected TComType iObj; protected TComType iObj = baseInterface ?? throw new ArgumentNullException(nameof(baseInterface));
/// <summary>Initializes a new instance of the <see cref="ComObjWrapper{TObj, TComType}"/> class.</summary>
/// <param name="baseInterface">The base interface.</param>
protected ComObjWrapper(TComType baseInterface) => iObj = baseInterface ?? throw new ArgumentNullException(nameof(baseInterface));
/// <summary>Occurs when a property value changes.</summary> /// <summary>Occurs when a property value changes.</summary>
public virtual event PropertyChangedEventHandler? PropertyChanged; public virtual event PropertyChangedEventHandler? PropertyChanged;

View File

@ -462,7 +462,7 @@ public class ShellContextMenu : IDisposable
internal static MenuItemInfo[] GetMenuItems(HMENU hMenu, ShellContextMenu? scm) internal static MenuItemInfo[] GetMenuItems(HMENU hMenu, ShellContextMenu? scm)
{ {
if (hMenu.IsNull) if (hMenu.IsNull)
return new MenuItemInfo[0]; return [];
var SubMenus = new MenuItemInfo[GetMenuItemCount(hMenu)]; var SubMenus = new MenuItemInfo[GetMenuItemCount(hMenu)];
for (uint i = 0; i < SubMenus.Length; i++) for (uint i = 0; i < SubMenus.Length; i++)

View File

@ -516,7 +516,7 @@ public class ShellItem : IComparable<ShellItem>, IDisposable, IEquatable<IShellI
/// <para>Gets the property store for the item.</para> /// <para>Gets the property store for the item.</para>
/// <note>Initially, this property store is the read-only store (change from R/W in v3.2.9) and should always have properties. /// <note>Initially, this property store is the read-only store (change from R/W in v3.2.9) and should always have properties.
/// However, setting any of the properties of this value change the function of all subsequent uses. For example, if you set the /// However, setting any of the properties of this value change the function of all subsequent uses. For example, if you set the
/// <see cref="ShellItemPropertyStore.ReadOnly"/> value to <see langword="false"/>, all subsequent calls to <see /// <see cref="ReadOnlyPropertyStore.ReadOnly"/> value to <see langword="false"/>, all subsequent calls to <see
/// cref="Properties"/> will access the read-write property store. If this <see cref="ShellItem"/> does not support /// cref="Properties"/> will access the read-write property store. If this <see cref="ShellItem"/> does not support
/// properties directly, your use of this property will fail. It is important that you check for exceptions when changing the /// properties directly, your use of this property will fail. It is important that you check for exceptions when changing the
/// properties of this value to prevent unexpected failures.</note> /// properties of this value to prevent unexpected failures.</note>
@ -785,7 +785,7 @@ public class ShellItem : IComparable<ShellItem>, IDisposable, IEquatable<IShellI
if (IsFolder) if (IsFolder)
SHOpenFolderAndSelectItems(PIDL, 0, null, OFASI.OFASI_NONE); SHOpenFolderAndSelectItems(PIDL, 0, null, OFASI.OFASI_NONE);
else else
SHOpenFolderAndSelectItems(Parent!.PIDL, 1, new IntPtr[] { (IntPtr)PIDL }, OFASI.OFASI_NONE); SHOpenFolderAndSelectItems(Parent!.PIDL, 1, [(IntPtr)PIDL], OFASI.OFASI_NONE);
} }
/// <summary> /// <summary>
@ -877,14 +877,12 @@ public class ShellItem : IComparable<ShellItem>, IDisposable, IEquatable<IShellI
/// <summary>Local implementation of IShellItem.</summary> /// <summary>Local implementation of IShellItem.</summary>
/// <seealso cref="IDisposable"/> /// <seealso cref="IDisposable"/>
/// <seealso cref="Shell32.IShellItem"/> /// <seealso cref="Shell32.IShellItem"/>
protected class ShellItemImpl : IDisposable, IShellItem /// <remarks>Initializes a new instance of the <see cref="ShellItemImpl"/> class.</remarks>
/// <param name="pidl">The pidl.</param>
/// <param name="owner">if set to <see langword="true"/> [owner].</param>
protected class ShellItemImpl(Shell32.PIDL pidl, bool owner) : IDisposable, IShellItem
{ {
/// <summary>Initializes a new instance of the <see cref="ShellItemImpl"/> class.</summary> private PIDL PIDL { get; set; } = owner ? pidl : new PIDL(pidl);
/// <param name="pidl">The pidl.</param>
/// <param name="owner">if set to <see langword="true"/> [owner].</param>
public ShellItemImpl(PIDL pidl, bool owner) => PIDL = owner ? pidl : new PIDL(pidl);
private PIDL PIDL { get; set; }
/// <summary>Binds to a handler for an item as specified by the handler ID value (BHID).</summary> /// <summary>Binds to a handler for an item as specified by the handler ID value (BHID).</summary>
/// <param name="pbc"> /// <param name="pbc">
@ -941,7 +939,7 @@ public class ShellItem : IComparable<ShellItem>, IDisposable, IEquatable<IShellI
{ {
var parentFolder = InternalGetParent().GetIShellFolder(); var parentFolder = InternalGetParent().GetIShellFolder();
var result = sfgaoMask; var result = sfgaoMask;
parentFolder.GetAttributesOf(1, new[] { (IntPtr)PIDL.LastId }, ref result).ThrowIfFailed(); parentFolder.GetAttributesOf(1, [(IntPtr)PIDL.LastId], ref result).ThrowIfFailed();
return result & sfgaoMask; return result & sfgaoMask;
} }
@ -1013,7 +1011,7 @@ internal class ShellItemTypeConverter : TypeConverter
} }
else if (destinationType == typeof(InstanceDescriptor)) else if (destinationType == typeof(InstanceDescriptor))
{ {
return new InstanceDescriptor(typeof(ShellItem).GetMethod("Open", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null), new object[] { uri.ToString() }); return new InstanceDescriptor(typeof(ShellItem).GetMethod("Open", BindingFlags.Public | BindingFlags.Static, null, [typeof(string)], null), new object[] { uri.ToString() });
} }
} }
return base.ConvertTo(context, culture, value, destinationType); return base.ConvertTo(context, culture, value, destinationType);

View File

@ -8,13 +8,10 @@ using static Vanara.PInvoke.User32;
namespace Vanara.Windows.Shell; namespace Vanara.Windows.Shell;
/// <summary>Exposes methods that get images related to shell items.</summary> /// <summary>Exposes methods that get images related to shell items.</summary>
public class ShellItemImages /// <remarks>Initializes a new instance of the <see cref="ShellItemImages"/> class.</remarks>
/// <param name="shellItem">The <see cref="ShellItem"/> instance.</param>
public class ShellItemImages(ShellItem shellItem)
{ {
private readonly ShellItem shellItem;
/// <summary>Initializes a new instance of the <see cref="ShellItemImages"/> class.</summary>
/// <param name="shellItem">The <see cref="ShellItem"/> instance.</param>
public ShellItemImages(ShellItem shellItem) => this.shellItem = shellItem;
/// <summary> /// <summary>
/// Gets an image that represents this item. The default behavior is to load a thumbnail. If there is no thumbnail for the current /// Gets an image that represents this item. The default behavior is to load a thumbnail. If there is no thumbnail for the current

View File

@ -99,7 +99,7 @@ public class ShellLibrary : ShellFolder
/// <summary>Gets the set of child folders that are contained in the library.</summary> /// <summary>Gets the set of child folders that are contained in the library.</summary>
/// <value>A <see cref="ShellItemArray"/> containing the child folders.</value> /// <value>A <see cref="ShellItemArray"/> containing the child folders.</value>
public ShellLibraryFolders Folders => folders ?? (folders = GetFilteredFolders()); public ShellLibraryFolders Folders => folders ??= GetFilteredFolders();
/// <summary> /// <summary>
/// Gets or sets a string that describes the location of the default icon. The string must be formatted as /// Gets or sets a string that describes the location of the default icon. The string must be formatted as

View File

@ -97,7 +97,7 @@ public class SearchCondition : ICloneable, IDisposable
/// <returns>The new <see cref="SearchCondition"/> node.</returns> /// <returns>The new <see cref="SearchCondition"/> node.</returns>
public static SearchCondition CreateFromStructuredQuery(string query, CultureInfo? cultureInfo = null) public static SearchCondition CreateFromStructuredQuery(string query, CultureInfo? cultureInfo = null)
{ {
if (cultureInfo is null) cultureInfo = CultureInfo.CurrentUICulture; cultureInfo ??= CultureInfo.CurrentUICulture;
using var qm = ComReleaserFactory.Create(new IQueryParserManager()); using var qm = ComReleaserFactory.Create(new IQueryParserManager());
using var qp = ComReleaserFactory.Create(qm.Item.CreateLoadedParser<IQueryParser>(systemCatalog, (uint)cultureInfo.LCID)); using var qp = ComReleaserFactory.Create(qm.Item.CreateLoadedParser<IQueryParser>(systemCatalog, (uint)cultureInfo.LCID));
qm.Item.InitializeOptions(false, true, qp.Item); qm.Item.InitializeOptions(false, true, qp.Item);

View File

@ -3,14 +3,12 @@
namespace Vanara.Windows.Shell; namespace Vanara.Windows.Shell;
/// <summary>Encapsulates an <see cref="IPropertyBag"/> instance.</summary> /// <summary>Encapsulates an <see cref="IPropertyBag"/> instance.</summary>
public class PropertyBag /// <remarks>Initializes a new instance of the <see cref="PropertyBag"/> class.</remarks>
/// <param name="ppb">The property bag.</param>
public class PropertyBag(PInvoke.OleAut32.IPropertyBag ppb)
{ {
/// <summary>The IPropertyBag instance.</summary> /// <summary>The IPropertyBag instance.</summary>
protected readonly IPropertyBag ibag; protected readonly IPropertyBag ibag = ppb;
/// <summary>Initializes a new instance of the <see cref="PropertyBag"/> class.</summary>
/// <param name="ppb">The property bag.</param>
public PropertyBag(IPropertyBag ppb) => ibag = ppb;
/// <summary>Gets or sets the <see cref="object"/> with the specified property name.</summary> /// <summary>Gets or sets the <see cref="object"/> with the specified property name.</summary>
/// <value>The <see cref="object"/>.</value> /// <value>The <see cref="object"/>.</value>

View File

@ -5,7 +5,12 @@ using static Vanara.PInvoke.User32;
namespace Vanara.Windows.Shell; namespace Vanara.Windows.Shell;
/// <summary>Represents a standard system icon.</summary> /// <summary>Represents a standard system icon.</summary>
public class StockIcon : IDisposable /// <remarks>Creates a new StockIcon instance with the specified identifer and options.</remarks>
/// <param name="id">A value that identifies the icon represented by this instance.</param>
/// <param name="size">A value that indicates the size of the stock icon.</param>
/// <param name="isLinkOverlay">A bool value that indicates whether the icon has a link overlay.</param>
/// <param name="isSelected">A bool value that indicates whether the icon is in a selected state.</param>
public class StockIcon(Shell32.SHSTOCKICONID id, ShellIconType size = ShellIconType.Large, bool isLinkOverlay = false, bool isSelected = false) : IDisposable
{ {
private SHGSI curFlags; private SHGSI curFlags;
private SHSTOCKICONID curId; private SHSTOCKICONID curId;
@ -15,19 +20,6 @@ public class StockIcon : IDisposable
static StockIcon() => FileIconInit(false); static StockIcon() => FileIconInit(false);
/// <summary>Creates a new StockIcon instance with the specified identifer and options.</summary>
/// <param name="id">A value that identifies the icon represented by this instance.</param>
/// <param name="size">A value that indicates the size of the stock icon.</param>
/// <param name="isLinkOverlay">A bool value that indicates whether the icon has a link overlay.</param>
/// <param name="isSelected">A bool value that indicates whether the icon is in a selected state.</param>
public StockIcon(SHSTOCKICONID id, ShellIconType size = ShellIconType.Large, bool isLinkOverlay = false, bool isSelected = false)
{
Identifier = id;
LinkOverlay = isLinkOverlay;
Selected = isSelected;
Size = size;
}
/// <summary>Finalizes an instance of the <see cref="StockIcon"/> class.</summary> /// <summary>Finalizes an instance of the <see cref="StockIcon"/> class.</summary>
~StockIcon() ~StockIcon()
{ {
@ -39,11 +31,11 @@ public class StockIcon : IDisposable
public HICON IconHandle => hIcon; public HICON IconHandle => hIcon;
/// <summary>Gets or sets the Stock Icon identifier associated with this icon.</summary> /// <summary>Gets or sets the Stock Icon identifier associated with this icon.</summary>
public SHSTOCKICONID Identifier { get; set; } public SHSTOCKICONID Identifier { get; set; } = id;
/// <summary>Gets or sets a value that cotrols whether to put a link overlay on the icon.</summary> /// <summary>Gets or sets a value that cotrols whether to put a link overlay on the icon.</summary>
/// <value>A <see cref="bool"/> value.</value> /// <value>A <see cref="bool"/> value.</value>
public bool LinkOverlay { get; set; } public bool LinkOverlay { get; set; } = isLinkOverlay;
/// <summary>Gets the icon location, composed of a resource path and the icon's index.</summary> /// <summary>Gets the icon location, composed of a resource path and the icon's index.</summary>
/// <value>The icon location.</value> /// <value>The icon location.</value>
@ -51,11 +43,11 @@ public class StockIcon : IDisposable
/// <summary>Gets or sets a value indicating whether the icon appears selected.</summary> /// <summary>Gets or sets a value indicating whether the icon appears selected.</summary>
/// <value>A <see cref="bool"/> value.</value> /// <value>A <see cref="bool"/> value.</value>
public bool Selected { get; set; } public bool Selected { get; set; } = isSelected;
/// <summary>Gets or sets a value that controls the size of the Stock Icon.</summary> /// <summary>Gets or sets a value that controls the size of the Stock Icon.</summary>
/// <value>A <see cref="ShellIconType"/> value.</value> /// <value>A <see cref="ShellIconType"/> value.</value>
public ShellIconType Size { get; set; } public ShellIconType Size { get; set; } = size;
/// <summary>Gets the index of the image in the system icon cache.</summary> /// <summary>Gets the index of the image in the system icon cache.</summary>
/// <value>The index of the system image.</value> /// <value>The index of the system image.</value>

View File

@ -266,18 +266,11 @@ public class JumpListSeparator : JumpListItem, IJumpListItem
/// <summary>A task for a jumplist.</summary> /// <summary>A task for a jumplist.</summary>
/// <seealso cref="JumpListItem"/> /// <seealso cref="JumpListItem"/>
public class JumpListTask : JumpListItem, IJumpListItem /// <remarks>Initializes a new instance of the <see cref="JumpListTask"/> class.</remarks>
public class JumpListTask(string? title, string applicationPath) : JumpListItem, IJumpListItem
{ {
private int iconResIdx = -1; private int iconResIdx = -1;
private string path; private string? description, args, dir, iconPath, appUserModelID;
private string? title, description, args, dir, iconPath, appUserModelID;
/// <summary>Initializes a new instance of the <see cref="JumpListTask"/> class.</summary>
public JumpListTask(string? title, string applicationPath)
{
this.title = title;
path = applicationPath;
}
/// <summary>Gets or sets the application path.</summary> /// <summary>Gets or sets the application path.</summary>
/// <value>The application path.</value> /// <value>The application path.</value>
@ -286,12 +279,12 @@ public class JumpListTask : JumpListItem, IJumpListItem
[Editor("System.Windows.Forms.Design.FileNameEditor, System.Design", "System.Drawing.Design.UITypeEditor, System.Drawing")] [Editor("System.Windows.Forms.Design.FileNameEditor, System.Design", "System.Drawing.Design.UITypeEditor, System.Drawing")]
public string ApplicationPath public string ApplicationPath
{ {
get => path; get => applicationPath;
set set
{ {
if (value is null) throw new ArgumentNullException(nameof(ApplicationPath)); if (value is null) throw new ArgumentNullException(nameof(ApplicationPath));
if (path == value) return; if (applicationPath == value) return;
path = value; applicationPath = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
@ -460,7 +453,7 @@ internal class GenericExpandableObjectConverter<T> : ExpandableObjectConverter
public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? info, object? value, Type destType) public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? info, object? value, Type destType)
{ {
if (destType == typeof(InstanceDescriptor)) if (destType == typeof(InstanceDescriptor))
return new InstanceDescriptor(typeof(T).GetConstructor(new Type[0]), null, false); return new InstanceDescriptor(typeof(T).GetConstructor([]), null, false);
if (destType == typeof(string)) if (destType == typeof(string))
return ""; return "";
return base.ConvertTo(context, info, value, destType); return base.ConvertTo(context, info, value, destType);

View File

@ -21,10 +21,13 @@ ChangeFilters, DialogStatus, ExecutableType, FileUsageType, FolderItemFilter, Li
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('net4')) "> <ItemGroup Condition=" $(TargetFramework.StartsWith('net4')) ">
<Reference Include="System.Configuration" /> <Reference Include="System.Configuration" />
<Reference Include="System.Drawing" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" !$(TargetFramework.StartsWith('net4')) "> <ItemGroup Condition=" !$(TargetFramework.StartsWith('net4')) ">
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" Condition=" '$(TargetFramework)' == 'netcoreapp3.1' Or '$(TargetFramework)' == 'net5.0' " /> <PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" Condition=" '$(TargetFramework)' == 'netcoreapp3.1' Or '$(TargetFramework)' == 'net5.0' " />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.0" Condition=" '$(TargetFramework)' != 'netcoreapp3.1' And '$(TargetFramework)' != 'net5.0' " /> <PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.0" Condition=" '$(TargetFramework)' != 'netcoreapp3.1' And '$(TargetFramework)' != 'net5.0' " />
<PackageReference Include="System.Drawing.Common" Version="6.0.0" Condition=" $(TargetFramework.StartsWith('netcore')) Or $(TargetFramework.StartsWith('net5')) " />
<PackageReference Include="System.Drawing.Common" Version="8.0.5" Condition=" !$(TargetFramework.StartsWith('netcore')) And !$(TargetFramework.StartsWith('net5')) " />
<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')) Or $(TargetFramework.StartsWith('net7')) " /> <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')) Or $(TargetFramework.StartsWith('net7')) " />
<PackageReference Include="System.Security.Permissions" Version="6.0.0" Condition=" '$(TargetFramework)' == 'netcoreapp3.1' Or '$(TargetFramework)' == 'net5.0' " /> <PackageReference Include="System.Security.Permissions" Version="6.0.0" Condition=" '$(TargetFramework)' == 'netcoreapp3.1' Or '$(TargetFramework)' == 'net5.0' " />
<PackageReference Include="System.Security.Permissions" Version="8.0.0" Condition=" '$(TargetFramework)' != 'netcoreapp3.1' And '$(TargetFramework)' != 'net5.0' " /> <PackageReference Include="System.Security.Permissions" Version="8.0.0" Condition=" '$(TargetFramework)' != 'netcoreapp3.1' And '$(TargetFramework)' != 'net5.0' " />
@ -35,6 +38,7 @@ ChangeFilters, DialogStatus, ExecutableType, FileUsageType, FolderItemFilter, Li
<ProjectReference Include="..\PInvoke\Ole\Vanara.PInvoke.Ole.csproj" /> <ProjectReference Include="..\PInvoke\Ole\Vanara.PInvoke.Ole.csproj" />
<ProjectReference Include="..\PInvoke\Shell32\Vanara.PInvoke.Shell32.csproj" /> <ProjectReference Include="..\PInvoke\Shell32\Vanara.PInvoke.Shell32.csproj" />
<ProjectReference Include="..\PInvoke\SearchApi\Vanara.PInvoke.SearchApi.csproj" /> <ProjectReference Include="..\PInvoke\SearchApi\Vanara.PInvoke.SearchApi.csproj" />
<ProjectReference Include="..\Windows.Extensions\Vanara.Windows.Extensions.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="~AppBar.cs" /> <None Remove="~AppBar.cs" />