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;
}
}
}