From 683bf3d936d0be7bafcd20dfa67550ad54291fcf Mon Sep 17 00:00:00 2001 From: Terry MacDonald Date: Sun, 18 Oct 2020 23:04:08 +1300 Subject: [PATCH] Fixed Bitmap processing for Shortcuts The Bitmap processing wasm't working in the listitemview. Traced it to a problem with a missing GenerateThumbnailView call. Also adjusted when the save to icon cache happens so that it is part of the ShortcutItem and is called when a new shortcut is created. This saves times. --- HeliosPlus/ShortcutItem.cs | 125 +++++++++++++++++++++++--- HeliosPlus/ShortcutRepository.cs | 9 +- HeliosPlus/UIForms/ShortcutAdaptor.cs | 22 +---- HeliosPlus/UIForms/ShortcutForm.cs | 24 +++-- 4 files changed, 139 insertions(+), 41 deletions(-) diff --git a/HeliosPlus/ShortcutItem.cs b/HeliosPlus/ShortcutItem.cs index 7078274..c0b76d3 100644 --- a/HeliosPlus/ShortcutItem.cs +++ b/HeliosPlus/ShortcutItem.cs @@ -95,8 +95,11 @@ namespace HeliosPlus private bool _autoName; private bool _isPossible; private List _startPrograms; + [JsonIgnore] public string _originalIconPath; private Bitmap _shortcutBitmap, _originalBitmap; + [JsonIgnore] + public string _savedShortcutIconCacheFilename; public ShortcutItem() @@ -132,7 +135,8 @@ namespace HeliosPlus string uuid = "" ) : this() { - _uuid = uuid; + if (!String.IsNullOrWhiteSpace(uuid)) + _uuid = uuid; _name = name; _profileToUse = profile; _category = ShortcutCategory.Game; @@ -151,12 +155,22 @@ namespace HeliosPlus // Now we need to find and populate the profileUuid _profileUuid = profile.UUID; + // We create the OriginalBitmap from the IconPath + _originalBitmap = ToBitmap(_originalIconPath); + + // We create the ShortcutBitmap from the OriginalBitmap + // (We only do it if there is a valid profile) + if (_profileToUse is ProfileItem) + _shortcutBitmap = ToBitmapOverlay(_originalBitmap, _profileToUse.ProfileTightestBitmap, 256, 256); + } public ShortcutItem(string name, ProfileItem profile, GameStruct game, ShortcutPermanence permanence, string originalIconPath, List startPrograms = null, bool autoName = true, string uuid = "") : this() { - _uuid = uuid; + // Create a new UUID for the shortcut if one wasn't created already + if (!String.IsNullOrWhiteSpace(uuid)) + _uuid = uuid; _name = name; _profileToUse = profile; _category = ShortcutCategory.Game; @@ -174,6 +188,13 @@ namespace HeliosPlus // Now we need to find and populate the profileUuid _profileUuid = profile.UUID; + // We create the OriginalBitmap from the IconPath + _originalBitmap = ToBitmap(_originalIconPath); + + // We create the ShortcutBitmap from the OriginalBitmap + // (We only do it if there is a valid profile) + if (_profileToUse is ProfileItem) + _shortcutBitmap = ToBitmapOverlay(_originalBitmap, _profileToUse.ProfileTightestBitmap, 256, 256); } @@ -181,7 +202,8 @@ namespace HeliosPlus public ShortcutItem(string name, string profileUuid, GameStruct game, ShortcutPermanence permanence, string originalIconPath, List startPrograms = null, bool autoName = true, string uuid = "") : this() { - _uuid = uuid; + if (!String.IsNullOrWhiteSpace(uuid)) + _uuid = uuid; _name = name; _profileUuid = profileUuid; _category = ShortcutCategory.Game; @@ -212,6 +234,14 @@ namespace HeliosPlus { throw new Exception($"Trying to create a ShortcutItem and cannot find a loaded profile with UUID {uuid}."); } + + // We create the OriginalBitmap from the IconPath + _originalBitmap = ToBitmap(_originalIconPath); + + // We create the ShortcutBitmap from the OriginalBitmap + // (We only do it if there is a valid profile) + if (_profileToUse is ProfileItem) + _shortcutBitmap = ToBitmapOverlay(_originalBitmap, _profileToUse.ProfileTightestBitmap, 256, 256); } public ShortcutItem( @@ -230,7 +260,8 @@ namespace HeliosPlus string uuid = "" ) : this() { - _uuid = uuid; + if (!String.IsNullOrWhiteSpace(uuid)) + _uuid = uuid; _name = name; _profileToUse = profile; _category = ShortcutCategory.Application; @@ -248,12 +279,21 @@ namespace HeliosPlus // Now we need to find and populate the profileUuid _profileUuid = profile.UUID; + // We create the OriginalBitmap from the IconPath + _originalBitmap = ToBitmap(_originalIconPath); + + // We create the ShortcutBitmap from the OriginalBitmap + // (We only do it if there is a valid profile) + if (_profileToUse is ProfileItem) + _shortcutBitmap = ToBitmapOverlay(_originalBitmap, _profileToUse.ProfileTightestBitmap, 256, 256); + } public ShortcutItem(string name, ProfileItem profile, Executable executable, ShortcutPermanence permanence, string originalIconPath, List startPrograms = null, bool autoName = true, string uuid = "") : this() { - _uuid = uuid; + if (!String.IsNullOrWhiteSpace(uuid)) + _uuid = uuid; _name = name; _profileToUse = profile; _category = ShortcutCategory.Application; @@ -271,12 +311,21 @@ namespace HeliosPlus // Now we need to find and populate the profileUuid _profileUuid = profile.UUID; + // We create the OriginalBitmap from the IconPath + _originalBitmap = ToBitmap(_originalIconPath); + + // We create the ShortcutBitmap from the OriginalBitmap + // (We only do it if there is a valid profile) + if (_profileToUse is ProfileItem) + _shortcutBitmap = ToBitmapOverlay(_originalBitmap, _profileToUse.ProfileTightestBitmap, 256, 256); + } public ShortcutItem(string name, string profileUuid, Executable executable, ShortcutPermanence permanence, string originalIconPath, List startPrograms = null, bool autoName = true, string uuid = "") : this() { - _uuid = uuid; + if (!String.IsNullOrWhiteSpace(uuid)) + _uuid = uuid; _name = name; _profileUuid = profileUuid; _category = ShortcutCategory.Application; @@ -307,6 +356,14 @@ namespace HeliosPlus throw new Exception($"Trying to create a ShortcutItem and cannot find a loaded profile with UUID {uuid}."); } + // We create the OriginalBitmap from the IconPath + _originalBitmap = ToBitmap(_originalIconPath); + + // We create the ShortcutBitmap from the OriginalBitmap + // (We only do it if there is a valid profile) + if (_profileToUse is ProfileItem) + _shortcutBitmap = ToBitmapOverlay(_originalBitmap, _profileToUse.ProfileTightestBitmap, 256, 256); + } @@ -445,9 +502,8 @@ namespace HeliosPlus // If the executableNameandPath is set then we also want to update the originalIconPath // so it's the path to the application. This will kick of the icon grabbing processes - if (!String.IsNullOrWhiteSpace(_originalIconPath)) - if (Category.Equals(ShortcutCategory.Application)) - _originalIconPath = value; + if (Category.Equals(ShortcutCategory.Application)) + _originalIconPath = value; } } @@ -593,8 +649,7 @@ namespace HeliosPlus _originalIconPath = value; // And we do the same for the OriginalBitmap - if (_originalBitmap == null) - _originalBitmap = ToBitmap(_originalIconPath); + _originalBitmap = ToBitmap(_originalIconPath); } } @@ -631,7 +686,17 @@ namespace HeliosPlus } } - public string SavedShortcutIconCacheFilename { get; set; } + public string SavedShortcutIconCacheFilename + { + get + { + return _savedShortcutIconCacheFilename; + } + set + { + _savedShortcutIconCacheFilename = value; + } + } [JsonIgnore] public bool IsPossible @@ -681,6 +746,40 @@ namespace HeliosPlus return true; } + public void SaveShortcutIconToCache() + { + + // Only add this set of options if the shortcut is to an standalone application + if (_category == ShortcutCategory.Application) + { + // Work out the name of the shortcut we'll save. + _savedShortcutIconCacheFilename = Path.Combine(Program.AppShortcutPath, String.Concat(@"executable-", _profileToUse.UUID, "-", Path.GetFileNameWithoutExtension(_executableNameAndPath), @".ico")); + + } + else + { + // Work out the name of the shortcut we'll save. + _savedShortcutIconCacheFilename = Path.Combine(Program.AppShortcutPath, String.Concat(_gameLibrary.ToString().ToLower(CultureInfo.InvariantCulture),@"-", _profileToUse.UUID, "-", _gameAppId.ToString(), @".ico")); + } + + MultiIcon shortcutIcon; + try + { + //shortcutIcon = new ProfileIcon(shortcut.ProfileToUse).ToIconOverlay(shortcut.OriginalIconPath); + shortcutIcon = ToIconOverlay(); + shortcutIcon.Save(_savedShortcutIconCacheFilename, MultiIconFormat.ICO); + } + catch (Exception ex) + { + Console.WriteLine($"ShortcutRepository/SaveShortcutIconToCache exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); + + // If we fail to create an icon based on the original executable or game + // Then we use the standard HeliosPlus profile one. + shortcutIcon = _profileToUse.ProfileIcon.ToIcon(); + shortcutIcon.Save(_savedShortcutIconCacheFilename, MultiIconFormat.ICO); + } + } + public static Bitmap ExtractVistaIcon(Icon icoIcon) { Bitmap bmpPngExtracted = null; @@ -768,7 +867,7 @@ namespace HeliosPlus return null; string fileExtension = Path.GetExtension(fileNameAndPath); - if (fileExtension.Equals("ico",StringComparison.OrdinalIgnoreCase)) + if (fileExtension.Equals(".ico",StringComparison.OrdinalIgnoreCase)) { return ToBitmapFromIcon(fileNameAndPath); } diff --git a/HeliosPlus/ShortcutRepository.cs b/HeliosPlus/ShortcutRepository.cs index a3cd68f..cda786d 100644 --- a/HeliosPlus/ShortcutRepository.cs +++ b/HeliosPlus/ShortcutRepository.cs @@ -117,7 +117,7 @@ namespace HeliosPlus if (ContainsShortcut(shortcut)) { // Generate the Shortcut Icon ready to be used - SaveShortcutIconToCache(shortcut); + //shortcut.SaveShortcutIconToCache(); // Save the shortcuts JSON as it's different SaveShortcuts(); @@ -374,6 +374,7 @@ namespace HeliosPlus } } + try { var json = JsonConvert.SerializeObject(_allShortcuts, Formatting.Indented, new JsonSerializerSettings @@ -401,9 +402,11 @@ namespace HeliosPlus return false; } - private static void SaveShortcutIconToCache(ShortcutItem shortcut) + /* private static void SaveShortcutIconToCache(ShortcutItem shortcut) { + // Force the creation of the ShortcutBitmap + // Only add the rest of the options if the permanence is temporary if (shortcut.Permanence == ShortcutPermanence.Temporary) { @@ -458,7 +461,7 @@ namespace HeliosPlus shortcutIcon = shortcut.ProfileToUse.ProfileIcon.ToIcon(); shortcutIcon.Save(shortcut.SavedShortcutIconCacheFilename, MultiIconFormat.ICO); } - } + }*/ // ReSharper disable once CyclomaticComplexity diff --git a/HeliosPlus/UIForms/ShortcutAdaptor.cs b/HeliosPlus/UIForms/ShortcutAdaptor.cs index bc12aa4..7b51a0b 100644 --- a/HeliosPlus/UIForms/ShortcutAdaptor.cs +++ b/HeliosPlus/UIForms/ShortcutAdaptor.cs @@ -43,15 +43,8 @@ namespace HeliosPlus.UIForms { ShortcutItem shortcut = (ShortcutItem) key; - if (shortcut == null) - { - return null; - } - Image.GetThumbnailImageAbort myCallback = new Image.GetThumbnailImageAbort(() => { return false; }); - //return shortcut.ShortcutBitmap.GetThumbnailImage(size.Width, size.Height, myCallback, IntPtr.Zero); - //return Manina.Windows.Forms.Instance.GetThumbnail(shortcut.ShortcutBitmap, size, useEmbeddedThumbnails, useExifOrientation); - return shortcut.ShortcutBitmap; + return shortcut.ShortcutBitmap.GetThumbnailImage(256, 256, myCallback, IntPtr.Zero); } catch (Exception ex) { @@ -85,18 +78,7 @@ namespace HeliosPlus.UIForms ShortcutItem shortcut = (ShortcutItem) key; //return shortcut.Name; - - StringBuilder sb = new StringBuilder(); - sb.Append(shortcut.ToString());// Filename - sb.Append(':'); - sb.Append(size.Width); // Thumbnail size - sb.Append(','); - sb.Append(size.Height); - sb.Append(':'); - sb.Append(useEmbeddedThumbnails); - sb.Append(':'); - sb.Append(useExifOrientation); - return sb.ToString(); + return shortcut.Name; } catch (Exception ex) { diff --git a/HeliosPlus/UIForms/ShortcutForm.cs b/HeliosPlus/UIForms/ShortcutForm.cs index f58d610..a1dd325 100644 --- a/HeliosPlus/UIForms/ShortcutForm.cs +++ b/HeliosPlus/UIForms/ShortcutForm.cs @@ -28,7 +28,7 @@ namespace HeliosPlus.UIForms List _startPrograms = new List(); private ShortcutItem _shortcutToEdit = null; private bool _isNewShortcut = true; - private bool _isUnsaved = false; + private bool _isUnsaved = true; private bool _loadedShortcut = false; private bool _autoName = true; private uint _gameId = 0; @@ -437,7 +437,8 @@ namespace HeliosPlus.UIForms _permanence, _gameToUse.GameToPlay.IconPath, _startPrograms, - _autoName + _autoName, + _uuid ); } @@ -490,8 +491,14 @@ namespace HeliosPlus.UIForms // Add the Shortcut to the list of saved Shortcuts so it gets saved for later // but only if it's new... if it is an edit then it will already be in the list. - ShortcutRepository.AddShortcut(_shortcutToEdit); - + if (_isNewShortcut) + { + // Generate the Shortcut Icon ready to be used + _shortcutToEdit.SaveShortcutIconToCache(); + //SAve the shortcut to the Shortcut Repository + ShortcutRepository.AddShortcut(_shortcutToEdit); + } + // We've saved, so mark it as so _isUnsaved = false; @@ -714,8 +721,14 @@ namespace HeliosPlus.UIForms // If it is a new Shortcut then we don't have to load anything! if (_isNewShortcut) + { + RefreshShortcutUI(); + ChangeSelectedProfile(ProfileRepository.CurrentProfile); + _isUnsaved = true; return; + } + // We only get down here if the form has loaded a shortcut to edit if (_shortcutToEdit is ShortcutItem && _shortcutToEdit.ProfileToUse is ProfileItem) { foreach (ProfileItem loadedProfile in ProfileRepository.AllProfiles) @@ -885,6 +898,7 @@ namespace HeliosPlus.UIForms RefreshImageListView(chosenProfile); _loadedShortcut = true; + _isUnsaved = false; // Finally enable the save button if it's still valid enableSaveButtonIfValid(); @@ -1153,7 +1167,7 @@ namespace HeliosPlus.UIForms MessageBoxIcon.Exclamation); e.Cancel = (result == DialogResult.No); } - + } private void btn_exe_to_start_Click(object sender, EventArgs e)