#nullable enable
using System;
using System.ComponentModel;
namespace Vanara.Windows.Shell
{
/// Wraps a resource reference used by some Shell classes.
public abstract class IndirectResource
{
/// Initializes a new instance of the class.
/// The value of the string.
public IndirectResource(string? value = null) => RawValue = value;
/// 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 resource in the module file.
///
/// The version modifier. This value can be, and usually is, .
public IndirectResource(string module, int resourceIdOrIndex, string? versionModifier = null)
{
if (module is null) throw new ArgumentNullException(nameof(module));
RawValue = $"@{module},{resourceIdOrIndex}" + (versionModifier is null ? "" : ';' + versionModifier);
}
/// Initializes a new instance of the class.
/// The package name or package resource index file name.
/// The package locator.
/// packageNameOrPriFile or packageLocator
/// Package locator must start with 'ms-resource://' - packageLocator
public IndirectResource(string packageNameOrPriFile, string packageLocator)
{
if (packageNameOrPriFile is null) throw new ArgumentNullException(nameof(packageNameOrPriFile));
if (packageLocator is null) throw new ArgumentNullException(nameof(packageLocator));
if (!packageLocator.StartsWith("ms-resource://")) throw new ArgumentException("Package locator must start with 'ms-resource://'", nameof(packageLocator));
RawValue = $"@{{{packageNameOrPriFile}? {packageLocator}}}";
}
/// Returns true if this location is valid.
/// true if this location is valid; otherwise, false.
[Browsable(false)]
public virtual bool IsValid => ModuleFileName != null && ResourceId != 0 || (PackageName != null || PackageResourceIndexFile != null) && PackageLocator != null;
/// Gets the module file name.
/// The module file name.
[Browsable(false)]
public string? ModuleFileName
{
get
{
if (RawValue is null || RawValue.Length == 0 || RawValue[0] != '@' || RawValue.Length > 1 && RawValue[1] == '{') return null;
return RawValue.TrimStart('@').Split(',')[0];
}
}
/// Gets the resource name used to lookup the resource within a package.
/// The resource lookup name.
public string? PackageLocator
{
get
{
if (RawValue is null || RawValue.Length == 0 || RawValue[0] != '@' || RawValue.Length > 1 && !(RawValue[1] == '{' && RawValue[RawValue.Length - 1] == '}')) return null;
var parts = RawValue.Substring(2).TrimEnd('}').Split('?');
return parts.Length > 1 && parts[1].Trim().StartsWith("ms-resource://") ? parts[1].Trim() : null;
}
}
///
/// Gets the name of the package. The string is extracted from the Resources.pri file stored in the app's root directory of the
/// package identified by PackageFullName, using the resource as a locator. The retrieved string is copied to the output buffer and
/// the function returns S_OK. The string is extracted based on the app's environment or ResourceContext. Note: This string must
/// refer to a package installed for the current user.If it does not, the call will fail.
///
/// The name of the package. Something like "Microsoft.Camera_6.2.8376.0_x64__8wekyb3d8bbwe".
[Browsable(false)]
public string? PackageName
{
get
{
if (RawValue is null || RawValue.Length == 0 || RawValue[0] != '@' || RawValue.Length > 1 && !(RawValue[1] == '{' && RawValue[RawValue.Length - 1] == '}')) return null;
var parts = RawValue.Substring(2).TrimEnd('}').Split('?');
return parts[0].IndexOf('\\') >= 0 ? null : parts[0];
}
}
///
/// Gets the package resource index file name. The Package Resource Index (PRI) is a binary format introduced in Windows 8 that
/// contains indexed resources or references to resources. The .pri file is bundled as part of an app's package. For more
/// information on .pri files, see Creating and retrieving resources in Windows Store apps. The string is extracted from the.pri
/// file named, using the resource as a locator.The retrieved string is copied to the output buffer and the function returns S_OK.
/// The string is extracted based on the current Shell environment or ResourceContext.
///
/// The package resource index file name. Something like "C:\Program Files\WindowsApps\Microsoft.Camera_6.2.8376.0_x64__8wekyb3d8bbwe\resources.pri".
[Browsable(false)]
public string? PackageResourceIndexFile
{
get
{
if (RawValue is null || RawValue.Length == 0 || RawValue[0] != '@' || RawValue.Length > 1 && !(RawValue[1] == '{' && RawValue[RawValue.Length - 1] == '}')) return null;
var parts = RawValue.Substring(2).TrimEnd('}').Split('?');
return parts[0].IndexOf('\\') >= 0 && System.IO.Path.GetExtension(parts[0]) != null && System.IO.Path.GetExtension(RawValue).Equals(".pri", StringComparison.InvariantCultureIgnoreCase) ? parts[0] : null;
}
}
/// Gets the raw value of the string.
/// Returns a value.
public string? RawValue { get; private set; }
/// Gets or sets the resource index or resource ID.
///
/// 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 icon in the module file.
///
[Browsable(false)]
public int ResourceId
{
get
{
if (RawValue is null || RawValue.Length == 0 || RawValue[0] != '@' || RawValue.Length > 1 && RawValue[1] == '{') return 0;
var parts = RawValue.Split(',', ';');
return parts.Length > 1 && int.TryParse(parts[1], out var i) ? i : 0;
}
}
/// Gets the version modifier. This value is rarely used.
/// The version modifier (e.g. "v2").
[Browsable(false)]
public string? VersionModifier
{
get
{
if (RawValue is null || RawValue.Length == 0 || RawValue[0] != '@' || RawValue.Length > 1 && RawValue[1] == '{') return null;
var parts = RawValue.Split(',', ';');
return parts.Length > 2 ? parts[2] : null;
}
}
/// Returns a that represents this instance.
/// A that represents this instance.
public override string ToString() => RawValue ?? "";
}
}