[Feature] Show icons of *.ico files and links to *.ico files (#396), version 1.2.9.16

This commit is contained in:
Markus Hofknecht 2022-06-09 19:55:13 +02:00
parent e5e1f848e4
commit 532716ea12
9 changed files with 71 additions and 152 deletions

View file

@ -470,7 +470,7 @@ namespace SystemTrayMenu.Business
RowData rowData = ReadRowData(directory, false, true);
rowData.HiddenEntry = hiddenEntry;
string resolvedLnkPath = string.Empty;
rowData.ReadIcon(true, ref resolvedLnkPath, level);
rowData.ReadIconOrResolveLinkAndReadIcon(true, ref resolvedLnkPath, level);
rowData.MenuLevel = level;
menuData.RowDatas.Add(rowData);
}
@ -528,7 +528,7 @@ namespace SystemTrayMenu.Business
}
string resolvedLnkPath = string.Empty;
if (rowData.ReadIcon(false, ref resolvedLnkPath, level))
if (rowData.ReadIconOrResolveLinkAndReadIcon(false, ref resolvedLnkPath, level))
{
rowData = ReadRowData(resolvedLnkPath, true, true, rowData);
rowData.HiddenEntry = hiddenEntry;

View file

@ -19,7 +19,7 @@ namespace SystemTrayMenu
{
private static readonly Icon SystemTrayMenu = Properties.Resources.SystemTrayMenu;
private static readonly Icon IconFromRootFolder = IconReader.GetIconSTA(
Path, false, IconReader.IconSize.Small, IconReader.FolderType.Closed);
Path, Path, false, IconReader.IconSize.Small, IconReader.FolderType.Closed);
private static bool readDarkModeDone;
private static bool isDarkMode;

View file

@ -81,7 +81,7 @@ namespace SystemTrayMenu.DataClasses
row[2] = data;
}
internal bool ReadIcon(bool isDirectory, ref string resolvedLnkPath, int level)
internal bool ReadIconOrResolveLinkAndReadIcon(bool isDirectory, ref string resolvedLnkPath, int level)
{
bool isLnkDirectory = false;
@ -108,7 +108,7 @@ namespace SystemTrayMenu.DataClasses
if (fileExtension.Equals(".lnk", StringComparison.InvariantCultureIgnoreCase))
{
handled = SetLnk(level, ref isLnkDirectory, ref resolvedLnkPath);
handled = ResolveLinkAndReadIcon(level, ref isLnkDirectory, ref resolvedLnkPath);
showOverlay = Properties.Settings.Default.ShowLinkOverlay;
}
else if (fileExtension.Equals(".url", StringComparison.InvariantCultureIgnoreCase))
@ -116,10 +116,6 @@ namespace SystemTrayMenu.DataClasses
SetText($"{FileInfo.Name[0..^4]}");
showOverlay = Properties.Settings.Default.ShowLinkOverlay;
}
else if (fileExtension.Equals(".sln", StringComparison.InvariantCultureIgnoreCase))
{
handled = SetSln(level);
}
else if (fileExtension.Equals(".appref-ms", StringComparison.InvariantCultureIgnoreCase))
{
showOverlay = Properties.Settings.Default.ShowLinkOverlay;
@ -127,21 +123,14 @@ namespace SystemTrayMenu.DataClasses
if (!handled)
{
try
{
FilePathIcon = TargetFilePathOrig;
icon = IconReader.GetFileIconWithCache(
FilePathIcon,
showOverlay,
true,
level == 0,
out bool loading);
IconLoading = loading;
}
catch (Exception ex)
{
Log.Warn($"path:'{TargetFilePathOrig}'", ex);
}
icon = IconReader.GetFileIconWithCache(
TargetFilePathOrig,
TargetFilePath,
showOverlay,
true,
level == 0,
out bool loading);
IconLoading = loading;
}
}
@ -250,20 +239,15 @@ namespace SystemTrayMenu.DataClasses
else
{
bool showOverlay = false;
string fileExtension = Path.GetExtension(TargetFilePath);
string fileExtension = Path.GetExtension(TargetFilePathOrig);
if (fileExtension == ".lnk" || fileExtension == ".url" || fileExtension == ".appref-ms")
{
showOverlay = Properties.Settings.Default.ShowLinkOverlay;
}
string filePath = FilePathIcon;
if (string.IsNullOrEmpty(filePath))
{
filePath = TargetFilePathOrig;
}
icon = IconReader.GetFileIconWithCache(
filePath,
TargetFilePathOrig,
TargetFilePath,
showOverlay,
false,
MenuLevel == 0,
@ -299,7 +283,7 @@ namespace SystemTrayMenu.DataClasses
}
}
private bool SetLnk(int level, ref bool isLnkDirectory, ref string resolvedLnkPath)
private bool ResolveLinkAndReadIcon(int level, ref bool isLnkDirectory, ref string resolvedLnkPath)
{
bool handled = false;
resolvedLnkPath = FileLnk.GetResolvedFileName(TargetFilePath, out bool isFolder);
@ -334,26 +318,5 @@ namespace SystemTrayMenu.DataClasses
return handled;
}
private bool SetSln(int level)
{
bool handled = false;
try
{
icon = IconReader.GetExtractAllIconsLastWithCache(
TargetFilePathOrig,
true,
level == 0,
out bool loading);
IconLoading = loading;
handled = true;
}
catch (Exception ex)
{
Log.Warn($"path:'{TargetFilePath}'", ex);
}
return handled;
}
}
}

