2021-04-24 21:32:30 +12:00
|
|
|
|
// <copyright file="IconReader.cs" company="PlaceholderCompany">
|
|
|
|
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
|
|
|
// </copyright>
|
2021-10-16 06:42:02 +13:00
|
|
|
|
// see also: https://www.codeproject.com/Articles/2532/Obtaining-and-managing-file-and-folder-icons-using.
|
2021-04-24 21:32:30 +12:00
|
|
|
|
|
|
|
|
|
namespace SystemTrayMenu.Utilities
|
|
|
|
|
{
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Drawing.Imaging;
|
|
|
|
|
using System.IO;
|
2021-10-14 04:13:11 +13:00
|
|
|
|
using System.Linq;
|
2021-04-24 21:32:30 +12:00
|
|
|
|
using System.Runtime.InteropServices;
|
2021-10-14 04:13:11 +13:00
|
|
|
|
using System.Text;
|
2021-09-24 08:53:46 +12:00
|
|
|
|
using System.Threading;
|
2021-10-14 04:13:11 +13:00
|
|
|
|
using TAFactory.IconPack;
|
2021-04-24 21:32:30 +12:00
|
|
|
|
|
|
|
|
|
/// <summary>
|
2021-10-16 06:42:02 +13:00
|
|
|
|
/// Provides static methods to read system icons for folders and files.
|
2021-04-24 21:32:30 +12:00
|
|
|
|
/// </summary>
|
|
|
|
|
public static class IconReader
|
|
|
|
|
{
|
2021-11-17 12:13:46 +13:00
|
|
|
|
private static readonly ConcurrentDictionary<string, Icon> DictIconCacheMainMenu = new();
|
|
|
|
|
private static readonly ConcurrentDictionary<string, Icon> DictIconCacheSubMenus = new();
|
2021-04-24 21:32:30 +12:00
|
|
|
|
|
|
|
|
|
public enum IconSize
|
|
|
|
|
{
|
|
|
|
|
Large = 0, // 32x32 pixels
|
|
|
|
|
Small = 1, // 16x16 pixels
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public enum FolderType
|
|
|
|
|
{
|
|
|
|
|
Open = 0,
|
|
|
|
|
Closed = 1,
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-22 07:25:13 +13:00
|
|
|
|
// see https://github.com/Hofknecht/SystemTrayMenu/issues/209.
|
2021-11-13 20:18:33 +13:00
|
|
|
|
public static bool MainPreload { get; set; }
|
2021-10-16 06:42:02 +13:00
|
|
|
|
|
2021-11-14 01:55:01 +13:00
|
|
|
|
public static void Dispose(bool includingMainMenu = true)
|
2021-04-24 21:32:30 +12:00
|
|
|
|
{
|
2021-11-14 01:55:01 +13:00
|
|
|
|
if (includingMainMenu)
|
|
|
|
|
{
|
|
|
|
|
foreach (Icon icon in DictIconCacheMainMenu.Values)
|
|
|
|
|
{
|
|
|
|
|
icon?.Dispose();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (Icon icon in DictIconCacheSubMenus.Values)
|
2021-04-24 21:32:30 +12:00
|
|
|
|
{
|
|
|
|
|
icon?.Dispose();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-11 03:44:06 +13:00
|
|
|
|
public static bool ClearIfCacheTooBig()
|
2021-10-07 10:22:58 +13:00
|
|
|
|
{
|
|
|
|
|
bool cleared = false;
|
2021-11-14 01:55:01 +13:00
|
|
|
|
if (DictIconCacheSubMenus.Count > Properties.Settings.Default.ClearCacheIfMoreThanThisNumberOfItems)
|
2021-10-07 10:22:58 +13:00
|
|
|
|
{
|
2021-11-14 01:55:01 +13:00
|
|
|
|
Dispose(false);
|
|
|
|
|
DictIconCacheSubMenus.Clear();
|
2021-10-07 10:22:58 +13:00
|
|
|
|
cleared = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cleared;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-14 01:55:01 +13:00
|
|
|
|
public static Icon GetExtractAllIconsLastWithCache(
|
|
|
|
|
string filePath,
|
|
|
|
|
bool updateIconInBackground,
|
|
|
|
|
bool isMainMenu,
|
|
|
|
|
out bool loading)
|
2021-10-14 04:13:11 +13:00
|
|
|
|
{
|
|
|
|
|
bool linkOverlay = false;
|
|
|
|
|
loading = false;
|
|
|
|
|
string key = filePath;
|
|
|
|
|
|
|
|
|
|
string extension = Path.GetExtension(filePath);
|
|
|
|
|
|
|
|
|
|
if (IsExtensionWithSameIcon(extension))
|
|
|
|
|
{
|
|
|
|
|
key = extension + linkOverlay;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-14 01:55:01 +13:00
|
|
|
|
if (!DictIconCache(isMainMenu).TryGetValue(key, out Icon icon) &&
|
|
|
|
|
!DictIconCache(!isMainMenu).TryGetValue(key, out icon))
|
2021-10-14 04:13:11 +13:00
|
|
|
|
{
|
2021-10-26 08:45:49 +13:00
|
|
|
|
icon = Resources.StaticResources.LoadingIcon;
|
2021-10-14 04:13:11 +13:00
|
|
|
|
loading = true;
|
|
|
|
|
|
|
|
|
|
if (updateIconInBackground)
|
|
|
|
|
{
|
|
|
|
|
new Thread(UpdateIconInBackground).Start();
|
|
|
|
|
void UpdateIconInBackground()
|
|
|
|
|
{
|
2021-11-14 01:55:01 +13:00
|
|
|
|
DictIconCache(isMainMenu).GetOrAdd(key, GetExtractAllIconsLast);
|
2021-10-14 04:13:11 +13:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Icon GetExtractAllIconsLast(string keyExtension)
|
|
|
|
|
{
|
|
|
|
|
return GetExtractAllIconsLastSTA(filePath);
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-16 06:42:02 +13:00
|
|
|
|
static Icon GetExtractAllIconsLastSTA(string filePath)
|
2021-10-14 04:13:11 +13:00
|
|
|
|
{
|
2021-10-16 06:42:02 +13:00
|
|
|
|
Icon icon = null;
|
|
|
|
|
|
|
|
|
|
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
|
2021-10-14 04:13:11 +13:00
|
|
|
|
{
|
|
|
|
|
icon = GetExtractAllIconsLast(filePath);
|
|
|
|
|
}
|
2021-10-16 06:42:02 +13:00
|
|
|
|
else
|
|
|
|
|
{
|
2021-11-17 12:13:46 +13:00
|
|
|
|
Thread staThread = new(new ParameterizedThreadStart(StaThreadMethod));
|
2021-10-16 06:42:02 +13:00
|
|
|
|
void StaThreadMethod(object obj)
|
|
|
|
|
{
|
|
|
|
|
icon = GetExtractAllIconsLast(filePath);
|
|
|
|
|
}
|
2021-10-14 04:13:11 +13:00
|
|
|
|
|
2021-10-16 06:42:02 +13:00
|
|
|
|
staThread.SetApartmentState(ApartmentState.STA);
|
|
|
|
|
staThread.Start(icon);
|
|
|
|
|
staThread.Join();
|
|
|
|
|
}
|
2021-10-14 04:13:11 +13:00
|
|
|
|
|
2021-10-16 06:42:02 +13:00
|
|
|
|
static Icon GetExtractAllIconsLast(string filePath)
|
|
|
|
|
{
|
2021-11-17 12:13:46 +13:00
|
|
|
|
StringBuilder executable = new(1024);
|
2021-10-16 06:42:02 +13:00
|
|
|
|
DllImports.NativeMethods.Shell32FindExecutable(filePath, string.Empty, executable);
|
|
|
|
|
|
|
|
|
|
// icon = IconReader.GetFileIcon(executable, false);
|
|
|
|
|
// e.g. VS 2019 icon, need another icom in imagelist
|
|
|
|
|
List<Icon> extractedIcons = IconHelper.ExtractAllIcons(
|
|
|
|
|
executable.ToString());
|
|
|
|
|
return extractedIcons.Last();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return icon;
|
2021-10-14 04:13:11 +13:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-14 01:55:01 +13:00
|
|
|
|
public static Icon GetFileIconWithCache(
|
|
|
|
|
string filePath,
|
|
|
|
|
bool linkOverlay,
|
|
|
|
|
bool updateIconInBackground,
|
|
|
|
|
bool isMainMenu,
|
|
|
|
|
out bool loading,
|
|
|
|
|
string keyPath = "")
|
2021-04-24 21:32:30 +12:00
|
|
|
|
{
|
2021-09-24 08:53:46 +12:00
|
|
|
|
loading = false;
|
2021-04-24 21:32:30 +12:00
|
|
|
|
string extension = Path.GetExtension(filePath);
|
2021-05-02 20:05:33 +12:00
|
|
|
|
IconSize size = IconSize.Small;
|
2021-06-27 01:23:39 +12:00
|
|
|
|
if (Scaling.Factor > 1)
|
|
|
|
|
{
|
|
|
|
|
size = IconSize.Large;
|
|
|
|
|
}
|
2021-04-24 21:32:30 +12:00
|
|
|
|
|
2021-10-06 09:47:47 +13:00
|
|
|
|
string key = filePath;
|
2021-10-14 04:13:11 +13:00
|
|
|
|
if (!string.IsNullOrEmpty(keyPath))
|
|
|
|
|
{
|
|
|
|
|
key = keyPath;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 09:47:47 +13:00
|
|
|
|
if (IsExtensionWithSameIcon(extension))
|
2021-04-24 21:32:30 +12:00
|
|
|
|
{
|
2021-10-06 09:47:47 +13:00
|
|
|
|
key = extension + linkOverlay;
|
2021-04-24 21:32:30 +12:00
|
|
|
|
}
|
2021-10-06 09:47:47 +13:00
|
|
|
|
|
2021-11-14 01:55:01 +13:00
|
|
|
|
if (!DictIconCache(isMainMenu).TryGetValue(key, out Icon icon) &&
|
|
|
|
|
!DictIconCache(!isMainMenu).TryGetValue(key, out icon))
|
2021-04-24 21:32:30 +12:00
|
|
|
|
{
|
2021-10-26 08:45:49 +13:00
|
|
|
|
icon = Resources.StaticResources.LoadingIcon;
|
2021-10-06 09:47:47 +13:00
|
|
|
|
loading = true;
|
2021-09-24 08:53:46 +12:00
|
|
|
|
|
2021-10-06 09:47:47 +13:00
|
|
|
|
if (updateIconInBackground)
|
|
|
|
|
{
|
|
|
|
|
new Thread(UpdateIconInBackground).Start();
|
|
|
|
|
void UpdateIconInBackground()
|
2021-09-24 08:53:46 +12:00
|
|
|
|
{
|
2021-11-14 01:55:01 +13:00
|
|
|
|
DictIconCache(isMainMenu).GetOrAdd(key, GetIcon);
|
2021-09-24 08:53:46 +12:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-30 03:14:36 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Icon GetIcon(string keyExtension)
|
|
|
|
|
{
|
|
|
|
|
return GetFileIconSTA(filePath, linkOverlay, size);
|
2021-04-24 21:32:30 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-16 06:42:02 +13:00
|
|
|
|
static Icon GetFileIconSTA(string filePath, bool linkOverlay, IconSize size = IconSize.Small)
|
|
|
|
|
{
|
|
|
|
|
Icon icon = null;
|
|
|
|
|
|
|
|
|
|
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
|
|
|
|
|
{
|
|
|
|
|
icon = GetFileIcon(filePath, linkOverlay, size);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-11-17 12:13:46 +13:00
|
|
|
|
Thread staThread = new(new ParameterizedThreadStart(StaThreadMethod));
|
2021-10-16 06:42:02 +13:00
|
|
|
|
void StaThreadMethod(object obj)
|
|
|
|
|
{
|
|
|
|
|
icon = GetFileIcon(filePath, linkOverlay, size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
staThread.SetApartmentState(ApartmentState.STA);
|
|
|
|
|
staThread.Start(icon);
|
|
|
|
|
staThread.Join();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-24 21:32:30 +12:00
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-14 01:55:01 +13:00
|
|
|
|
public static Icon GetFolderIconWithCache(
|
|
|
|
|
string path,
|
|
|
|
|
FolderType folderType,
|
|
|
|
|
bool linkOverlay,
|
|
|
|
|
bool updateIconInBackground,
|
|
|
|
|
bool isMainMenu,
|
|
|
|
|
out bool loading)
|
2021-10-14 04:13:11 +13:00
|
|
|
|
{
|
|
|
|
|
loading = false;
|
2021-10-16 06:42:02 +13:00
|
|
|
|
|
|
|
|
|
// always IconSize.Small, because IconSize.Large returns another folder icon than windows explorer
|
2021-10-14 04:13:11 +13:00
|
|
|
|
IconSize size = IconSize.Small;
|
|
|
|
|
|
|
|
|
|
string key = path;
|
|
|
|
|
|
2021-11-14 01:55:01 +13:00
|
|
|
|
if (!DictIconCache(isMainMenu).TryGetValue(key, out Icon icon) &&
|
|
|
|
|
!DictIconCache(!isMainMenu).TryGetValue(key, out icon))
|
2021-10-14 04:13:11 +13:00
|
|
|
|
{
|
2021-10-26 08:45:49 +13:00
|
|
|
|
icon = Resources.StaticResources.LoadingIcon;
|
2021-10-14 04:13:11 +13:00
|
|
|
|
loading = true;
|
|
|
|
|
|
|
|
|
|
if (updateIconInBackground)
|
|
|
|
|
{
|
2021-11-13 20:18:33 +13:00
|
|
|
|
if (MainPreload)
|
2021-10-14 04:13:11 +13:00
|
|
|
|
{
|
2021-11-14 01:55:01 +13:00
|
|
|
|
DictIconCache(isMainMenu).GetOrAdd(key, GetFolder);
|
2021-10-14 04:13:11 +13:00
|
|
|
|
}
|
2021-10-16 06:42:02 +13:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
new Thread(UpdateIconInBackground).Start();
|
|
|
|
|
void UpdateIconInBackground()
|
|
|
|
|
{
|
2021-11-14 01:55:01 +13:00
|
|
|
|
DictIconCache(isMainMenu).GetOrAdd(key, GetFolder);
|
2021-10-16 06:42:02 +13:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-10-14 04:13:11 +13:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Icon GetFolder(string keyExtension)
|
|
|
|
|
{
|
|
|
|
|
return GetFolderIconSTA(path, folderType, linkOverlay, size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-24 21:32:30 +12:00
|
|
|
|
public static Icon GetFolderIconSTA(
|
|
|
|
|
string directoryPath,
|
|
|
|
|
FolderType folderType,
|
|
|
|
|
bool linkOverlay,
|
|
|
|
|
IconSize size = IconSize.Small)
|
|
|
|
|
{
|
|
|
|
|
Icon icon = null;
|
2021-10-14 04:13:11 +13:00
|
|
|
|
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
|
|
|
|
|
{
|
|
|
|
|
icon = GetFolderIcon(
|
|
|
|
|
directoryPath,
|
|
|
|
|
folderType,
|
|
|
|
|
linkOverlay,
|
|
|
|
|
size);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-11-17 12:13:46 +13:00
|
|
|
|
Thread staThread = new(new ParameterizedThreadStart(StaThreadMethod));
|
2021-10-14 04:13:11 +13:00
|
|
|
|
void StaThreadMethod(object obj)
|
|
|
|
|
{
|
|
|
|
|
icon = GetFolderIcon(
|
|
|
|
|
directoryPath,
|
|
|
|
|
folderType,
|
|
|
|
|
linkOverlay,
|
|
|
|
|
size);
|
|
|
|
|
}
|
2021-04-24 21:32:30 +12:00
|
|
|
|
|
2021-10-14 04:13:11 +13:00
|
|
|
|
staThread.SetApartmentState(ApartmentState.STA);
|
|
|
|
|
staThread.Start(icon);
|
|
|
|
|
staThread.Join();
|
|
|
|
|
}
|
2021-04-24 21:32:30 +12:00
|
|
|
|
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Icon GetFolderIcon(
|
|
|
|
|
string directoryPath,
|
|
|
|
|
FolderType folderType,
|
|
|
|
|
bool linkOverlay,
|
|
|
|
|
IconSize size = IconSize.Small)
|
|
|
|
|
{
|
|
|
|
|
Icon icon = null;
|
|
|
|
|
|
|
|
|
|
// Need to add size check, although errors generated at present!
|
|
|
|
|
// uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES;
|
|
|
|
|
|
2021-10-16 06:42:02 +13:00
|
|
|
|
// Removed SHGFI_USEFILEATTRIBUTES, otherwise was wrong folder icon
|
2021-04-24 21:32:30 +12:00
|
|
|
|
uint flags = DllImports.NativeMethods.ShgfiIcon; // | Shell32.SHGFI_USEFILEATTRIBUTES;
|
|
|
|
|
|
|
|
|
|
if (linkOverlay)
|
|
|
|
|
{
|
|
|
|
|
flags += DllImports.NativeMethods.ShgfiLINKOVERLAY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (folderType == FolderType.Open)
|
|
|
|
|
{
|
|
|
|
|
flags += DllImports.NativeMethods.ShgfiOPENICON;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (size == IconSize.Small)
|
|
|
|
|
{
|
|
|
|
|
flags += DllImports.NativeMethods.ShgfiSMALLICON;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
flags += DllImports.NativeMethods.ShgfiLARGEICON;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the folder icon
|
|
|
|
|
DllImports.NativeMethods.SHFILEINFO shfi = default;
|
|
|
|
|
IntPtr success = DllImports.NativeMethods.Shell32SHGetFileInfo(
|
|
|
|
|
directoryPath,
|
|
|
|
|
DllImports.NativeMethods.FileAttributeDirectory,
|
|
|
|
|
ref shfi,
|
|
|
|
|
(uint)Marshal.SizeOf(shfi),
|
|
|
|
|
flags);
|
|
|
|
|
if (success != IntPtr.Zero &&
|
|
|
|
|
shfi.hIcon != IntPtr.Zero)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone();
|
|
|
|
|
DllImports.NativeMethods.User32DestroyIcon(shfi.hIcon);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Log.Error($"directoryPath:'{directoryPath}'", ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Icon AddIconOverlay(Icon originalIcon, Icon overlay)
|
|
|
|
|
{
|
|
|
|
|
Icon icon = null;
|
|
|
|
|
if (originalIcon != null)
|
|
|
|
|
{
|
2021-11-17 12:13:46 +13:00
|
|
|
|
using Bitmap target = new(originalIcon.Width, originalIcon.Height, PixelFormat.Format32bppArgb);
|
2021-10-14 04:13:11 +13:00
|
|
|
|
using Graphics graphics = Graphics.FromImage(target);
|
2021-04-24 21:32:30 +12:00
|
|
|
|
graphics.DrawIcon(originalIcon, 0, 0);
|
2022-01-08 00:40:55 +13:00
|
|
|
|
graphics.DrawIcon(overlay, new(0, 0, originalIcon.Width + 2, originalIcon.Height + 2));
|
2021-04-24 21:32:30 +12:00
|
|
|
|
target.MakeTransparent(target.GetPixel(1, 1));
|
2021-10-14 04:13:11 +13:00
|
|
|
|
IntPtr hIcon = target.GetHicon();
|
|
|
|
|
icon = (Icon)Icon.FromHandle(hIcon).Clone();
|
|
|
|
|
DllImports.NativeMethods.User32DestroyIcon(hIcon);
|
2021-04-24 21:32:30 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-14 01:55:01 +13:00
|
|
|
|
private static ConcurrentDictionary<string, Icon> DictIconCache(bool isMainMenu)
|
2021-10-22 07:25:13 +13:00
|
|
|
|
{
|
2021-11-14 01:55:01 +13:00
|
|
|
|
if (isMainMenu)
|
|
|
|
|
{
|
|
|
|
|
return DictIconCacheMainMenu;
|
|
|
|
|
}
|
|
|
|
|
else
|
2021-10-22 07:25:13 +13:00
|
|
|
|
{
|
2021-11-14 01:55:01 +13:00
|
|
|
|
return DictIconCacheSubMenus;
|
2021-10-22 07:25:13 +13:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 09:47:47 +13:00
|
|
|
|
private static bool IsExtensionWithSameIcon(string fileExtension)
|
2021-04-24 21:32:30 +12:00
|
|
|
|
{
|
2021-10-06 09:47:47 +13:00
|
|
|
|
bool isExtensionWithSameIcon = true;
|
2021-11-17 12:13:46 +13:00
|
|
|
|
List<string> extensionsWithDiffIcons = new() { string.Empty, ".EXE", ".LNK", ".ICO", ".URL" };
|
2021-04-24 21:32:30 +12:00
|
|
|
|
if (extensionsWithDiffIcons.Contains(fileExtension.ToUpperInvariant()))
|
|
|
|
|
{
|
2021-10-06 09:47:47 +13:00
|
|
|
|
isExtensionWithSameIcon = false;
|
2021-04-24 21:32:30 +12:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 09:47:47 +13:00
|
|
|
|
return isExtensionWithSameIcon;
|
2021-04-24 21:32:30 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Icon GetFileIcon(string filePath, bool linkOverlay, IconSize size = IconSize.Small)
|
|
|
|
|
{
|
|
|
|
|
Icon icon = null;
|
|
|
|
|
DllImports.NativeMethods.SHFILEINFO shfi = default;
|
|
|
|
|
uint flags = DllImports.NativeMethods.ShgfiIcon | DllImports.NativeMethods.ShgfiSYSICONINDEX;
|
|
|
|
|
|
|
|
|
|
if (linkOverlay)
|
|
|
|
|
{
|
|
|
|
|
flags += DllImports.NativeMethods.ShgfiLINKOVERLAY;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-16 06:42:02 +13:00
|
|
|
|
// Check the size specified for return.
|
2021-04-24 21:32:30 +12:00
|
|
|
|
if (size == IconSize.Small)
|
|
|
|
|
{
|
|
|
|
|
flags += DllImports.NativeMethods.ShgfiSMALLICON;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
flags += DllImports.NativeMethods.ShgfiLARGEICON;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IntPtr hImageList = DllImports.NativeMethods.Shell32SHGetFileInfo(
|
|
|
|
|
filePath,
|
|
|
|
|
DllImports.NativeMethods.FileAttributeNormal,
|
|
|
|
|
ref shfi,
|
|
|
|
|
(uint)Marshal.SizeOf(shfi),
|
|
|
|
|
flags);
|
|
|
|
|
if (hImageList != IntPtr.Zero)
|
|
|
|
|
{
|
|
|
|
|
IntPtr hIcon;
|
|
|
|
|
if (linkOverlay)
|
|
|
|
|
{
|
2021-10-16 06:42:02 +13:00
|
|
|
|
// Get icon directly
|
|
|
|
|
hIcon = shfi.hIcon;
|
2021-04-24 21:32:30 +12:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Get icon from .ink without overlay
|
|
|
|
|
hIcon = DllImports.NativeMethods.ImageList_GetIcon(hImageList, shfi.iIcon, DllImports.NativeMethods.IldTransparent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
// Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly
|
|
|
|
|
icon = (Icon)Icon.FromHandle(hIcon).Clone();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2021-10-14 07:05:03 +13:00
|
|
|
|
Log.Warn($"filePath:'{filePath}'", ex);
|
2021-04-24 21:32:30 +12:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Cleanup
|
|
|
|
|
if (!linkOverlay)
|
|
|
|
|
{
|
|
|
|
|
DllImports.NativeMethods.User32DestroyIcon(hIcon);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DllImports.NativeMethods.User32DestroyIcon(shfi.hIcon);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|