mirror of
https://github.com/Hofknecht/SystemTrayMenu.git
synced 2024-05-19 11:53:02 +12:00
Revert "[Feature] Read icons from system cache (#149), version 1.0.17.17", version 1.0.17.19
This reverts commitecebddb0cb
. This reverts commit010af66b42
.
This commit is contained in:
parent
903322eaa1
commit
a175d6a718
|
@ -113,7 +113,10 @@ namespace SystemTrayMenu.DataClasses
|
||||||
}
|
}
|
||||||
else if (isDirectory)
|
else if (isDirectory)
|
||||||
{
|
{
|
||||||
icon = IconReader.GetFolderIconSTA(TargetFilePath);
|
icon = IconReader.GetFolderIconSTA(
|
||||||
|
TargetFilePath,
|
||||||
|
IconReader.FolderType.Closed,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -139,8 +142,20 @@ namespace SystemTrayMenu.DataClasses
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
icon = IconReader.GetFileIconWithCache(TargetFilePath);
|
icon = IconReader.GetFileIconWithCache(TargetFilePath, false);
|
||||||
diposeIcon = false;
|
diposeIcon = false;
|
||||||
|
|
||||||
|
// other project -> fails sometimes
|
||||||
|
// icon = IconHelper.ExtractIcon(TargetFilePath, 0);
|
||||||
|
|
||||||
|
// standard way -> fails sometimes
|
||||||
|
// icon = Icon.ExtractAssociatedIcon(filePath);
|
||||||
|
|
||||||
|
// API Code Pack -> fails sometimes
|
||||||
|
// ShellFile shellFile = ShellFile.FromFilePath(filePath);
|
||||||
|
// Bitmap shellThumb = shellFile.Thumbnail.ExtraLargeBitmap;
|
||||||
|
|
||||||
|
// IShellItemImageFactory GetImage works, but missing link overlay there #149
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -265,7 +280,7 @@ namespace SystemTrayMenu.DataClasses
|
||||||
resolvedLnkPath = FileLnk.GetResolvedFileName(TargetFilePath);
|
resolvedLnkPath = FileLnk.GetResolvedFileName(TargetFilePath);
|
||||||
if (FileLnk.IsDirectory(resolvedLnkPath))
|
if (FileLnk.IsDirectory(resolvedLnkPath))
|
||||||
{
|
{
|
||||||
icon = IconReader.GetFolderIconSTA(TargetFilePath);
|
icon = IconReader.GetFolderIconSTA(TargetFilePath, IconReader.FolderType.Open, true);
|
||||||
handled = true;
|
handled = true;
|
||||||
isLnkDirectory = true;
|
isLnkDirectory = true;
|
||||||
}
|
}
|
||||||
|
@ -328,7 +343,7 @@ namespace SystemTrayMenu.DataClasses
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
icon = IconReader.GetFileIconWithCache(browserPath);
|
icon = IconReader.GetFileIconWithCache(browserPath, false);
|
||||||
diposeIcon = false;
|
diposeIcon = false;
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
// <copyright file="DeleteObject.cs" company="PlaceholderCompany">
|
|
||||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
|
|
||||||
namespace SystemTrayMenu.DllImports
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// wraps the methodcalls to native windows dll's.
|
|
||||||
/// </summary>
|
|
||||||
public static partial class NativeMethods
|
|
||||||
{
|
|
||||||
internal static bool Gdi32DeleteObject(IntPtr hObject)
|
|
||||||
{
|
|
||||||
return DeleteObject(hObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
||||||
private static extern bool DeleteObject(IntPtr hObject);
|
|
||||||
}
|
|
||||||
}
|
|
50
NativeDllImport/GetIcon.cs
Normal file
50
NativeDllImport/GetIcon.cs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// <copyright file="GetIcon.cs" company="PlaceholderCompany">
|
||||||
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
namespace SystemTrayMenu.DllImports
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// wraps the methodcalls to native windows dll's.
|
||||||
|
/// </summary>
|
||||||
|
public static partial class NativeMethods
|
||||||
|
{
|
||||||
|
#pragma warning disable SA1600 // Elements should be documented
|
||||||
|
public const uint ShgfiIcon = 0x000000100; // get icon
|
||||||
|
public const uint ShgfiSYSICONINDEX = 0x000004000; // get system icon index
|
||||||
|
public const uint ShgfiLINKOVERLAY = 0x000008000; // put a link overlay on icon
|
||||||
|
public const uint ShgfiLARGEICON = 0x000000000; // get large icon
|
||||||
|
public const uint ShgfiSMALLICON = 0x000000001; // get small icon
|
||||||
|
public const uint ShgfiOPENICON = 0x000000002; // get open icon
|
||||||
|
public const uint FileAttributeDirectory = 0x00000010;
|
||||||
|
public const uint FileAttributeNormal = 0x00000080;
|
||||||
|
public const int IldTransparent = 0x00000001;
|
||||||
|
#pragma warning restore SA1600 // Elements should be documented
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// comctl32 ImageList_GetIcon(IntPtr hIcon).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hIcon">hIcon.</param>
|
||||||
|
public static void Comctl32ImageListGetIcon(IntPtr hIcon)
|
||||||
|
{
|
||||||
|
_ = DestroyIcon(hIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// comctl32 ImageList_GetIcon(IntPtr himl, int i, int flags).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="himl">himl.</param>
|
||||||
|
/// <param name="i">i.</param>
|
||||||
|
/// <param name="flags">flags.</param>
|
||||||
|
/// <returns>IntPtr.</returns>
|
||||||
|
[DllImport("comctl32", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||||
|
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
|
||||||
|
internal static extern IntPtr ImageList_GetIcon(
|
||||||
|
IntPtr himl,
|
||||||
|
int i,
|
||||||
|
int flags);
|
||||||
|
}
|
||||||
|
}
|
25
NativeDllImport/GetMenuDefaultItem.cs
Normal file
25
NativeDllImport/GetMenuDefaultItem.cs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// <copyright file="GetMenuDefaultItem.cs" company="PlaceholderCompany">
|
||||||
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
namespace SystemTrayMenu.DllImports
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// wraps the methodcalls to native windows dll's.
|
||||||
|
/// </summary>
|
||||||
|
public static partial class NativeMethods
|
||||||
|
{
|
||||||
|
public static int User32GetMenuDefaultItem(IntPtr hMenu, bool fByPos, uint gmdiFlags)
|
||||||
|
{
|
||||||
|
return GetMenuDefaultItem(hMenu, fByPos, gmdiFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determines the default menu item on the specified menu
|
||||||
|
[DllImport("user32", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||||
|
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
|
||||||
|
private static extern int GetMenuDefaultItem(IntPtr hMenu, bool fByPos, uint gmdiFlags);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
// <copyright file="IShellItem.cs" company="PlaceholderCompany">
|
|
||||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
|
|
||||||
namespace SystemTrayMenu.DllImports
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[ComImport]
|
|
||||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
||||||
[Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")]
|
|
||||||
public interface IShellItem
|
|
||||||
{
|
|
||||||
void BindToHandler(
|
|
||||||
IntPtr pbc,
|
|
||||||
[MarshalAs(UnmanagedType.LPStruct)] Guid bhid,
|
|
||||||
[MarshalAs(UnmanagedType.LPStruct)] Guid riid,
|
|
||||||
out IntPtr ppv);
|
|
||||||
|
|
||||||
void GetParent(out IShellItem ppsi);
|
|
||||||
|
|
||||||
void GetDisplayName(SIGDN sigdnName, out IntPtr ppszName);
|
|
||||||
|
|
||||||
void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);
|
|
||||||
|
|
||||||
void Compare(IShellItem psi, uint hint, out int piOrder);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
// <copyright file="IShellItemImageFactory.cs" company="PlaceholderCompany">
|
|
||||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
|
|
||||||
namespace SystemTrayMenu.DllImports
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[ComImport]
|
|
||||||
[Guid("bcc18b79-ba16-442f-80c4-8a59c30c463b")]
|
|
||||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
||||||
public interface IShellItemImageFactory
|
|
||||||
{
|
|
||||||
void GetImage(
|
|
||||||
[In, MarshalAs(UnmanagedType.Struct)] SIZE size,
|
|
||||||
[In] SIIGBF flags,
|
|
||||||
[Out] out IntPtr phbm);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
// <copyright file="SHCreateItemFromParsingName.cs" company="PlaceholderCompany">
|
|
||||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
|
|
||||||
namespace SystemTrayMenu.DllImports
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// wraps the methodcalls to native windows dll's.
|
|
||||||
/// </summary>
|
|
||||||
public static partial class NativeMethods
|
|
||||||
{
|
|
||||||
[DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
|
|
||||||
internal static extern void SHCreateItemFromParsingName(
|
|
||||||
[In][MarshalAs(UnmanagedType.LPWStr)] string pszPath,
|
|
||||||
[In] IntPtr pbc,
|
|
||||||
[In][MarshalAs(UnmanagedType.LPStruct)] Guid riid,
|
|
||||||
[Out][MarshalAs(UnmanagedType.Interface, IidParameterIndex = 2)] out IShellItem ppv);
|
|
||||||
}
|
|
||||||
}
|
|
55
NativeDllImport/SHGetFileInfo.cs
Normal file
55
NativeDllImport/SHGetFileInfo.cs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
// <copyright file="SHGetFileInfo.cs" company="PlaceholderCompany">
|
||||||
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
namespace SystemTrayMenu.DllImports
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// wraps the methodcalls to native windows dll's.
|
||||||
|
/// </summary>
|
||||||
|
public static partial class NativeMethods
|
||||||
|
{
|
||||||
|
private const int maxPath = 256;
|
||||||
|
|
||||||
|
internal static IntPtr Shell32SHGetFileInfo(
|
||||||
|
string pszPath,
|
||||||
|
uint dwFileAttributes,
|
||||||
|
ref SHFILEINFO psfi,
|
||||||
|
uint cbFileInfo,
|
||||||
|
uint uFlags)
|
||||||
|
{
|
||||||
|
return SHGetFileInfo(
|
||||||
|
pszPath,
|
||||||
|
dwFileAttributes,
|
||||||
|
ref psfi,
|
||||||
|
cbFileInfo,
|
||||||
|
uFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||||
|
[DefaultDllImportSearchPaths(DllImportSearchPath.UserDirectories)]
|
||||||
|
private static extern IntPtr SHGetFileInfo(
|
||||||
|
string pszPath,
|
||||||
|
uint dwFileAttributes,
|
||||||
|
ref SHFILEINFO psfi,
|
||||||
|
uint cbFileInfo,
|
||||||
|
uint uFlags);
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||||
|
|
||||||
|
internal struct SHFILEINFO
|
||||||
|
{
|
||||||
|
public const int NAMESIZE = 80;
|
||||||
|
public IntPtr hIcon;
|
||||||
|
public int iIcon;
|
||||||
|
public uint dwAttributes;
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = maxPath)]
|
||||||
|
public string szDisplayName;
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NAMESIZE)]
|
||||||
|
public string szTypeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
// <copyright file="SIGDN.cs" company="PlaceholderCompany">
|
|
||||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
|
|
||||||
namespace SystemTrayMenu.DllImports
|
|
||||||
{
|
|
||||||
public enum SIGDN : uint
|
|
||||||
{
|
|
||||||
NORMALDISPLAY = 0,
|
|
||||||
PARENTRELATIVEPARSING = 0x80018001,
|
|
||||||
PARENTRELATIVEFORADDRESSBAR = 0x8001c001,
|
|
||||||
DESKTOPABSOLUTEPARSING = 0x80028000,
|
|
||||||
PARENTRELATIVEEDITING = 0x80031001,
|
|
||||||
DESKTOPABSOLUTEEDITING = 0x8004c000,
|
|
||||||
FILESYSPATH = 0x80058000,
|
|
||||||
URL = 0x80068000,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
// <copyright file="SIIGBF.cs" company="PlaceholderCompany">
|
|
||||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
|
|
||||||
namespace SystemTrayMenu.DllImports
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
public enum SIIGBF
|
|
||||||
{
|
|
||||||
SIIGBF_RESIZETOFIT = 0x00,
|
|
||||||
SIIGBF_BIGGERSIZEOK = 0x01,
|
|
||||||
SIIGBF_MEMORYONLY = 0x02,
|
|
||||||
SIIGBF_ICONONLY = 0x04,
|
|
||||||
SIIGBF_THUMBNAILONLY = 0x08,
|
|
||||||
SIIGBF_INCACHEONLY = 0x10,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
// <copyright file="SIZE.cs" company="PlaceholderCompany">
|
|
||||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
|
|
||||||
namespace SystemTrayMenu.DllImports
|
|
||||||
{
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
|
||||||
public struct SIZE
|
|
||||||
{
|
|
||||||
public int Cx;
|
|
||||||
public int Cy;
|
|
||||||
|
|
||||||
public SIZE(int cx, int cy)
|
|
||||||
{
|
|
||||||
Cx = cx;
|
|
||||||
Cy = cy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -39,5 +39,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.0.17.18")]
|
[assembly: AssemblyVersion("1.0.17.19")]
|
||||||
[assembly: AssemblyFileVersion("1.0.17.18")]
|
[assembly: AssemblyFileVersion("1.0.17.19")]
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
namespace SystemTrayMenu.Utilities
|
namespace SystemTrayMenu.Utilities
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
public class FileIni
|
public class FileIni
|
||||||
|
@ -13,7 +14,7 @@ namespace SystemTrayMenu.Utilities
|
||||||
|
|
||||||
public FileIni(string path)
|
public FileIni(string path)
|
||||||
{
|
{
|
||||||
values = System.IO.File.ReadLines(path)
|
values = File.ReadLines(path)
|
||||||
.Where(line => !string.IsNullOrWhiteSpace(line) &&
|
.Where(line => !string.IsNullOrWhiteSpace(line) &&
|
||||||
!line.StartsWith("#", System.StringComparison.InvariantCulture))
|
!line.StartsWith("#", System.StringComparison.InvariantCulture))
|
||||||
.Select(line => line.Split(new char[] { '=' }, 2, 0))
|
.Select(line => line.Split(new char[] { '=' }, 2, 0))
|
|
@ -52,7 +52,7 @@ namespace SystemTrayMenu.Utilities
|
||||||
|
|
||||||
public static bool IsNetworkRoot(string path)
|
public static bool IsNetworkRoot(string path)
|
||||||
{
|
{
|
||||||
return !File.Exists(path) &&
|
return !System.IO.File.Exists(path) &&
|
||||||
path.StartsWith(@"\\", StringComparison.InvariantCulture) &&
|
path.StartsWith(@"\\", StringComparison.InvariantCulture) &&
|
||||||
!path.Substring(2).Contains(@"\", StringComparison.InvariantCulture);
|
!path.Substring(2).Contains(@"\", StringComparison.InvariantCulture);
|
||||||
}
|
}
|
257
Utilities/File/IconReader.cs
Normal file
257
Utilities/File/IconReader.cs
Normal file
|
@ -0,0 +1,257 @@
|
||||||
|
// <copyright file="IconReader.cs" company="PlaceholderCompany">
|
||||||
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
|
||||||
|
namespace SystemTrayMenu.Utilities
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
// from https://www.codeproject.com/Articles/2532/Obtaining-and-managing-file-and-folder-icons-using
|
||||||
|
// added ImageList_GetIcon, IconCache, AddIconOverlay
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides static methods to read system icons for both folders and files.
|
||||||
|
/// </summary>
|
||||||
|
/// <example>
|
||||||
|
/// <code>IconReader.GetFileIcon("c:\\general.xls");</code>
|
||||||
|
/// </example>
|
||||||
|
public static class IconReader
|
||||||
|
{
|
||||||
|
private static readonly ConcurrentDictionary<string, Icon> DictIconCache = new ConcurrentDictionary<string, Icon>();
|
||||||
|
|
||||||
|
// private static readonly object ReadIcon = new object();
|
||||||
|
public enum IconSize
|
||||||
|
{
|
||||||
|
Large = 0, // 32x32 pixels
|
||||||
|
Small = 1, // 16x16 pixels
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum FolderType
|
||||||
|
{
|
||||||
|
Open = 0,
|
||||||
|
Closed = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Dispose()
|
||||||
|
{
|
||||||
|
foreach (Icon icon in DictIconCache.Values)
|
||||||
|
{
|
||||||
|
icon?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Icon GetFileIconWithCache(string filePath, bool linkOverlay, IconSize size = IconSize.Small)
|
||||||
|
{
|
||||||
|
Icon icon = null;
|
||||||
|
string extension = Path.GetExtension(filePath);
|
||||||
|
|
||||||
|
if (IsExtensionWitSameIcon(extension))
|
||||||
|
{
|
||||||
|
icon = DictIconCache.GetOrAdd(extension, GetIcon);
|
||||||
|
Icon GetIcon(string keyExtension)
|
||||||
|
{
|
||||||
|
return GetFileIconSTA(filePath, linkOverlay, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
icon = GetFileIconSTA(filePath, linkOverlay, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2008:Do not create tasks without passing a TaskScheduler", Justification = "todo")]
|
||||||
|
public static Icon GetFolderIconSTA(
|
||||||
|
string directoryPath,
|
||||||
|
FolderType folderType,
|
||||||
|
bool linkOverlay,
|
||||||
|
IconSize size = IconSize.Small)
|
||||||
|
{
|
||||||
|
Icon icon = null;
|
||||||
|
|
||||||
|
Task<Icon> task = Task.Factory.StartNew(() => GetFolderIcon(
|
||||||
|
directoryPath,
|
||||||
|
folderType,
|
||||||
|
linkOverlay,
|
||||||
|
size));
|
||||||
|
icon = task.Result;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// MH: Removed SHGFI_USEFILEATTRIBUTES, otherwise was wrong folder icon
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#pragma warning disable CA1031 // Do not catch general exception types
|
||||||
|
catch (Exception ex)
|
||||||
|
#pragma warning restore CA1031 // Do not catch general exception types
|
||||||
|
{
|
||||||
|
Log.Error($"directoryPath:'{directoryPath}'", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Icon AddIconOverlay(Icon originalIcon, Icon overlay)
|
||||||
|
{
|
||||||
|
Icon icon = null;
|
||||||
|
if (originalIcon != null)
|
||||||
|
{
|
||||||
|
using Bitmap target = new Bitmap(
|
||||||
|
originalIcon.Width,
|
||||||
|
originalIcon.Height,
|
||||||
|
PixelFormat.Format32bppArgb);
|
||||||
|
Graphics graphics = Graphics.FromImage(target);
|
||||||
|
graphics.DrawIcon(originalIcon, 0, 0);
|
||||||
|
graphics.DrawIcon(overlay, 0, 0);
|
||||||
|
target.MakeTransparent(target.GetPixel(1, 1));
|
||||||
|
icon = Icon.FromHandle(target.GetHicon());
|
||||||
|
}
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsExtensionWitSameIcon(string fileExtension)
|
||||||
|
{
|
||||||
|
bool isExtensionWitSameIcon = true;
|
||||||
|
List<string> extensionsWithDiffIcons = new List<string>
|
||||||
|
{ string.Empty, ".EXE", ".LNK", ".ICO", ".URL" };
|
||||||
|
if (extensionsWithDiffIcons.Contains(fileExtension.ToUpperInvariant()))
|
||||||
|
{
|
||||||
|
isExtensionWitSameIcon = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isExtensionWitSameIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2008:Do not create tasks without passing a TaskScheduler", Justification = "todo")]
|
||||||
|
private static Icon GetFileIconSTA(string filePath, bool linkOverlay, IconSize size = IconSize.Small)
|
||||||
|
{
|
||||||
|
Icon icon = null;
|
||||||
|
|
||||||
|
Task<Icon> task = Task.Factory.StartNew(() => GetFileIcon(filePath, linkOverlay, size));
|
||||||
|
icon = task.Result;
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the size specified for return. */
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
hIcon = shfi.hIcon; // Get icon directly
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
#pragma warning disable CA1031 // Do not catch general exception types
|
||||||
|
catch (Exception ex)
|
||||||
|
#pragma warning restore CA1031 // Do not catch general exception types
|
||||||
|
{
|
||||||
|
Log.Error($"filePath:'{filePath}'", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
if (!linkOverlay)
|
||||||
|
{
|
||||||
|
DllImports.NativeMethods.User32DestroyIcon(hIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
DllImports.NativeMethods.User32DestroyIcon(shfi.hIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,100 +0,0 @@
|
||||||
// <copyright file="IconReader.cs" company="PlaceholderCompany">
|
|
||||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
|
|
||||||
namespace SystemTrayMenu.Utilities
|
|
||||||
{
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Drawing.Imaging;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
// from https://www.codeproject.com/Articles/2532/Obtaining-and-managing-file-and-folder-icons-using
|
|
||||||
// added ImageList_GetIcon, IconCache, AddIconOverlay
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides static methods to read system icons for both folders and files.
|
|
||||||
/// </summary>
|
|
||||||
/// <example>
|
|
||||||
/// <code>IconReader.GetFileIcon("c:\\general.xls");</code>
|
|
||||||
/// </example>
|
|
||||||
public static class IconReader
|
|
||||||
{
|
|
||||||
private static readonly ConcurrentDictionary<string, Icon> DictIconCache = new ConcurrentDictionary<string, Icon>();
|
|
||||||
|
|
||||||
public static void Dispose()
|
|
||||||
{
|
|
||||||
foreach (Icon icon in DictIconCache.Values)
|
|
||||||
{
|
|
||||||
icon?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Icon GetFileIconWithCache(string filePath)
|
|
||||||
{
|
|
||||||
Icon icon = null;
|
|
||||||
string extension = Path.GetExtension(filePath);
|
|
||||||
|
|
||||||
if (IsExtensionWitSameIcon(extension))
|
|
||||||
{
|
|
||||||
icon = DictIconCache.GetOrAdd(extension, GetIcon);
|
|
||||||
Icon GetIcon(string keyExtension)
|
|
||||||
{
|
|
||||||
return GetFileIconSTA(filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
icon = GetFileIconSTA(filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Icon GetFolderIconSTA(string directoryPath)
|
|
||||||
{
|
|
||||||
Task<Icon> task = Task.Factory.StartNew(() => IconsFromSystemCache.GetIcon(directoryPath));
|
|
||||||
return task.Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Icon AddIconOverlay(Icon originalIcon, Icon overlay)
|
|
||||||
{
|
|
||||||
Icon icon = null;
|
|
||||||
if (originalIcon != null)
|
|
||||||
{
|
|
||||||
using Bitmap target = new Bitmap(
|
|
||||||
originalIcon.Width,
|
|
||||||
originalIcon.Height,
|
|
||||||
PixelFormat.Format32bppArgb);
|
|
||||||
Graphics graphics = Graphics.FromImage(target);
|
|
||||||
graphics.DrawIcon(originalIcon, 0, 0);
|
|
||||||
graphics.DrawIcon(overlay, 0, 0);
|
|
||||||
target.MakeTransparent(target.GetPixel(1, 1));
|
|
||||||
icon = Icon.FromHandle(target.GetHicon());
|
|
||||||
}
|
|
||||||
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsExtensionWitSameIcon(string fileExtension)
|
|
||||||
{
|
|
||||||
bool isExtensionWitSameIcon = true;
|
|
||||||
List<string> extensionsWithDiffIcons = new List<string>
|
|
||||||
{ string.Empty, ".EXE", ".LNK", ".ICO", ".URL" };
|
|
||||||
if (extensionsWithDiffIcons.Contains(fileExtension.ToUpperInvariant()))
|
|
||||||
{
|
|
||||||
isExtensionWitSameIcon = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isExtensionWitSameIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Icon GetFileIconSTA(string filePath)
|
|
||||||
{
|
|
||||||
Task<Icon> task = Task.Factory.StartNew(() => IconsFromSystemCache.GetIcon(filePath));
|
|
||||||
return task.Result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,127 +0,0 @@
|
||||||
// <copyright file="IconsFromSystemCache.cs" company="PlaceholderCompany">
|
|
||||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
||||||
// </copyright>
|
|
||||||
|
|
||||||
namespace SystemTrayMenu.Utilities
|
|
||||||
{
|
|
||||||
using System;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Drawing.Imaging;
|
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using SystemTrayMenu.DllImports;
|
|
||||||
|
|
||||||
public static partial class IconsFromSystemCache
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Get Icon from system cache.
|
|
||||||
/// http://pinvoke.net/default.aspx/Interfaces/IShellItem.html?diff=y.
|
|
||||||
/// https://github.com/Hofknecht/SystemTrayMenu/issues/149.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="filename">filename.</param>
|
|
||||||
/// <returns>Icon.</returns>
|
|
||||||
public static Icon GetIcon(string filename)
|
|
||||||
{
|
|
||||||
Icon icon = null;
|
|
||||||
|
|
||||||
// GUID of IShellItem.
|
|
||||||
Guid uuid = new Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
NativeMethods.SHCreateItemFromParsingName(filename, IntPtr.Zero, uuid, out IShellItem ppsi);
|
|
||||||
IntPtr hbitmap = IntPtr.Zero;
|
|
||||||
((IShellItemImageFactory)ppsi).GetImage(new SIZE(16, 16), SIIGBF.SIIGBF_ICONONLY, out hbitmap);
|
|
||||||
|
|
||||||
Bitmap bitmap = GetBitmapFromHBitmap(hbitmap);
|
|
||||||
NativeMethods.Gdi32DeleteObject(hbitmap);
|
|
||||||
bitmap.MakeTransparent();
|
|
||||||
IntPtr icH = bitmap.GetHicon();
|
|
||||||
|
|
||||||
icon = (Icon)Icon.FromHandle(icH).Clone();
|
|
||||||
NativeMethods.User32DestroyIcon(icH);
|
|
||||||
}
|
|
||||||
#pragma warning disable CA1031 // Do not catch general exception types
|
|
||||||
catch (Exception ex)
|
|
||||||
#pragma warning restore CA1031 // Do not catch general exception types
|
|
||||||
{
|
|
||||||
if (ex is FileNotFoundException)
|
|
||||||
{
|
|
||||||
Log.Warn($"filename:'{filename}'", ex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Error($"filename:'{filename}'", ex);
|
|
||||||
|
|
||||||
// throw; // comment in to remove CA1031
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Preserving Alpha channel
|
|
||||||
/// https://stackoverflow.com/questions/4627376/use-native-hbitmap-in-c-sharp-while-preserving-alpha-channel-transparency/9291151#9291151.
|
|
||||||
/// (when using "Bitmap image = Image.FromHbitmap(hbitmap);" alpha channel lost).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="nativeHBitmap">nativeHBitmap.</param>
|
|
||||||
/// <returns>Bitmap.</returns>
|
|
||||||
private static Bitmap GetBitmapFromHBitmap(IntPtr nativeHBitmap)
|
|
||||||
{
|
|
||||||
Bitmap bmp = Image.FromHbitmap(nativeHBitmap);
|
|
||||||
|
|
||||||
if (Image.GetPixelFormatSize(bmp.PixelFormat) < 32)
|
|
||||||
{
|
|
||||||
return bmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsAlphaBitmap(bmp, out BitmapData bmpData))
|
|
||||||
{
|
|
||||||
return GetlAlphaBitmapFromBitmapData(bmpData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return bmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Bitmap GetlAlphaBitmapFromBitmapData(BitmapData bmpData)
|
|
||||||
{
|
|
||||||
return new Bitmap(
|
|
||||||
bmpData.Width,
|
|
||||||
bmpData.Height,
|
|
||||||
bmpData.Stride,
|
|
||||||
PixelFormat.Format32bppArgb,
|
|
||||||
bmpData.Scan0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsAlphaBitmap(Bitmap bmp, out BitmapData bmpData)
|
|
||||||
{
|
|
||||||
Rectangle bmBounds = new Rectangle(0, 0, bmp.Width, bmp.Height);
|
|
||||||
|
|
||||||
bmpData = bmp.LockBits(bmBounds, ImageLockMode.ReadOnly, bmp.PixelFormat);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (int y = 0; y <= bmpData.Height - 1; y++)
|
|
||||||
{
|
|
||||||
for (int x = 0; x <= bmpData.Width - 1; x++)
|
|
||||||
{
|
|
||||||
Color pixelColor = Color.FromArgb(
|
|
||||||
Marshal.ReadInt32(bmpData.Scan0, (bmpData.Stride * y) + (4 * x)));
|
|
||||||
|
|
||||||
if (pixelColor.A > 0 & pixelColor.A < 255)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
bmp.UnlockBits(bmpData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue