From cc702999721e73862bace430fdcdbb4d01dd883f Mon Sep 17 00:00:00 2001 From: Markus Hofknecht Date: Thu, 23 Sep 2021 22:53:46 +0200 Subject: [PATCH] [Feature] Show menu faster (load icons in background and update UI later) #196, 1.0.18.2 --- Business/Menus.cs | 5 +++++ DataClasses/RowData.cs | 15 ++++++++++++--- Properties/AssemblyInfo.cs | 4 ++-- Properties/Resources.Designer.cs | 20 +++++++++++++++++++ Properties/Resources.resx | 6 ++++++ Resources/Loading.ico | Bin 0 -> 4286 bytes Resources/NotFound.ico | Bin 0 -> 4286 bytes UserInterface/Menu.Designer.cs | 11 +++++++++++ UserInterface/Menu.cs | 32 +++++++++++++++++++++++++++++++ UserInterface/Menu.resx | 3 +++ Utilities/File/IconReader.cs | 19 ++++++++++++++++-- 11 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 Resources/Loading.ico create mode 100644 Resources/NotFound.ico diff --git a/Business/Menus.cs b/Business/Menus.cs index 72dd676..becfc39 100644 --- a/Business/Menus.cs +++ b/Business/Menus.cs @@ -538,6 +538,11 @@ namespace SystemTrayMenu.Business Path.GetFileName(Config.Path)); AdjustMenusSizeAndLocation(); DisposeMenu(menus[0]); + + if (FileUrl.GetDefaultBrowserPath(out string browserPath)) + { + IconReader.GetFileIconWithCache(browserPath, true, true, out bool loading); + } } internal void StartWorker() diff --git a/DataClasses/RowData.cs b/DataClasses/RowData.cs index 3bf46b0..babe993 100644 --- a/DataClasses/RowData.cs +++ b/DataClasses/RowData.cs @@ -23,6 +23,7 @@ namespace SystemTrayMenu.DataClasses internal class RowData : IDisposable { private static readonly Icon White50PercentageIcon = Properties.Resources.White50Percentage; + private static readonly Icon NotFoundIcon = Properties.Resources.NotFound; private static DateTime contextMenuClosed; private string workingDirectory; private string arguments; @@ -59,6 +60,10 @@ namespace SystemTrayMenu.DataClasses internal int MenuLevel { get; set; } + internal Icon Icon => icon; + + internal bool IconLoading { get; set; } + public void Dispose() { Dispose(true); @@ -79,7 +84,7 @@ namespace SystemTrayMenu.DataClasses if (icon == null) { - icon = White50PercentageIcon; + icon = NotFoundIcon; } if (HiddenEntry) @@ -150,7 +155,10 @@ namespace SystemTrayMenu.DataClasses { icon = IconReader.GetFileIconWithCache( TargetFilePath, - showOverlay); + showOverlay, + true, + out bool loading); + IconLoading = loading; diposeIcon = false; } catch (Exception ex) @@ -334,7 +342,8 @@ namespace SystemTrayMenu.DataClasses { if (FileUrl.GetDefaultBrowserPath(out string browserPath)) { - icon = IconReader.GetFileIconWithCache(browserPath, true); + icon = IconReader.GetFileIconWithCache(browserPath, true, true, out bool loading); + IconLoading = loading; diposeIcon = false; handled = true; } diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index f3c9e98..4be8395 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.0.18.1")] -[assembly: AssemblyFileVersion("1.0.18.1")] +[assembly: AssemblyVersion("1.0.18.2")] +[assembly: AssemblyFileVersion("1.0.18.2")] diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs index ea58bcd..03c022a 100644 --- a/Properties/Resources.Designer.cs +++ b/Properties/Resources.Designer.cs @@ -300,6 +300,26 @@ namespace SystemTrayMenu.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + public static System.Drawing.Icon Loading { + get { + object obj = ResourceManager.GetObject("Loading", resourceCulture); + return ((System.Drawing.Icon)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// + public static System.Drawing.Icon NotFound { + get { + object obj = ResourceManager.GetObject("NotFound", 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 64ecebe..7682f88 100644 --- a/Properties/Resources.resx +++ b/Properties/Resources.resx @@ -199,4 +199,10 @@ ..\Resources\ic_fluent_folder_arrow_right_48_regular.svg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\Loading.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\NotFound.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/Loading.ico b/Resources/Loading.ico new file mode 100644 index 0000000000000000000000000000000000000000..f8e548902d9d25efa335dec6b015e0bd0590e80a GIT binary patch literal 4286 zcmb`LTWnNS6o%KJDeyo_cmR2V#6UX0w8Kmb29PNQrgG5&3YJSiNF`ti;UX7Bfr>EY zA|OaXjGFjhNd&>90x4ETP!LcNq4u0J(+kFkEu}LZsLar5xBohwsr7W9wjtfk*K_t> z>;M0Cc6oxxf}g>IiGS0vzC`_rC<)+*(gC0A3$?DS@NdH?66fYH650^Uqf+ZounZJ7 z{%$P=bs!Rh-*2JzIamsY2>;WT2()n@_Uy`f`0H>A-x#LTtXSD2HFDE>@X;-6IcNl; z6S&6@%>if~q9Uo)kG(ru|NJt7n1|Q(83tgE?U=h7h{xm(Jhp{z4DZjLaevti4cCzU za|`Ho059eh-NNVHw_%xe%31n>xp0~%c?Z~&M1uxpGfshahUQEfytbKWA z%&*@UKjSNY7K+u-+Yg$(@OmWi;h`gc*9kdTWr!i=UFofY`| z*#oSV_zPs;`s=GvAs`GiV4n`C`gCe%F{X9avIocnVPMRu`}51uQ6LP|VxJ65y}Mdq z58wnrV9bg9@x?PyAPm%EZv$P8G3{dy-~<6+%!%AC91{YfN#CQo3k2`z06-Q*@{^!foR7e_etLenSFc*o+EAFG-;OcP-pd+j6a9zW zr`!3qWR)X(sIOph5A+_!%tAucw|`2WwtwoA+Mef0+x-HmyRwXtt$VI%yV1wJ`==(r zFCR2Xd<8NOYDXqnw7t^^jKSKf;L~K{ zCA3{xJAC`5TKGQsuAt%h2jZJ9s@rFY4yaS#eencXj(iuefn<=5vs`cr+CT?-fsFIW z8o-%)_D=lG0JQu~Y3e((H6?G3kTYALF4R0`P6Mcof%lf0T-V|UZ5c8goTcR>6S=$; z?8~-f6TC>-l08A$oUJLF=ZfwnTY>j@&M4bFSI=zy2gEaMeVLF4vPpSsewwmr!3E{b z1)^Knw7?5br|!)eTj#WmZhcqYo`>vtq;8r|%EpBQm5qybDjOEn0P&bq!^5Mzv2cLy z32)BmXyJPa{W|KZ9E-AU@hElOlEdojODaJWh)!rky#ks;(57iCms;X}?A?`xZzXm8 zD>};h#pGMHyob6r$EvQ$Spkl#YhG1B2t;G>yV6q2$whCHf8}cy)~Xv~KJb*SFwvkO zQDPNQPcP9ETlv2W+Aa%DdRCzWU4zi=iV|&UZb1klCcfvIE9S@=*0x#LS-i-of+J^g F=f74?sL22T literal 0 HcmV?d00001 diff --git a/Resources/NotFound.ico b/Resources/NotFound.ico new file mode 100644 index 0000000000000000000000000000000000000000..dcbfffa5f5dd370113b767c296c454d3fb7adc56 GIT binary patch literal 4286 zcmeHJTS~(~6unXe5%B@i?|!-r7v+cI14aE1{1yT(z-5StTWFI7WC3}${ki6(+z_Xk z@iwGIFbO9&Gih=j^Pogq#W@-guJm?DG$f*v0!0^{7C?V_6wl7~7g%)k*FJ&2k-+oQ zBX1I>YjB5QxPI9!gM-iAkXs(S(dRNO;Z*mNy36Sjv0uesPwrCf7cq|brt^c zIk6U+95%rZ9WoB6G7hNgPG=RVE*Sv4*-@o2vjRx#hzwJ>j z|F-e>Z}wQD0sN-tdK>f6#c#{szdc}$2F+gW; private void InitializeComponent() { + this.components = new System.ComponentModel.Container(); System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); this.tableLayoutPanelDgvAndScrollbar = new System.Windows.Forms.TableLayoutPanel(); this.dgv = new System.Windows.Forms.DataGridView(); @@ -44,6 +48,7 @@ this.tableLayoutPanelTitle = new System.Windows.Forms.TableLayoutPanel(); this.pictureBoxOpenFolder = new System.Windows.Forms.PictureBox(); this.pictureBoxMenuAlwaysOpen = new System.Windows.Forms.PictureBox(); + this.timerUpdateIcons = new System.Windows.Forms.Timer(this.components); this.tableLayoutPanelDgvAndScrollbar.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.dgv)).BeginInit(); this.tableLayoutPanelSearch.SuspendLayout(); @@ -288,6 +293,11 @@ // InitializeComponentControlsTheDesignerRemoves(); // + // timerUpdateIcons + // + this.timerUpdateIcons.Interval = 300; + this.timerUpdateIcons.Tick += new System.EventHandler(this.TimerUpdateIcons_Tick); + // // Menu // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); @@ -340,5 +350,6 @@ private System.Windows.Forms.PictureBox pictureBoxFilesCount; private System.Windows.Forms.PictureBox pictureBoxFoldersCount; private System.Windows.Forms.Label labelFoldersCount; + private System.Windows.Forms.Timer timerUpdateIcons; } } \ No newline at end of file diff --git a/UserInterface/Menu.cs b/UserInterface/Menu.cs index 5b3f879..7c42017 100644 --- a/UserInterface/Menu.cs +++ b/UserInterface/Menu.cs @@ -43,6 +43,7 @@ namespace SystemTrayMenu.UserInterface isShowing = true; Visible = true; isShowing = false; + timerUpdateIcons.Start(); } catch (ObjectDisposedException) { @@ -702,6 +703,13 @@ namespace SystemTrayMenu.UserInterface else { filesCount++; + + if (rowData.IconLoading) + { + string resolvedLnkPath = string.Empty; + rowData.ReadIcon(rowData.ContainsMenu, ref resolvedLnkPath); + row.Cells[0].Value = rowData.Icon; + } } } @@ -795,5 +803,29 @@ namespace SystemTrayMenu.UserInterface UserClickedOpenFolder?.Invoke(); } } + + private void TimerUpdateIcons_Tick(object sender, EventArgs e) + { + int iconsToUpdate = 0; + + foreach (DataGridViewRow row in dgv.Rows) + { + RowData rowData = (RowData)row.Cells[2].Value; + rowData.RowIndex = row.Index; + + if (rowData.IconLoading) + { + iconsToUpdate++; + string resolvedLnkPath = string.Empty; + rowData.ReadIcon(rowData.ContainsMenu, ref resolvedLnkPath); + row.Cells[0].Value = rowData.Icon; + } + } + + if (iconsToUpdate < 1) + { + timerUpdateIcons.Stop(); + } + } } } \ No newline at end of file diff --git a/UserInterface/Menu.resx b/UserInterface/Menu.resx index f298a7b..0ef9e60 100644 --- a/UserInterface/Menu.resx +++ b/UserInterface/Menu.resx @@ -57,4 +57,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 17 + \ No newline at end of file diff --git a/Utilities/File/IconReader.cs b/Utilities/File/IconReader.cs index 3a7bdb0..7fa0147 100644 --- a/Utilities/File/IconReader.cs +++ b/Utilities/File/IconReader.cs @@ -11,6 +11,7 @@ namespace SystemTrayMenu.Utilities using System.Drawing.Imaging; using System.IO; using System.Runtime.InteropServices; + using System.Threading; using System.Threading.Tasks; // from https://www.codeproject.com/Articles/2532/Obtaining-and-managing-file-and-folder-icons-using @@ -47,9 +48,10 @@ namespace SystemTrayMenu.Utilities } } - public static Icon GetFileIconWithCache(string filePath, bool linkOverlay) + public static Icon GetFileIconWithCache(string filePath, bool linkOverlay, bool updateIconInBackground, out bool loading) { Icon icon = null; + loading = false; string extension = Path.GetExtension(filePath); IconSize size = IconSize.Small; if (Scaling.Factor > 1) @@ -63,7 +65,20 @@ namespace SystemTrayMenu.Utilities } else { - icon = DictIconCache.GetOrAdd(filePath, GetIcon); + if (!DictIconCache.TryGetValue(filePath, out icon)) + { + icon = Properties.Resources.Loading; + loading = true; + + if (updateIconInBackground) + { + new Thread(UpdateIconInBackground).Start(); + void UpdateIconInBackground() + { + DictIconCache.GetOrAdd(filePath, GetIcon); + } + } + } } Icon GetIcon(string keyExtension)