using System;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Globalization;
using Vanara.PInvoke;
using static Vanara.PInvoke.Kernel32;
using static Vanara.PInvoke.User32_Gdi;
namespace Vanara.Windows.Shell
{
/// Wraps a string resource reference used by some Shell classes.
[TypeConverter(typeof(IndirectStringTypeConverter))]
public class IndirectString : IndirectResource
{
/// Initializes a new instance of the class.
public IndirectString() { }
/// Initializes a new instance of the class.
public IndirectString(string value) : base(value, 0) { }
/// Initializes a new instance of the class.
/// The module file name.
///
/// If this number is positive, this is the index of the resource in the module file. If negative, the absolute value of the number
/// is the resource ID of the string in the module file.
///
public IndirectString(string module, int resourceIdOrIndex) : base(module, resourceIdOrIndex) { }
/// Gets the raw value of the string.
/// Returns a value.
[Browsable(false)]
public string RawValue => IsValid ? $"@{ModuleFileName},{ResourceId}" : ModuleFileName;
/// Gets the localized string referred to by this instance.
/// The referenced localized string.
[Browsable(false)]
public string Value
{
get
{
if (ResourceId == 0) return ModuleFileName;
using (var lib = LoadLibraryEx(ModuleFileName, Kernel32.LoadLibraryExFlags.LOAD_LIBRARY_AS_IMAGE_RESOURCE))
{
if (ResourceId >= 0) throw new NotSupportedException();
const int sz = 2048;
var sb = new System.Text.StringBuilder(sz, sz);
LoadString(lib, -ResourceId, sb, sz);
return sb.ToString();
}
}
}
/// Performs an implicit conversion from to .
/// The ind.
/// The result of the conversion.
public static implicit operator string(IndirectString ind) => ind.RawValue;
/// Performs an implicit conversion from to .
/// The s.
/// The result of the conversion.
public static implicit operator IndirectString(string s) => TryParse(s, out var loc) ? loc : null;
/// Tries to parse the specified string to create a instance.
/// The string representation in the format of either "ModuleFileName,ResourceIndex" or "ModuleFileName,-ResourceID".
/// The resulting instance on success.
/// true if successfully parsed.
public static bool TryParse(string value, out IndirectString loc)
{
var parts = value?.Split(',');
if (parts != null && parts.Length == 2 && int.TryParse(parts[1], out var i) && parts[0].StartsWith("@"))
{
loc = new IndirectString(parts[0].TrimStart('@'), i);
return true;
}
loc = new IndirectString(value);
return !string.IsNullOrEmpty(value);
}
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString() => RawValue ?? "";
}
internal class IndirectStringTypeConverter : ExpandableObjectConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destType)
{
if (destType == typeof(InstanceDescriptor) || destType == typeof(string))
return true;
return base.CanConvertTo(context, destType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string s)
return IndirectString.TryParse(s, out var loc) ? loc : null;
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo info, object value, Type destType)
{
if (destType == typeof(string) && value is IndirectString s)
return s.RawValue;
if (destType == typeof(InstanceDescriptor))
return new InstanceDescriptor(typeof(IndirectString).GetConstructor(new Type[0]), null, false);
return base.ConvertTo(context, info, value, destType);
}
}
}