View file

@ -39,5 +39,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.9.15")]
[assembly: AssemblyFileVersion("1.2.9.15")]
[assembly: AssemblyVersion("1.2.9.16")]
[assembly: AssemblyFileVersion("1.2.9.16")]

View file

@ -120,6 +120,16 @@ namespace SystemTrayMenu.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>
public static System.Drawing.Icon LinkArrow {
get {
object obj = ResourceManager.GetObject("LinkArrow", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>

View file

@ -112,12 +112,12 @@
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="White50Percentage" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\White50Percentage.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
@ -148,4 +148,7 @@
<data name="ic_fluent_settings_28_regular" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ic_fluent_settings_28_regular.svg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="LinkArrow" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\LinkArrow.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

BIN
Resources/LinkArrow.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -110,10 +110,6 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>ThirdParty\Clearcove.Logging.dll</HintPath>
</Reference>
<Reference Include="TAFactory.IconPack, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>ThirdParty\TAFactory.IconPack.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">

View file

@ -16,7 +16,6 @@ namespace SystemTrayMenu.Utilities
using System.Text;
using System.Threading;
using SystemTrayMenu.DllImports;
using TAFactory.IconPack;
/// <summary>
/// Provides static methods to read system icons for folders and files.
@ -70,80 +69,9 @@ namespace SystemTrayMenu.Utilities
return cleared;
}
public static Icon GetExtractAllIconsLastWithCache(
string filePath,
bool updateIconInBackground,
bool isMainMenu,
out bool loading)
{
bool linkOverlay = false;
loading = false;
string key = filePath;
string extension = Path.GetExtension(filePath);
if (IsExtensionWithSameIcon(extension))
{
key = extension + linkOverlay;
}
if (!DictIconCache(isMainMenu).TryGetValue(key, out Icon icon) &&
!DictIconCache(!isMainMenu).TryGetValue(key, out icon))
{
icon = Resources.StaticResources.LoadingIcon;
loading = true;
if (updateIconInBackground)
{
new Thread(UpdateIconInBackground).Start();
void UpdateIconInBackground()
{
DictIconCache(isMainMenu).GetOrAdd(key, GetExtractAllIconsLastSTA(filePath));
}
}
}
static Icon GetExtractAllIconsLastSTA(string filePath)
{
Icon icon = null;
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
{
icon = GetExtractAllIconsLast(filePath);
}
else
{
Thread staThread = new(new ParameterizedThreadStart(StaThreadMethod));
void StaThreadMethod(object obj)
{
icon = GetExtractAllIconsLast(filePath);
}
staThread.SetApartmentState(ApartmentState.STA);
staThread.Start(icon);
staThread.Join();
}
static Icon GetExtractAllIconsLast(string filePath)
{
StringBuilder executable = new(1024);
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;
}
return icon;
}
public static Icon GetFileIconWithCache(
string filePath,
string pathOrig,
string path,
bool linkOverlay,
bool updateIconInBackground,
bool isMainMenu,
@ -151,10 +79,10 @@ namespace SystemTrayMenu.Utilities
string keyPath = "")
{
loading = false;
string extension = Path.GetExtension(filePath);
string extension = Path.GetExtension(pathOrig);
IconSize size = IconSize.Large;
string key = filePath;
string key = pathOrig;
if (!string.IsNullOrEmpty(keyPath))
{
key = keyPath;
@ -175,7 +103,7 @@ namespace SystemTrayMenu.Utilities
new Thread(UpdateIconInBackground).Start();
void UpdateIconInBackground()
{
DictIconCache(isMainMenu).GetOrAdd(key, GetIconSTA(filePath, linkOverlay, size, null));
DictIconCache(isMainMenu).GetOrAdd(key, GetIconSTA(pathOrig, path, linkOverlay, size, null));
}
}
}
@ -228,25 +156,25 @@ namespace SystemTrayMenu.Utilities
Icon GetFolder(string keyExtension)
{
return GetIconSTA(path, linkOverlay, size, folderType);
return GetIconSTA(path, path, linkOverlay, size, folderType);
}
return icon;
}
public static Icon GetIconSTA(string path, bool linkOverlay, IconSize size, FolderType? folderType)
public static Icon GetIconSTA(string pathOrig, string path, bool linkOverlay, IconSize size, FolderType? folderType)
{
Icon icon = null;
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
{
icon = GetIcon(path, linkOverlay, size, folderType);
icon = GetIcon(pathOrig, path, linkOverlay, size, folderType);
}
else
{
Thread staThread = new(new ParameterizedThreadStart(StaThreadMethod));
void StaThreadMethod(object obj)
{
icon = GetIcon(path, linkOverlay, size, folderType);
icon = GetIcon(pathOrig, path, linkOverlay, size, folderType);
}
staThread.SetApartmentState(ApartmentState.STA);
@ -299,15 +227,34 @@ namespace SystemTrayMenu.Utilities
return isExtensionWithSameIcon;
}
private static Icon GetIcon(string path, bool linkOverlay, IconSize size, FolderType? type)
private static Icon GetIcon(string path, string pathOrig, bool linkOverlay, IconSize size, FolderType? type)
{
NativeMethods.SHFILEINFO shFileInfo = default;
uint flags = GetFlags(linkOverlay, size, type);
uint attribute = type == null ? NativeMethods.FileAttributeNormal :
NativeMethods.FileAttributeDirectory;
IntPtr imageList = NativeMethods.Shell32SHGetFileInfo(
path, attribute, ref shFileInfo, (uint)Marshal.SizeOf(shFileInfo), flags);
return GetIcon(path, linkOverlay, shFileInfo, imageList);
Icon icon;
if (Path.GetExtension(path).Equals(".ico", StringComparison.InvariantCultureIgnoreCase))
{
icon = Icon.ExtractAssociatedIcon(path);
}
else if (Path.GetExtension(pathOrig).Equals(".ico", StringComparison.InvariantCultureIgnoreCase) &&
File.Exists(pathOrig))
{
icon = Icon.ExtractAssociatedIcon(pathOrig);
if (linkOverlay)
{
icon = AddIconOverlay(icon, Properties.Resources.LinkArrow);
}
}
else
{
NativeMethods.SHFILEINFO shFileInfo = default;
uint flags = GetFlags(linkOverlay, size, type);
uint attribute = type == null ? NativeMethods.FileAttributeNormal :
NativeMethods.FileAttributeDirectory;
IntPtr imageList = NativeMethods.Shell32SHGetFileInfo(
path, attribute, ref shFileInfo, (uint)Marshal.SizeOf(shFileInfo), flags);
icon = GetIcon(path, linkOverlay, shFileInfo, imageList);
}
return icon;
}
private static uint GetFlags(bool linkOverlay, IconSize size, FolderType? folderType)