migrate Pilz.Win32 & optimize Pilz & Pilz.IO
This commit is contained in:
231
Pilz.Win32/Internals/IconFactory.cs
Normal file
231
Pilz.Win32/Internals/IconFactory.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
using Microsoft.Win32;
|
||||
using Pilz.Win32.Mapped;
|
||||
using Pilz.Win32.Native;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Pilz.Win32.Native.Shell32;
|
||||
|
||||
namespace Pilz.Win32.Internals;
|
||||
|
||||
public class IconFactory
|
||||
{
|
||||
|
||||
#region Custom exceptions class
|
||||
|
||||
public class IconNotFoundException : Exception
|
||||
{
|
||||
public IconNotFoundException(string fileName, int index) : base(string.Format("Icon with Id = {0} wasn't found in file {1}", index, fileName))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class UnableToExtractIconsException : Exception
|
||||
{
|
||||
public UnableToExtractIconsException(string fileName, int firstIconIndex, int iconCount) : base(string.Format("Tryed to extract {2} icons starting from the one with id {1} from the \"{0}\" file but failed", fileName, firstIconIndex, iconCount))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of icons in the specified file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">Full path of the file to look for.</param>
|
||||
/// <returns></returns>
|
||||
private static int GetIconsCountInFile(string fileName)
|
||||
{
|
||||
return ExtractIconEx(fileName, -1, null, null, 0);
|
||||
}
|
||||
|
||||
#region ExtractIcon-like functions
|
||||
|
||||
public static void ExtractEx(string fileName, List<Icon> largeIcons, List<Icon> smallIcons, int firstIconIndex, int iconCount)
|
||||
{
|
||||
//
|
||||
// Memory allocations
|
||||
//
|
||||
|
||||
var smallIconsPtrs = (nint[])null;
|
||||
var largeIconsPtrs = (nint[])null;
|
||||
|
||||
if (smallIcons is not null)
|
||||
smallIconsPtrs = new nint[iconCount];
|
||||
if (largeIcons is not null)
|
||||
largeIconsPtrs = new nint[iconCount];
|
||||
|
||||
//
|
||||
// Call to native Win32 API
|
||||
//
|
||||
|
||||
var apiResult = ExtractIconEx(fileName, firstIconIndex, largeIconsPtrs, smallIconsPtrs, iconCount);
|
||||
if (apiResult != iconCount)
|
||||
throw new UnableToExtractIconsException(fileName, firstIconIndex, iconCount);
|
||||
|
||||
//
|
||||
// Fill lists
|
||||
//
|
||||
|
||||
if (smallIcons is not null)
|
||||
{
|
||||
smallIcons.Clear();
|
||||
foreach (var actualIconPtr in smallIconsPtrs)
|
||||
smallIcons.Add(Icon.FromHandle(actualIconPtr));
|
||||
}
|
||||
if (largeIcons is not null)
|
||||
{
|
||||
largeIcons.Clear();
|
||||
foreach (var actualIconPtr in largeIconsPtrs)
|
||||
largeIcons.Add(Icon.FromHandle(actualIconPtr));
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Icon> ExtractEx(string fileName, SystemIconSize size, int firstIconIndex, int iconCount)
|
||||
{
|
||||
var iconList = new List<Icon>();
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case SystemIconSize.Large:
|
||||
{
|
||||
ExtractEx(fileName, iconList, null, firstIconIndex, iconCount);
|
||||
break;
|
||||
}
|
||||
case SystemIconSize.Small:
|
||||
{
|
||||
ExtractEx(fileName, null, iconList, firstIconIndex, iconCount);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("size");
|
||||
}
|
||||
}
|
||||
|
||||
return iconList;
|
||||
}
|
||||
|
||||
public static void Extract(string fileName, List<Icon> largeIcons, List<Icon> smallIcons)
|
||||
{
|
||||
var iconCount = GetIconsCountInFile(fileName);
|
||||
ExtractEx(fileName, largeIcons, smallIcons, 0, iconCount);
|
||||
}
|
||||
|
||||
public static List<Icon> Extract(string fileName, SystemIconSize size)
|
||||
{
|
||||
var iconCount = GetIconsCountInFile(fileName);
|
||||
return ExtractEx(fileName, size, 0, iconCount);
|
||||
}
|
||||
|
||||
public static Icon ExtractOne(string fileName, int index, SystemIconSize size)
|
||||
{
|
||||
try
|
||||
{
|
||||
var iconList = ExtractEx(fileName, size, index, 1);
|
||||
return iconList[0];
|
||||
}
|
||||
catch (UnableToExtractIconsException __unusedUnableToExtractIconsException1__)
|
||||
{
|
||||
throw new IconNotFoundException(fileName, index);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExtractOne(string fileName, int index, out Icon largeIcon, out Icon smallIcon)
|
||||
{
|
||||
var smallIconList = new List<Icon>();
|
||||
var largeIconList = new List<Icon>();
|
||||
try
|
||||
{
|
||||
ExtractEx(fileName, largeIconList, smallIconList, index, 1);
|
||||
largeIcon = largeIconList[0];
|
||||
smallIcon = smallIconList[0];
|
||||
}
|
||||
catch (UnableToExtractIconsException __unusedUnableToExtractIconsException1__)
|
||||
{
|
||||
throw new IconNotFoundException(fileName, index);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// this will look throw the registry
|
||||
// to find if the Extension have an icon.
|
||||
public static Icon IconFromExtension(string extension, SystemIconSize size)
|
||||
{
|
||||
// Add the '.' to the extension if needed
|
||||
if (extension[0] != '.')
|
||||
extension = '.' + extension;
|
||||
|
||||
// opens the registry for the wanted key.
|
||||
var Root = Registry.ClassesRoot;
|
||||
var ExtensionKey = Root.OpenSubKey(extension);
|
||||
ExtensionKey.GetValueNames();
|
||||
var ApplicationKey = Root.OpenSubKey(ExtensionKey.GetValue("").ToString());
|
||||
|
||||
// gets the name of the file that have the icon.
|
||||
var IconLocation = ApplicationKey.OpenSubKey("DefaultIcon").GetValue("").ToString();
|
||||
var IconPath = IconLocation.Split(',');
|
||||
|
||||
if (Equals(IconPath[1], null))
|
||||
IconPath[1] = "0";
|
||||
var Large = new nint[1];
|
||||
var Small = new nint[1];
|
||||
|
||||
// extracts the icon from the file.
|
||||
ExtractIconEx(IconPath[0], Convert.ToInt16(IconPath[1]), Large, Small, 1);
|
||||
return size == SystemIconSize.Large ? Icon.FromHandle(Large[0]) : Icon.FromHandle(Small[0]);
|
||||
}
|
||||
|
||||
public static Icon IconFromExtensionShell(string extension, SystemIconSize size)
|
||||
{
|
||||
// add '.' if nessesry
|
||||
if (extension[0] != '.')
|
||||
extension = '.' + extension;
|
||||
|
||||
// temp struct for getting file shell info
|
||||
var fileInfo = new SHFILEINFO();
|
||||
|
||||
Shell32.SHGetFileInfo(extension, 0U, ref fileInfo, (uint)Marshal.SizeOf(fileInfo), (uint)(FileInfoFlags.SHGFI_ICON | FileInfoFlags.SHGFI_USEFILEATTRIBUTES | (FileInfoFlags)size));
|
||||
|
||||
return Icon.FromHandle(fileInfo.hIcon);
|
||||
}
|
||||
|
||||
public static Icon IconFromResource(string resourceName)
|
||||
{
|
||||
var @assembly = Assembly.GetCallingAssembly();
|
||||
|
||||
return new Icon(assembly.GetManifestResourceStream(resourceName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse strings in registry who contains the name of the icon and
|
||||
/// the index of the icon an return both parts.
|
||||
/// </summary>
|
||||
/// <param name="regString">The full string in the form "path,index" as found in registry.</param>
|
||||
/// <param name="fileName">The "path" part of the string.</param>
|
||||
/// <param name="index">The "index" part of the string.</param>
|
||||
public static void ExtractInformationsFromRegistryString(string regString, out string fileName, out int index)
|
||||
{
|
||||
if (Equals(regString, null))
|
||||
throw new ArgumentNullException("regString");
|
||||
if (regString.Length == 0)
|
||||
throw new ArgumentException("The string should not be empty.", "regString");
|
||||
|
||||
index = 0;
|
||||
var strArr = regString.Replace("\"", "").Split(',');
|
||||
fileName = strArr[0].Trim();
|
||||
if (strArr.Length > 1)
|
||||
int.TryParse(strArr[1].Trim(), out index);
|
||||
}
|
||||
|
||||
public static Icon ExtractFromRegistryString(string regString, SystemIconSize size)
|
||||
{
|
||||
string fileName;
|
||||
int index;
|
||||
ExtractInformationsFromRegistryString(regString, out fileName, out index);
|
||||
return ExtractOne(fileName, index, size);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user