From 532716ea121dbca47818c2186c589f19c4f94452 Mon Sep 17 00:00:00 2001 From: Markus Hofknecht Date: Thu, 9 Jun 2022 19:55:13 +0200 Subject: [PATCH] [Feature] Show icons of *.ico files and links to *.ico files (#396), version 1.2.9.16 --- Business/Menus.cs | 4 +- Config/Config.cs | 2 +- DataClasses/RowData.cs | 65 ++++------------ Properties/AssemblyInfo.cs | 4 +- Properties/Resources.Designer.cs | 10 +++ Properties/Resources.resx | 9 ++- Resources/LinkArrow.ico | Bin 0 -> 30678 bytes SystemTrayMenu.csproj | 4 - Utilities/File/IconReader.cs | 125 +++++++++---------------------- 9 files changed, 71 insertions(+), 152 deletions(-) create mode 100644 Resources/LinkArrow.ico diff --git a/Business/Menus.cs b/Business/Menus.cs index a40ddad..b5aa405 100644 --- a/Business/Menus.cs +++ b/Business/Menus.cs @@ -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; diff --git a/Config/Config.cs b/Config/Config.cs index 4ea5bd3..22efa26 100644 --- a/Config/Config.cs +++ b/Config/Config.cs @@ -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; diff --git a/DataClasses/RowData.cs b/DataClasses/RowData.cs index 4dc2673..d130c4e 100644 --- a/DataClasses/RowData.cs +++ b/DataClasses/RowData.cs @@ -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; - } } } diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 7ad9b8d..1b3c73e 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -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")] diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs index 3059eaf..79f4986 100644 --- a/Properties/Resources.Designer.cs +++ b/Properties/Resources.Designer.cs @@ -120,6 +120,16 @@ namespace SystemTrayMenu.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + public static System.Drawing.Icon LinkArrow { + get { + object obj = ResourceManager.GetObject("LinkArrow", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). /// diff --git a/Properties/Resources.resx b/Properties/Resources.resx index f576e12..4b3f22f 100644 --- a/Properties/Resources.resx +++ b/Properties/Resources.resx @@ -112,12 +112,12 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + ..\Resources\White50Percentage.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a @@ -148,4 +148,7 @@ ..\Resources\ic_fluent_settings_28_regular.svg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\LinkArrow.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/Resources/LinkArrow.ico b/Resources/LinkArrow.ico new file mode 100644 index 0000000000000000000000000000000000000000..faa4e6403a0af0d7a7b53862e155704eb741107a GIT binary patch literal 30678 zcmeI&Ur)HG{q#02A^w+71iCm{c1 zEFraWtVjj4d@@P)FS|>!|5!lSW%>Ky%;|UTa;}%<-eniIseAY6eEHqE?5@|(J@?$- zy?Z6;3Gug}KoUQnk@`N7q^BiGdR9cNlDb83J^raaE=jkZibY-_et0|{aJwmPvFrwy z3*&;};b9mV83B(6L$ASc_3QAp7^jos1cw9T0EgWHb|rSPYzLdw2393juv)AzG&Cd! z-$UDH)Nypw3kwSiO6KS1L7lm|IiSqW&H^PGjRIw6W(L%WL?S>5hr^)G^z<}PrlzJK zKKNRT#bS6@uh$EUi;IdY8mnD#nOt#1*XT?H+=IWvoy*NIG;me+RlDLcx#FmH#bt8E z(d@3t*hZr>aIg0wG#$=|>cZ!sX3r)Vy#9S!>(*@bimr)l!w)B*=ZiAgvZnBPz&Cz#b$%QpOQ96CSUDO-{$j(4whrM=&p$JHm-Db*{D%DGJR*Pm)Wg0I9eAD>a% zpNgy8chhh#GmERwr|n90Yw7<1zJ51LWYell21ey`8qE>XVTZSYhBA65N+4%YGMr?5(;B^=sPevW}`apOh2n{7UP`fuvH+4l@ zz|wbFzK%%6HX^PK^sXInJznD))swbc&o$t>5B2-9p>FSH-PDTTHI=;pe%DaawgHbF z2F`z}^aeccDL5C9U2W!deQ^H{)E8~mOr2P-PRpT}z~>xX(>6HbfVN|=!OyiP6xaB= zjk(%QP_KT?`Kw=?>l^lM6|P$}gFQf<)+0L-+K&D0gpT8H$nW{3u6%{7+7{1qHk+wD!^(mu{daer# z^U!hZRZ+9qDFto)&cBqN5PC2Sogcow;xouq%Qog}{QIwZu6Vum$AxNWEY40j?ML%v z+t8>Bx;}pM@%zO-Y82_MKe^(54fX*F&e8B5xKZnrwmXsQgx3wtrFn2x*ruAcLoY(d z2Rl~3Pq_XjT+t6}lcIJt!}kS=To=VX?!J~PXe!yd@f3^CSPr>r+2T5LxCS)m19V?& zHZl!86}va?iu-2S^?F0BUePe#Hs;q|61$>rcp?B7PrL=q`?sZ@67in6+-Uer z_dXb2x8e7V)TfL(CgX~>Q)6D)w&lP!NGf6h@CQJIT4C zzmDrom213h%yl?p>XrH}_Jr>8opA0z&bo8+>?vh_i;ikr{Qh@XJcD4=q>u9h1>_wkV5?+=IYA0dd2(QS1R6yj)U9Roq^^G`S}_$r4eoM zdtiJv%&5mdZFeetARIZC=>#%jE|24MeFyt4r^VVU~mj@KCBMjf53Z@@$vfufZtU-9&yFalse ThirdParty\Clearcove.Logging.dll - - False - ThirdParty\TAFactory.IconPack.dll - diff --git a/Utilities/File/IconReader.cs b/Utilities/File/IconReader.cs index 0b6556b..16b9919 100644 --- a/Utilities/File/IconReader.cs +++ b/Utilities/File/IconReader.cs @@ -16,7 +16,6 @@ namespace SystemTrayMenu.Utilities using System.Text; using System.Threading; using SystemTrayMenu.DllImports; - using TAFactory.IconPack; /// /// 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 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)