using System; using System.Runtime.InteropServices; using Vanara.Extensions; using Vanara.InteropServices; using static Vanara.PInvoke.Macros; #pragma warning disable IDE1006 // Naming Styles namespace Vanara.PInvoke { /// Predefined resource types. [PInvokeData("winuser.h")] public enum ResourceType : ushort { /// Accelerator table. RT_ACCELERATOR = 9, /// Animated cursor. RT_ANICURSOR = 21, /// Animated icon. RT_ANIICON = 22, /// Bitmap resource. RT_BITMAP = 2, /// Hardware-dependent cursor resource. RT_CURSOR = 1, /// Dialog box. RT_DIALOG = 5, /// /// Allows a resource editing tool to associate a string with an .rc file. Typically, the string is the name of the header file that /// provides symbolic names. The resource compiler parses the string but otherwise ignores the value. /// RT_DLGINCLUDE = 17, /// Font resource. RT_FONT = 8, /// Font directory resource. RT_FONTDIR = 7, /// Hardware-independent cursor resource. RT_GROUP_CURSOR = 12, /// Hardware-independent icon resource. RT_GROUP_ICON = 14, /// HTML resource. RT_HTML = 23, /// Hardware-dependent icon resource. RT_ICON = 3, /// Side-by-Side Assembly Manifest. RT_MANIFEST = 24, /// Menu resource. RT_MENU = 4, /// Message-table entry. RT_MESSAGETABLE = 11, /// Plug and Play resource. RT_PLUGPLAY = 19, /// Application-defined resource (raw data). RT_RCDATA = 10, /// String-table entry. RT_STRING = 6, /// Version resource. RT_VERSION = 16, /// VXD. RT_VXD = 20, } /// Helper structure to use for a pointer that can morph into a string, pointer or integer. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] [PInvokeData("winuser.h")] public struct ResourceId : IEquatable, IEquatable, IEquatable, IEquatable, IHandle { private IntPtr ptr; /// Gets or sets an integer identifier. /// The identifier. public int id { get => IS_INTRESOURCE(ptr) ? (ushort)ptr.ToInt32() : 0; set { if (value is > ushort.MaxValue or <= 0) throw new ArgumentOutOfRangeException(nameof(id)); ptr = (IntPtr)(ushort)value; } } /// Determines whether this value is an integer identifier for a resource. /// If the value is a resource identifier, the return value is . Otherwise, the return value is . public bool IsIntResource => IS_INTRESOURCE(ptr); /// Represent a NULL value. public static readonly ResourceId NULL = new(); /// public static bool operator ==(ResourceId left, ResourceId right) => left.Equals(right); /// public static bool operator !=(ResourceId left, ResourceId right) => !left.Equals(right); /// Performs an implicit conversion from to . /// The r. /// The result of the conversion. public static implicit operator int(ResourceId r) => r.id; /// Performs an implicit conversion from to . /// The r. /// The result of the conversion. public static implicit operator IntPtr(ResourceId r) => r.ptr; /// Performs an implicit conversion from to . /// The resource identifier. /// The result of the conversion. public static implicit operator ResourceId(int resId) => new() { id = resId }; /// Performs an implicit conversion from to . /// Type of the resource. /// The result of the conversion. public static implicit operator ResourceId(ResourceType resType) => new() { id = (int)resType }; /// Performs an implicit conversion from to . /// The PTR. /// The result of the conversion. public static implicit operator ResourceId(IntPtr p) => new() { ptr = p }; /// Performs an implicit conversion from to . /// The r. /// The result of the conversion. public static explicit operator string(ResourceId r) => r.ToString(); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public override bool Equals(object obj) { switch (obj) { case null: return false; case string s: return Equals(s); case int i: return Equals(i); case IntPtr p: return Equals(p); case ResourceId r: return Equals(r); case IHandle h: return Equals(h.DangerousGetHandle()); default: if (!obj.GetType().IsPrimitive) return false; try { return Equals(Convert.ToInt32(obj)); } catch { return false; } } } /// Returns a hash code for this instance. /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. public override int GetHashCode() => ptr.GetHashCode(); /// Returns a that represents this instance. /// A that represents this instance. public override string ToString() => IS_INTRESOURCE(ptr) ? $"#{ptr.ToInt32()}" : Marshal.PtrToStringAuto(ptr); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. public bool Equals(int other) => ptr.ToInt32().Equals(other); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. /// public bool Equals(string other) => string.Equals(ToString(), other); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. public bool Equals(IntPtr other) => ptr.Equals(other); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. /// public bool Equals(ResourceId other) => string.Equals(other.ToString(), ToString()); /// public IntPtr DangerousGetHandle() => ptr; } /// Helper structure to use for a pointer that can morph into a string, handle or integer. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] [PInvokeData("winuser.h")] public struct ResourceIdOrHandle : IEquatable, IEquatable, IEquatable>, IHandle where THandle : IHandle { private IntPtr ptr; /// Gets or sets an integer identifier. /// The identifier. public int id { get => IS_INTRESOURCE(ptr) ? (ushort)ptr.ToInt32() : 0; set { if (value is > ushort.MaxValue or <= 0) throw new ArgumentOutOfRangeException(nameof(id)); ptr = (IntPtr)(ushort)value; } } /// Represent a NULL value. public static readonly ResourceIdOrHandle NULL = new(); /// public static bool operator ==(ResourceIdOrHandle left, ResourceIdOrHandle right) => left.Equals(right); /// public static bool operator !=(ResourceIdOrHandle left, ResourceIdOrHandle right) => !left.Equals(right); /// Performs an implicit conversion from to . /// The r. /// The result of the conversion. public static implicit operator int(ResourceIdOrHandle r) => r.id; /// Performs an implicit conversion from to . /// The r. /// The result of the conversion. public static implicit operator IntPtr(ResourceIdOrHandle r) => r.ptr; /// Performs an implicit conversion from to . /// The resource identifier. /// The result of the conversion. public static implicit operator ResourceIdOrHandle(int resId) => new() { id = resId }; /// Performs an implicit conversion from to . /// Type of the resource. /// The result of the conversion. public static implicit operator ResourceIdOrHandle(ResourceType resType) => new() { id = (int)resType }; /// Performs an implicit conversion from to . /// The PTR. /// The result of the conversion. public static implicit operator ResourceIdOrHandle(THandle p) => new() { ptr = p.DangerousGetHandle() }; /// Performs an implicit conversion from to . /// The r. /// The result of the conversion. public static explicit operator string(ResourceIdOrHandle r) => r.ToString(); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public override bool Equals(object obj) { switch (obj) { case null: return false; case string s: return Equals(s); case int i: return Equals(i); case IntPtr p: return Equals(p); case ResourceIdOrHandle r: return Equals(r); case IHandle h: return Equals(h.DangerousGetHandle()); default: if (!obj.GetType().IsPrimitive) return false; try { return Equals(Convert.ToInt32(obj)); } catch { return false; } } } /// Returns a hash code for this instance. /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. public override int GetHashCode() => ptr.GetHashCode(); /// Returns a that represents this instance. /// A that represents this instance. public override string ToString() => IS_INTRESOURCE(ptr) ? $"#{ptr.ToInt32()}" : Marshal.PtrToStringAuto(ptr); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. public bool Equals(int other) => ptr.ToInt32().Equals(other); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. /// public bool Equals(string other) => string.Equals(ToString(), other); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. public bool Equals(IntPtr other) => ptr.Equals(other); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. /// public bool Equals(ResourceIdOrHandle other) => string.Equals(other.ToString(), ToString()); /// public IntPtr DangerousGetHandle() => ptr; } /// Represents a system resource name that can identify as a string, integer, or pointer. /// public class SafeResourceId : GenericSafeHandle, IEquatable, IEquatable, IEquatable, IEquatable, IEquatable, IHandle { /// Represent a NULL value. public static readonly SafeResourceId Null = new(); /// Initializes a new instance of the class. /// Name of the resource. /// The character set. /// resName public SafeResourceId(string resName, CharSet charSet = CharSet.Auto) { if (string.IsNullOrEmpty(resName)) throw new ArgumentNullException(nameof(resName)); CharSet = charSet; SetHandle(StringHelper.AllocString(resName, charSet)); } /// Initializes a new instance of the class. /// The resource identifier. public SafeResourceId(int resId) => id = resId; /// Initializes a new instance of the class. /// Type of the resource. public SafeResourceId(ResourceType resType) : this((int)resType) { } /// Initializes a new instance of the class. /// The PTR. public SafeResourceId(IntPtr ptr) { if (IS_INTRESOURCE(ptr)) SetHandle(ptr); else { var s = StringHelper.GetString(ptr, CharSet); if (s != null) SetHandle(StringHelper.AllocString(s, CharSet)); } } /// Initializes a new instance of the class. protected SafeResourceId() { } /// Gets or sets the character set to use on resource strings. /// The character set. public virtual CharSet CharSet { get; set; } = CharSet.Auto; /// Gets or sets an integer identifier. /// The identifier. public int id { get => IsIntResource ? (ushort)handle.ToInt32() : 0; set { if (value is > short.MaxValue or < short.MinValue) throw new ArgumentOutOfRangeException(nameof(id)); InternalCloseMethod(handle); SetHandle((IntPtr)unchecked((ushort)value)); } } /// Gets a value indicating whether this instance is an integer-based resource. /// true if this instance is an integer-based resource; otherwise, false. public bool IsIntResource => IS_INTRESOURCE(handle); /// public override bool IsInvalid => handle == IntPtr.Zero; /// protected override Func CloseMethod => InternalCloseMethod; /// Gets the string representation of a resource identifier. /// The resource identifier. /// The character set. /// The string representation. public static string GetString(IntPtr ptr, CharSet charSet = CharSet.Auto) => IS_INTRESOURCE(ptr) ? $"#{ptr.ToInt32()}" : StringHelper.GetString(ptr, charSet); /// Performs an implicit conversion from to . /// The r. /// The result of the conversion. public static implicit operator int(SafeResourceId r) => r.IsIntResource ? (ushort)r.handle.ToInt32() : 0; /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator ResourceId(SafeResourceId h) => h.handle; /// Performs an implicit conversion from to . /// Name of the resource. /// The result of the conversion. public static implicit operator SafeResourceId(string resName) => new(resName); /// Performs an implicit conversion from to . /// The resource identifier. /// The result of the conversion. public static implicit operator SafeResourceId(int resId) => new(resId); /// Performs an implicit conversion from to . /// Type of the resource. /// The result of the conversion. public static implicit operator SafeResourceId(ResourceType resType) => new(resType); /// Performs an implicit conversion from to . /// The PTR. /// The result of the conversion. public static implicit operator SafeResourceId(IntPtr ptr) => new(ptr); /// Performs an implicit conversion from to . /// The r. /// The result of the conversion. public static implicit operator string(SafeResourceId r) => r.ToString(); /// /// Gets a cloned handle that also, if a string resource, copies the string to a new handle which must be released using StringHelper.FreeString. /// /// A safe copy of this resource id. public SafeResourceId Clone() => new(handle); /// Determines whether the specified , is equal to this instance. /// The to compare with this instance. /// true if the specified is equal to this instance; otherwise, false. public override bool Equals(object obj) { switch (obj) { case null: return false; case ResourceId resId: return Equals(resId); case string s: return Equals(s); case int i: return Equals(i); case IntPtr p: return Equals(p); case SafeResourceId r: return Equals(r); default: if (!obj.GetType().IsPrimitive) return false; try { return Equals(Convert.ToInt32(obj)); } catch { return false; } } } /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. public bool Equals(string other) => string.Equals(ToString(), other); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. public bool Equals(int other) => other == handle.ToInt32(); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. public bool Equals(SafeResourceId other) => string.Equals(other.ToString(), ToString()); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. public bool Equals(ResourceId other) => other.Equals((ResourceId)this); /// Indicates whether the current object is equal to another object of the same type. /// An object to compare with this object. /// true if the current object is equal to the parameter; otherwise, false. public bool Equals(IntPtr other) => new SafeResourceId(other).Equals(this); /// public override int GetHashCode() => handle.GetHashCode(); /// public override string ToString() => GetString(handle, CharSet); private bool InternalCloseMethod(IntPtr h) { if (h != IntPtr.Zero && !IS_INTRESOURCE(h)) StringHelper.FreeString(h); return true; } } }