diff --git a/HeliosPlus.Reporting/Program.cs b/HeliosPlus.Reporting/Program.cs index 751a402..fbdf7c0 100644 --- a/HeliosPlus.Reporting/Program.cs +++ b/HeliosPlus.Reporting/Program.cs @@ -208,7 +208,7 @@ namespace HeliosPlus.Reporting try { - Dump(Profile.LoadAllProfiles(), "HeliosPlus.Shared.Profile.GetAllProfiles()", null, 99); + Dump(ProfileItem.LoadAllProfiles(), "HeliosPlus.Shared.Profile.GetAllProfiles()", null, 99); } catch (Exception e) { diff --git a/HeliosPlus.Shared/Helios.cs b/HeliosPlus.Shared/Helios.cs index efa3527..24f0268 100644 --- a/HeliosPlus.Shared/Helios.cs +++ b/HeliosPlus.Shared/Helios.cs @@ -45,7 +45,7 @@ namespace HeliosPlus.Shared // ReSharper disable once TooManyArguments public static void Open( HeliosStartupAction action = HeliosStartupAction.None, - Profile profile = null, + ProfileItem profile = null, string programAddress = null, bool asAdmin = false) { @@ -94,7 +94,7 @@ namespace HeliosPlus.Shared public static void OpenSteamGame( HeliosStartupAction action = HeliosStartupAction.None, - Profile profile = null, + ProfileItem profile = null, uint steamAppId = 0) { try diff --git a/HeliosPlus.Shared/HeliosPlus.Shared.csproj b/HeliosPlus.Shared/HeliosPlus.Shared.csproj index 25b26f6..fb87745 100644 --- a/HeliosPlus.Shared/HeliosPlus.Shared.csproj +++ b/HeliosPlus.Shared/HeliosPlus.Shared.csproj @@ -46,7 +46,7 @@ - + diff --git a/HeliosPlus.Shared/ProfileIcon.cs b/HeliosPlus.Shared/ProfileIcon.cs index a90ca57..5e977a4 100644 --- a/HeliosPlus.Shared/ProfileIcon.cs +++ b/HeliosPlus.Shared/ProfileIcon.cs @@ -4,6 +4,7 @@ using System.Drawing.Drawing2D; using System.Drawing.IconLib; using System.Drawing.Imaging; using System.Linq; +using System.Windows.Forms; using HeliosPlus.Shared.Topology; namespace HeliosPlus.Shared @@ -11,9 +12,9 @@ namespace HeliosPlus.Shared public class ProfileIcon { - private Profile _profile; + private ProfileItem _profile; - public ProfileIcon(Profile profile, int paddingX = 100, int paddingY = 100) + public ProfileIcon(ProfileItem profile, int paddingX = 100, int paddingY = 100) { _profile = profile; PaddingX = paddingX; @@ -72,19 +73,19 @@ namespace HeliosPlus.Shared public static Size NormalizeResolution(ProfileViewport path) { - var bigest = Size.Empty; + var biggest = Size.Empty; foreach (var target in path.TargetDisplays) { var res = NormalizeResolution(path.Resolution, target.Rotation); - if ((ulong) res.Width * (ulong) res.Height > (ulong) bigest.Width * (ulong) bigest.Height) + if ((ulong) res.Width * (ulong) res.Height > (ulong) biggest.Width * (ulong) biggest.Height) { - bigest = res; + biggest = res; } } - return bigest.IsEmpty ? path.Resolution : bigest; + return biggest.IsEmpty ? path.Resolution : biggest; } @@ -127,7 +128,7 @@ namespace HeliosPlus.Shared return path; } - public Bitmap ToBitmap(int width = 128, int height = 128, PixelFormat format = PixelFormat.Format32bppArgb) + public Bitmap ToBitmap(int width = 256, int height = 256, PixelFormat format = PixelFormat.Format32bppArgb) { var bitmap = new Bitmap(width, height, format); bitmap.MakeTransparent(); @@ -141,40 +142,73 @@ namespace HeliosPlus.Shared return bitmap; } - public Bitmap ToBitmapOverlay(Bitmap bitmap, int width = 0, int height = 0, PixelFormat format = PixelFormat.Format32bppArgb) + public Bitmap ToTightestBitmap(int width = 256, int height = 0, PixelFormat format = PixelFormat.Format32bppArgb) { - - if (width == 0) - width = bitmap.Width; + var viewSize = CalculateViewSize(_profile.Viewports, true, PaddingX, PaddingY); + int viewSizeRatio = Convert.ToInt32(viewSize.Width / viewSize.Height); if (height == 0) - height = bitmap.Height; + height = width * viewSizeRatio; - var viewSize = CalculateViewSize(_profile.Viewports, true, PaddingX, PaddingY); - int viewSizeRatio = (int) Math.Round(viewSize.Width * viewSize.Height); - int overlayWidth = (int) Math.Round(width * 0.7f,0); - int overlayHeight = overlayWidth / viewSizeRatio; - int overlayX = width - overlayWidth; - int overlayY = height - overlayHeight; - Point overlayPosition = new Point(overlayX, overlayY); - Size overlaySize = new Size(overlayWidth, overlayHeight); - Rectangle overlayRect = new Rectangle(overlayPosition, overlaySize); - //var width = bitmap.Width * 0.7f; - //var height = width / viewSize.Width * viewSize.Height; + var bitmap = new Bitmap(width, height, format); + bitmap.MakeTransparent(); - var combinedBitmap = new Bitmap(width, height, format); - combinedBitmap.MakeTransparent(); - - using (var g = Graphics.FromImage(combinedBitmap)) + using (var g = Graphics.FromImage(bitmap)) { g.SmoothingMode = SmoothingMode.HighQuality; - //g.DrawImage(bitmap, 0, 0, width, height); - g.TranslateTransform(overlayX, overlayY); - //Rectangle compressionRectangle = new Rectangle(300, 10, - //myBitmap.Width / 2, myBitmap.Height / 2); - g.DrawRectangle(new Pen(Color.FromArgb(125, 50, 50, 50), 2f), overlayRect); + DrawView(g, width, height); + } - DrawView(g, overlayWidth, overlayHeight); + return bitmap; + } + + public Bitmap ToBitmapOverlay(Bitmap bitmap) + { + + /* if (width == 0) + width = bitmap.Width; + + if (height == 0) + height = bitmap.Height; + + var viewSize = CalculateViewSize(_profile.Viewports, true, PaddingX, PaddingY); + int viewSizeRatio = (int) Math.Round(viewSize.Width / viewSize.Height); + int overlayWidth = (int) Math.Round(width * 0.7f,0); + int overlayHeight = overlayWidth / viewSizeRatio; + int overlayX = width - overlayWidth; + int overlayY = height - overlayHeight; + Point overlayPosition = new Point(overlayX, overlayY); + Size overlaySize = new Size(overlayWidth, overlayHeight); + Rectangle overlayRect = new Rectangle(overlayPosition, overlaySize); + //var width = bitmap.Width * 0.7f; + //var height = width / viewSize.Width * viewSize.Height; + + var combinedBitmap = new Bitmap(width, height, format); + combinedBitmap.MakeTransparent(); + + using (var g = Graphics.FromImage(combinedBitmap)) + { + g.SmoothingMode = SmoothingMode.HighQuality; + //g.DrawImage(bitmap, 0, 0, width, height); + g.TranslateTransform(overlayX, overlayY); + //Rectangle compressionRectangle = new Rectangle(300, 10, + //myBitmap.Width / 2, myBitmap.Height / 2); + g.DrawRectangle(new Pen(Color.FromArgb(125, 50, 50, 50), 2f), overlayRect); + + DrawView(g, overlayWidth, overlayHeight); + } + return bitmap;*/ + + + var viewSize = CalculateViewSize(_profile.Viewports, true, PaddingX, PaddingY); + var width = bitmap.Width * 0.7f; + var height = width / viewSize.Width * viewSize.Height; + + using (var g = Graphics.FromImage(bitmap)) + { + g.SmoothingMode = SmoothingMode.HighQuality; + g.TranslateTransform(bitmap.Width - width, bitmap.Height - height * 1.1f); + DrawView(g, width, height); } return bitmap; diff --git a/HeliosPlus.Shared/Profile.cs b/HeliosPlus.Shared/ProfileItem.cs similarity index 90% rename from HeliosPlus.Shared/Profile.cs rename to HeliosPlus.Shared/ProfileItem.cs index 564e08d..af0c720 100644 --- a/HeliosPlus.Shared/Profile.cs +++ b/HeliosPlus.Shared/ProfileItem.cs @@ -18,12 +18,12 @@ using WindowsDisplayAPI; namespace HeliosPlus.Shared { - public class Profile + public class ProfileItem { - private static Profile _currentProfile; - private static List _allSavedProfiles = new List(); + private static ProfileItem _currentProfile; + private static List _allSavedProfiles = new List(); private ProfileIcon _profileIcon; - private Bitmap _profileBitmap; + private Bitmap _profileBitmap, _profileShortcutBitmap; private static List _availableDisplays; private static List _unavailableDisplays; @@ -89,7 +89,7 @@ namespace HeliosPlus.Shared } #endregion - static Profile() + static ProfileItem() { try { @@ -162,19 +162,19 @@ namespace HeliosPlus.Shared get => System.IO.Path.Combine(AppDataPath, $"Profiles"); } - public static List AllSavedProfiles + public static List AllSavedProfiles { get { if (_allSavedProfiles.Count == 0) { - Profile.LoadAllProfiles(); + ProfileItem.LoadAllProfiles(); } return _allSavedProfiles; } } - public static Profile CurrentProfile + public static ProfileItem CurrentProfile { get => _currentProfile; } @@ -211,7 +211,7 @@ namespace HeliosPlus.Shared return _profileBitmap; else { - _profileBitmap = this.ProfileIcon.ToBitmap(128, 128); + _profileBitmap = this.ProfileIcon.ToBitmap(256, 256); return _profileBitmap; } } @@ -222,7 +222,27 @@ namespace HeliosPlus.Shared } - public static List LoadAllProfiles() + [JsonConverter(typeof(CustomBitmapConverter))] + public Bitmap ProfileTightestBitmap + { + get + { + if (_profileShortcutBitmap != null) + return _profileShortcutBitmap; + else + { + _profileShortcutBitmap = this.ProfileIcon.ToTightestBitmap(); + return _profileShortcutBitmap; + } + } + set + { + _profileShortcutBitmap = value; + } + + } + + public static List LoadAllProfiles() { if (File.Exists(SavedProfilesFilePath)) @@ -231,11 +251,11 @@ namespace HeliosPlus.Shared if (!string.IsNullOrWhiteSpace(json)) { - List profiles = new List(); + List profiles = new List(); try { //var profiles = JsonConvert.DeserializeObject(json, new JsonSerializerSettings - profiles = JsonConvert.DeserializeObject>(json, new JsonSerializerSettings + profiles = JsonConvert.DeserializeObject>(json, new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, @@ -254,7 +274,7 @@ namespace HeliosPlus.Shared //List profilesList = profiles.ToList(); // Find which entry is being used now, and save that info in a class variable - Profile myCurrentProfile = new Profile + ProfileItem myCurrentProfile = new ProfileItem { Name = "Current Display Profile", Viewports = PathInfo.GetActivePaths().Select(info => new ProfileViewport(info)).ToArray() @@ -262,7 +282,7 @@ namespace HeliosPlus.Shared _currentProfile = myCurrentProfile; - foreach (Profile loadedProfile in profiles) + foreach (ProfileItem loadedProfile in profiles) { // Save a profile Icon to the profile loadedProfile.ProfileIcon = new ProfileIcon(loadedProfile); @@ -283,7 +303,7 @@ namespace HeliosPlus.Shared // If we get here, then we don't have any profiles saved! // So we gotta start from scratch // Create a new profile based on our current display settings - _currentProfile = new Profile + _currentProfile = new ProfileItem { Name = "Current Display Profile", Viewports = PathInfo.GetActivePaths().Select(info => new ProfileViewport(info)).ToArray() @@ -294,14 +314,14 @@ namespace HeliosPlus.Shared _currentProfile.ProfileBitmap = _currentProfile.ProfileIcon.ToBitmap(128, 128); // Create a new empty list of all our display profiles as we don't have any saved! - _allSavedProfiles = new List(); + _allSavedProfiles = new List(); return _allSavedProfiles; } public static bool IsValidName(string testName) { - foreach (Profile loadedProfile in _allSavedProfiles) + foreach (ProfileItem loadedProfile in _allSavedProfiles) { if (loadedProfile.Name == testName) { @@ -314,7 +334,7 @@ namespace HeliosPlus.Shared public static bool IsValidId(string testId) { - foreach (Profile loadedProfile in _allSavedProfiles) + foreach (ProfileItem loadedProfile in _allSavedProfiles) { if (loadedProfile.Id == testId) { @@ -328,7 +348,7 @@ namespace HeliosPlus.Shared public static void UpdateCurrentProfile() { - _currentProfile = new Profile + _currentProfile = new ProfileItem { Name = "Current Display Profile", Viewports = PathInfo.GetActivePaths().Select(info => new ProfileViewport(info)).ToArray() @@ -342,7 +362,7 @@ namespace HeliosPlus.Shared return false; } - public static bool SaveAllProfiles(List profilesToSave) + public static bool SaveAllProfiles(List profilesToSave) { if (!Directory.Exists(SavedProfilesPath)) @@ -359,7 +379,7 @@ namespace HeliosPlus.Shared // Now we loop over the profiles and save their images for later - foreach (Profile profileToSave in profilesToSave) + foreach (ProfileItem profileToSave in profilesToSave) { profileToSave.SaveProfileImageToCache(); } @@ -403,11 +423,11 @@ namespace HeliosPlus.Shared // The public override for the Object.Equals public override bool Equals(object obj) { - return this.Equals(obj as Profile); + return this.Equals(obj as ProfileItem); } // Profiles are equal if their contents (except name) are equal - public bool Equals(Profile other) + public bool Equals(ProfileItem other) { // If parameter is null, return false. @@ -591,10 +611,10 @@ namespace HeliosPlus.Shared // Custom comparer for the Profile class // Allows us to use 'Contains' - class ProfileComparer : IEqualityComparer + class ProfileComparer : IEqualityComparer { // Products are equal if their names and product numbers are equal. - public bool Equals(Profile x, Profile y) + public bool Equals(ProfileItem x, ProfileItem y) { //Check whether the compared objects reference the same data. @@ -616,7 +636,7 @@ namespace HeliosPlus.Shared // If Equals() returns true for a pair of objects // then GetHashCode() must return the same value for these objects. - public int GetHashCode(Profile profile) + public int GetHashCode(ProfileItem profile) { // Check whether the object is null diff --git a/HeliosPlus.Shared/UserControls/DisplayView.cs b/HeliosPlus.Shared/UserControls/DisplayView.cs index 1248245..e36ccbe 100644 --- a/HeliosPlus.Shared/UserControls/DisplayView.cs +++ b/HeliosPlus.Shared/UserControls/DisplayView.cs @@ -7,7 +7,7 @@ namespace HeliosPlus.Shared.UserControls { public partial class DisplayView : UserControl { - private Profile _profile; + private ProfileItem _profile; public DisplayView() { @@ -18,7 +18,7 @@ namespace HeliosPlus.Shared.UserControls public int PaddingX { get; set; } = 100; public int PaddingY { get; set; } = 100; - public Profile Profile + public ProfileItem Profile { get => _profile; set diff --git a/HeliosPlus.ShellExtension/Helios.cs b/HeliosPlus.ShellExtension/Helios.cs index 8955ec5..b109826 100644 --- a/HeliosPlus.ShellExtension/Helios.cs +++ b/HeliosPlus.ShellExtension/Helios.cs @@ -12,7 +12,7 @@ namespace HeliosPlus.ShellExtension public static void Open( HeliosStartupAction action = HeliosStartupAction.None, - Profile profile = null, + ProfileItem profile = null, string programAddress = null, bool asAdmin = false) { @@ -29,7 +29,7 @@ namespace HeliosPlus.ShellExtension public static void OpenSteamGame( HeliosStartupAction action = HeliosStartupAction.None, - Profile profile = null, + ProfileItem profile = null, uint steamAppId = 0) { try diff --git a/HeliosPlus.ShellExtension/HeliosDesktopMenuExtension.cs b/HeliosPlus.ShellExtension/HeliosDesktopMenuExtension.cs index f95334e..8410ef8 100644 --- a/HeliosPlus.ShellExtension/HeliosDesktopMenuExtension.cs +++ b/HeliosPlus.ShellExtension/HeliosDesktopMenuExtension.cs @@ -13,7 +13,7 @@ namespace HeliosPlus.ShellExtension [Guid("2EC0C798-715B-458E-8C86-5D846F67FBA1")] internal class HeliosDesktopMenuExtension : SharpContextMenu { - private static ToolStripMenuItem CreateProfileMenu(Profile profile) + private static ToolStripMenuItem CreateProfileMenu(ProfileItem profile) { var profileMenu = new ToolStripMenuItem(profile.Name, new ProfileIcon(profile).ToBitmap(16, 16)); profileMenu.DropDownItems.Add(new ToolStripMenuItem(Language.Apply, null, @@ -39,13 +39,13 @@ namespace HeliosPlus.ShellExtension { var explorerMenu = new ContextMenuStrip(); - if (Profile.LoadAllProfiles().Any()) + if (ProfileItem.LoadAllProfiles().Any()) { - Profile.UpdateCurrentProfile(); + ProfileItem.UpdateCurrentProfile(); var extensionMenu = new ToolStripMenuItem(Language.Display_Profiles, Properties.Resources.Icon_x16); - foreach (var profile in Profile.LoadAllProfiles()) + foreach (var profile in ProfileItem.LoadAllProfiles()) { extensionMenu.DropDownItems.Add(CreateProfileMenu(profile)); } diff --git a/HeliosPlus.ShellExtension/HeliosExecutableMenuExtension.cs b/HeliosPlus.ShellExtension/HeliosExecutableMenuExtension.cs index b0cee20..56dcfa7 100644 --- a/HeliosPlus.ShellExtension/HeliosExecutableMenuExtension.cs +++ b/HeliosPlus.ShellExtension/HeliosExecutableMenuExtension.cs @@ -18,7 +18,7 @@ namespace HeliosPlus.ShellExtension { return Helios.IsInstalled && SelectedItemPaths.Count() == 1 && - Profile.LoadAllProfiles().Any() && + ProfileItem.LoadAllProfiles().Any() && Path.GetExtension(SelectedItemPaths.First())?.ToLower() == @".exe"; } @@ -28,11 +28,11 @@ namespace HeliosPlus.ShellExtension var extensionMenu = new ToolStripMenuItem(Language.Open_under_Display_Profile, Properties.Resources.Icon_x16); - if (Profile.LoadAllProfiles().Any()) + if (ProfileItem.LoadAllProfiles().Any()) { - Profile.UpdateCurrentProfile(); + ProfileItem.UpdateCurrentProfile(); - foreach (var profile in Profile.LoadAllProfiles()) + foreach (var profile in ProfileItem.LoadAllProfiles()) { extensionMenu.DropDownItems.Add(CreateProfileMenu(profile)); } @@ -52,7 +52,7 @@ namespace HeliosPlus.ShellExtension return explorerMenu; } - private ToolStripMenuItem CreateProfileMenu(Profile profile) + private ToolStripMenuItem CreateProfileMenu(ProfileItem profile) { var profileMenu = new ToolStripMenuItem(profile.Name, new ProfileIcon(profile).ToBitmap(16, 16)); profileMenu.DropDownItems.Add(new ToolStripMenuItem(Language.Run, null, diff --git a/HeliosPlus.ShellExtension/HeliosSteamUrlMenuExtension.cs b/HeliosPlus.ShellExtension/HeliosSteamUrlMenuExtension.cs index 11ad797..adb8b87 100644 --- a/HeliosPlus.ShellExtension/HeliosSteamUrlMenuExtension.cs +++ b/HeliosPlus.ShellExtension/HeliosSteamUrlMenuExtension.cs @@ -19,7 +19,7 @@ namespace HeliosPlus.ShellExtension { return Helios.IsInstalled && SelectedItemPaths.Count() == 1 && - Profile.LoadAllProfiles().Any() && + ProfileItem.LoadAllProfiles().Any() && ParseSteamAppId() > 0; } @@ -29,11 +29,11 @@ namespace HeliosPlus.ShellExtension var extensionMenu = new ToolStripMenuItem(Language.Open_under_Display_Profile, Properties.Resources.Icon_x16); - if (Profile.LoadAllProfiles().Any()) + if (ProfileItem.LoadAllProfiles().Any()) { - Profile.UpdateCurrentProfile(); + ProfileItem.UpdateCurrentProfile(); - foreach (var profile in Profile.LoadAllProfiles()) + foreach (var profile in ProfileItem.LoadAllProfiles()) { extensionMenu.DropDownItems.Add(CreateProfileMenu(profile)); } @@ -53,7 +53,7 @@ namespace HeliosPlus.ShellExtension return explorerMenu; } - private ToolStripMenuItem CreateProfileMenu(Profile profile) + private ToolStripMenuItem CreateProfileMenu(ProfileItem profile) { var appId = ParseSteamAppId(); var profileMenu = new ToolStripMenuItem(profile.Name, new ProfileIcon(profile).ToBitmap(16, 16)); diff --git a/HeliosPlus/DisplayRepresentation.cs b/HeliosPlus/DisplayRepresentation.cs index a03f215..9bea825 100644 --- a/HeliosPlus/DisplayRepresentation.cs +++ b/HeliosPlus/DisplayRepresentation.cs @@ -48,7 +48,7 @@ namespace HeliosPlus public DisplayPossibleSetting[] PossibleSettings { get; } - public static IEnumerable GetDisplays(Profile profile = null) + public static IEnumerable GetDisplays(ProfileItem profile = null) { //var displays = // Display.GetDisplays() @@ -77,12 +77,12 @@ namespace HeliosPlus return Display.GetDisplays().FirstOrDefault(display => display.DevicePath.StartsWith(Path)); } - public ProfileViewport GetPathSource(Profile profile) + public ProfileViewport GetPathSource(ProfileItem profile) { return profile.Viewports.FirstOrDefault(path => path.TargetDisplays.Any(target => target.DevicePath == Path)); } - public ProfileViewportTargetDisplay GetPathTarget(Profile profile) + public ProfileViewportTargetDisplay GetPathTarget(ProfileItem profile) { return profile.Viewports.SelectMany(path => path.TargetDisplays).FirstOrDefault(target => target.DevicePath == Path); } @@ -96,7 +96,7 @@ namespace HeliosPlus .FirstOrDefault(); } - public Bitmap ToBitmap(Size size, Profile profile = null) + public Bitmap ToBitmap(Size size, ProfileItem profile = null) { var targetInfo = GetTargetInfo(); var resolution = Size.Empty; @@ -115,7 +115,7 @@ namespace HeliosPlus } } - var p = new Profile {Viewports = new ProfileViewport[1]}; + var p = new ProfileItem {Viewports = new ProfileViewport[1]}; p.Viewports[0] = new ProfileViewport { Resolution = resolution, diff --git a/HeliosPlus/HeliosPlus.csproj b/HeliosPlus/HeliosPlus.csproj index 5a7b318..e9a7aaa 100644 --- a/HeliosPlus/HeliosPlus.csproj +++ b/HeliosPlus/HeliosPlus.csproj @@ -77,7 +77,8 @@ - + + @@ -145,6 +146,7 @@ DisplayProfileForm.cs + Designer ResXFileCodeGenerator @@ -156,6 +158,7 @@ ShortcutLibraryForm.cs + Designer diff --git a/HeliosPlus/IconUtils.cs b/HeliosPlus/IconUtils.cs new file mode 100644 index 0000000..3f44abd --- /dev/null +++ b/HeliosPlus/IconUtils.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; + +namespace IconUtils +{ + internal static class ExtractIcon + { + [UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = true, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + internal delegate bool ENUMRESNAMEPROC(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam); + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags); + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, IntPtr lpType); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr LockResource(IntPtr hResData); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo); + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + [SuppressUnmanagedCodeSecurity] + public static extern bool EnumResourceNames(IntPtr hModule, IntPtr lpszType, ENUMRESNAMEPROC lpEnumFunc, IntPtr lParam); + + + private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002; + private readonly static IntPtr RT_ICON = (IntPtr)3; + private readonly static IntPtr RT_GROUP_ICON = (IntPtr)14; + + public static Icon ExtractIconFromExecutable(string path) + { + IntPtr hModule = LoadLibraryEx(path, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE); + var tmpData = new List(); + + ENUMRESNAMEPROC callback = (h, t, name, l) => + { + var dir = GetDataFromResource(hModule, RT_GROUP_ICON, name); + + // Calculate the size of an entire .icon file. + + int count = BitConverter.ToUInt16(dir, 4); // GRPICONDIR.idCount + int len = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count + for (int i = 0; i < count; ++i) + len += BitConverter.ToInt32(dir, 6 + 14 * i + 8); // GRPICONDIRENTRY.dwBytesInRes + + using (var dst = new BinaryWriter(new MemoryStream(len))) + { + // Copy GRPICONDIR to ICONDIR. + + dst.Write(dir, 0, 6); + + int picOffset = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count + + for (int i = 0; i < count; ++i) + { + // Load the picture. + + ushort id = BitConverter.ToUInt16(dir, 6 + 14 * i + 12); // GRPICONDIRENTRY.nID + var pic = GetDataFromResource(hModule, RT_ICON, (IntPtr)id); + + // Copy GRPICONDIRENTRY to ICONDIRENTRY. + + dst.Seek(6 + 16 * i, 0); + + dst.Write(dir, 6 + 14 * i, 8); // First 8bytes are identical. + dst.Write(pic.Length); // ICONDIRENTRY.dwBytesInRes + dst.Write(picOffset); // ICONDIRENTRY.dwImageOffset + + // Copy a picture. + + dst.Seek(picOffset, 0); + dst.Write(pic, 0, pic.Length); + + picOffset += pic.Length; + } + + tmpData.Add(((MemoryStream)dst.BaseStream).ToArray()); + } + return true; + }; + EnumResourceNames(hModule, RT_GROUP_ICON, callback, IntPtr.Zero); + byte[][] iconData = tmpData.ToArray(); + using (var ms = new MemoryStream(iconData[0])) + { + return new Icon(ms); + } + } + private static byte[] GetDataFromResource(IntPtr hModule, IntPtr type, IntPtr name) + { + // Load the binary data from the specified resource. + + IntPtr hResInfo = FindResource(hModule, name, type); + + IntPtr hResData = LoadResource(hModule, hResInfo); + + IntPtr pResData = LockResource(hResData); + + uint size = SizeofResource(hModule, hResInfo); + + byte[] buf = new byte[size]; + Marshal.Copy(pResData, buf, 0, buf.Length); + + return buf; + } + } +} \ No newline at end of file diff --git a/HeliosPlus/Program.cs b/HeliosPlus/Program.cs index 87d98d0..53bd113 100644 --- a/HeliosPlus/Program.cs +++ b/HeliosPlus/Program.cs @@ -34,10 +34,10 @@ namespace HeliosPlus { //internal static string ShortcutIconCachePath; - internal static Profile GetProfile(string profileName) + internal static ProfileItem GetProfile(string profileName) { // Create an array of display profiles we have - var profiles = Profile.LoadAllProfiles().ToArray(); + var profiles = ProfileItem.LoadAllProfiles().ToArray(); // Check if the user supplied a --profile option using the profiles' ID var profileIndex = profiles.Length > 0 ? Array.FindIndex(profiles, p => p.Id.Equals(profileName, StringComparison.InvariantCultureIgnoreCase)) : -1; // If the profileID wasn't there, maybe they used the profile name? @@ -50,7 +50,7 @@ namespace HeliosPlus { return profiles[profileIndex]; } - internal static bool GoProfile(Profile profile) + internal static bool GoProfile(ProfileItem profile) { if (profile.IsActive) { @@ -92,12 +92,12 @@ namespace HeliosPlus { } } - private static void EditProfile(Profile profile) + private static void EditProfile(ProfileItem profile) { // Get the status of the thing IPCService.GetInstance().Status = InstanceStatus.User; // Load all the profiles from JSON - Profile.LoadAllProfiles().ToArray(); + ProfileItem.LoadAllProfiles().ToArray(); // Start up the DisplayProfileForm directly new DisplayProfileForm(profile).ShowDialog(); // Then we close down as we're only here to edit one profile @@ -268,9 +268,9 @@ namespace HeliosPlus { } - private static void SwitchToExecutable(Profile profile, string executableToRun, string processToMonitor, uint timeout, string executableArguments) + private static void SwitchToExecutable(ProfileItem profile, string executableToRun, string processToMonitor, uint timeout, string executableArguments) { - var rollbackProfile = Profile.CurrentProfile; + var rollbackProfile = ProfileItem.CurrentProfile; if (!profile.IsPossible) { @@ -372,7 +372,7 @@ namespace HeliosPlus { - private static void SwitchToSteamGame(Profile profile, string steamGameIdToRun, uint timeout, string steamGameArguments) + private static void SwitchToSteamGame(ProfileItem profile, string steamGameIdToRun, uint timeout, string steamGameArguments) { // Convert the steamGameIdToRun string to a uint for Steam Games @@ -383,7 +383,7 @@ namespace HeliosPlus { } // Save the profile we're on now - var rollbackProfile = Profile.CurrentProfile; + var rollbackProfile = ProfileItem.CurrentProfile; // Check that the profile we've been asked to change to will actually work if (!profile.IsPossible) @@ -512,10 +512,10 @@ namespace HeliosPlus { } - private static void SwitchToUplayGame(Profile profile, string uplayGameIdToRun, uint timeout, string uplayGameArguments) + private static void SwitchToUplayGame(ProfileItem profile, string uplayGameIdToRun, uint timeout, string uplayGameArguments) { - var rollbackProfile = Profile.CurrentProfile; + var rollbackProfile = ProfileItem.CurrentProfile; if (!profile.IsPossible) { @@ -641,9 +641,9 @@ namespace HeliosPlus { // ReSharper disable once CyclomaticComplexity - private static void SwitchToProfile(Profile profile) + private static void SwitchToProfile(ProfileItem profile) { - var rollbackProfile = Profile.CurrentProfile; + var rollbackProfile = ProfileItem.CurrentProfile; if ( IPCClient.QueryAll() diff --git a/HeliosPlus/Shortcut.cs b/HeliosPlus/ShortcutItem.cs similarity index 54% rename from HeliosPlus/Shortcut.cs rename to HeliosPlus/ShortcutItem.cs index 0181389..fc0007f 100644 --- a/HeliosPlus/Shortcut.cs +++ b/HeliosPlus/ShortcutItem.cs @@ -5,8 +5,10 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Drawing; +using System.Drawing.Drawing2D; using System.Drawing.IconLib; using System.Drawing.Imaging; +using TsudaKageyu; using System.Globalization; using System.IO; using System.Linq; @@ -31,22 +33,23 @@ namespace HeliosPlus NoGame, } - public class Shortcut + public class ShortcutItem { - private static List _allSavedShortcuts = new List(); + private static List _allSavedShortcuts = new List(); private MultiIcon _shortcutIcon, _originalIcon = null; private Bitmap _shortcutBitmap, _originalBitmap = null; - private Profile _profileToUse = null; + private ProfileItem _profileToUse = null; + private string _originalIconPath = ""; private uint _id = 0; private string _profileName = ""; private bool _isPossible = false; - public Shortcut() + public ShortcutItem() { } - public Shortcut(Profile profile) : this() + public ShortcutItem(ProfileItem profile) : this() { ProfileToUse = profile; } @@ -70,18 +73,39 @@ namespace HeliosPlus public string Name { get; set; } = ""; [JsonIgnore] - public Profile ProfileToUse { get; set; } = null; + public ProfileItem ProfileToUse { + get + { + return _profileToUse; + } + set + { + if (value is ProfileItem) + { + _profileToUse = value; + _profileName = _profileToUse.Name; + // And if we have the _originalBitmap we can also save the Bitmap overlay, but only if the ProfileToUse is set + if (_originalBitmap is Bitmap) + _shortcutBitmap = ToBitmapOverlay(_originalBitmap, ProfileToUse.ProfileTightestBitmap,256,256); + } + } + } public string ProfileName { get { - if (ProfileToUse is Profile) - _profileName = ProfileToUse.Name; return _profileName; } set { _profileName = value; + + // We try to find and set the ProfileTouse + foreach (ProfileItem profileToTest in ProfileItem.AllSavedProfiles) + { + if (profileToTest.Name.Equals(_profileName)) + _profileToUse = profileToTest; + } } } @@ -113,7 +137,28 @@ namespace HeliosPlus public bool GameArgumentsRequired { get; set; } = false; - public string OriginalIconPath { get; set; } = ""; + public string OriginalIconPath { + get + { + if (String.IsNullOrEmpty(_originalIconPath)) + return null; + + return _originalIconPath; + } + + set + { + _originalIconPath = value; + + // We now force creation of the bitmap + // straight away, so we know it has already been done. + _originalBitmap = ToBitmapFromIcon(_originalIconPath); + + // And we do the same for the Bitmap overlay, but only if the ProfileToUse is set + if (ProfileToUse is ProfileItem) + _shortcutBitmap = ToBitmapOverlay(_originalBitmap, ProfileToUse.ProfileTightestBitmap, 256, 256); + } + } //[JsonConverter(typeof(CustomBitmapConverter))] [JsonIgnore] @@ -121,18 +166,14 @@ namespace HeliosPlus { get { - if (_originalBitmap != null) + if (_originalBitmap is Bitmap) return _originalBitmap; else { if (String.IsNullOrEmpty(OriginalIconPath)) return null; - Icon icoAppIcon = Icon.ExtractAssociatedIcon(OriginalIconPath); - // We first try high quality icons - _originalBitmap = ExtractVistaIcon(icoAppIcon); - if (_originalBitmap == null) - _originalBitmap = icoAppIcon.ToBitmap(); - return _originalBitmap; + + return ToBitmapFromIcon(OriginalIconPath); } } @@ -148,7 +189,7 @@ namespace HeliosPlus { get { - if (_shortcutBitmap != null) + if (_shortcutBitmap is Bitmap) return _shortcutBitmap; else { @@ -159,7 +200,9 @@ namespace HeliosPlus if (OriginalBitmap == null) return null; - _shortcutBitmap = new ProfileIcon(ProfileToUse).ToBitmapOverlay(OriginalBitmap,128 ,128); + //_shortcutBitmap = new ProfileIcon(ProfileToUse).ToBitmapOverlay(OriginalBitmap,128 ,128); + _shortcutBitmap = ToBitmapOverlay(_originalBitmap, ProfileToUse.ProfileTightestBitmap, 256, 256); + _shortcutBitmap.Save(Path.Combine(Program.AppDataPath, @"ShortcutOverlay.png"), ImageFormat.Png); return _shortcutBitmap; } } @@ -186,10 +229,9 @@ namespace HeliosPlus } } - - public bool CopyTo (Shortcut shortcut, bool overwriteId = false) + public bool CopyTo (ShortcutItem shortcut, bool overwriteId = false) { - if (!(shortcut is Shortcut)) + if (!(shortcut is ShortcutItem)) return false; if (overwriteId) @@ -222,7 +264,6 @@ namespace HeliosPlus return true; } - public static Bitmap ExtractVistaIcon(Icon icoIcon) { Bitmap bmpPngExtracted = null; @@ -256,6 +297,228 @@ namespace HeliosPlus return bmpPngExtracted; } + /* public Bitmap ToBitmap(int width = 256, int height = 256, PixelFormat format = PixelFormat.Format32bppArgb) + { + var bitmap = new Bitmap(width, height, format); + bitmap.MakeTransparent(); + + using (var g = Graphics.FromImage(bitmap)) + { + g.SmoothingMode = SmoothingMode.HighQuality; + g.DrawImage(g, width, height); + } + + return bitmap; + }*/ + + private Bitmap ToBitmapFromExe(string fileNameAndPath) + { + /* IconExtractor ie = new IconExtractor(fileNameAndPath); + Icon[] allIcons = ie.GetAllIcons(); + Icon biggestIcon = allIcons.OrderByDescending(item => item.Size).First(); + //_originalBitmap = ExtractVistaIcon(biggestIcon); + Bitmap bitmapToReturn = IconUtil.ToBitmap(biggestIcon); + if (bitmapToReturn == null) + bitmapToReturn = biggestIcon.ToBitmap(); + return bitmapToReturn; + */ + + Icon exeIcon = IconUtils.ExtractIcon.ExtractIconFromExecutable(fileNameAndPath); + Bitmap bitmapToReturn = exeIcon.ToBitmap(); + exeIcon.Dispose(); + return bitmapToReturn; + } + + private Bitmap ToBitmapFromIcon(string fileNameAndPath) + { + Icon icoIcon = new Icon(fileNameAndPath, 256, 256); + //_originalBitmap = ExtractVistaIcon(biggestIcon); + Bitmap bitmapToReturn = icoIcon.ToBitmap(); + icoIcon.Dispose(); + return bitmapToReturn; + } + + + private Bitmap ToBitmapOverlay(Bitmap originalBitmap, Bitmap overlayBitmap, int width, int height, PixelFormat format = PixelFormat.Format32bppArgb) + { + + if (!(width is int) || width <= 0) + return null; + + if (!(height is int) || height <= 0) + return null; + + // Make a new empoty bitmap of the wanted size + var combinedBitmap = new Bitmap(width, height, format); + combinedBitmap.MakeTransparent(); + + using (var g = Graphics.FromImage(combinedBitmap)) + { + + g.SmoothingMode = SmoothingMode.None; + g.InterpolationMode = InterpolationMode.NearestNeighbor; + g.PixelOffsetMode = PixelOffsetMode.HighQuality; + g.CompositingQuality = CompositingQuality.AssumeLinear; + + // Resize the originalBitmap if needed + if (originalBitmap.Width > width || originalBitmap.Height > height) + { + + + float originalBitmapRatio = (float) originalBitmap.Width / (float) originalBitmap.Height; + float newWidth, newHeight, newX, newY; + if (originalBitmap.Width > width) + { + // We need to shrink down until Height fits + newWidth = width; + newHeight = originalBitmap.Height * originalBitmapRatio; + newX = 0; + newY = (height - newHeight) / 2; + } else + { + // We need to shrink down until Width fits + newWidth = originalBitmap.Width * originalBitmapRatio; + newHeight = height; + newX = (width - newWidth) / 2; + newY = 0; + } + g.DrawImage(originalBitmap, newX, newY, newWidth, newHeight); + } + else + g.DrawImage(originalBitmap, 0, 0, width, height); + + float overlayBitmapRatio = (float) overlayBitmap.Width / (float) overlayBitmap.Height; + float overlayWidth, overlayHeight, overlayX, overlayY; + string mode = + if (overlayBitmap.Width > width && overlayBitmap.Height < height) + { + // We need to shrink down until Height fits + + overlayHeight = overlayWidth * overlayBitmapRatio; + overlayX = width - overlayWidth; + overlayY = height - overlayHeight; + } + else if (overlayBitmap.Width < width && overlayBitmap.Height > height) + { + // We need to shrink down until Width fits + overlayHeight = (height * 0.7F); + overlayWidth = overlayHeight * (1 / overlayBitmapRatio); + overlayX = width - overlayWidth; + overlayY = height - overlayHeight; + } + else if (overlayBitmap.Width > width && overlayBitmap.Height > height) + { + // We need to shrink down until Width and Height fits + + overlayHeight = (height * 0.7F); + overlayWidth = overlayHeight * (1 / overlayBitmapRatio); + overlayX = width - overlayWidth; + overlayY = height - overlayHeight; + } + + + if (overlayBitmap.Width > width && overlayBitmap.Height < height) + { + // We need to shrink down until Height fits + overlayWidth = (width * 0.7F); + overlayHeight = overlayWidth * overlayBitmapRatio; + overlayX = width - overlayWidth; + overlayY = height - overlayHeight; + } + else if (overlayBitmap.Width < width && overlayBitmap.Height > height) + { + // We need to shrink down until Width fits + overlayHeight = (height * 0.7F); + overlayWidth = overlayHeight * (1/overlayBitmapRatio); + overlayX = width - overlayWidth; + overlayY = height - overlayHeight; + } + else if (overlayBitmap.Width > width && overlayBitmap.Height > height) + { + // We need to shrink down until Width and Height fits + + overlayHeight = (height * 0.7F); + overlayWidth = overlayHeight * (1 / overlayBitmapRatio); + overlayX = width - overlayWidth; + overlayY = height - overlayHeight; + } + g.DrawImage(overlayBitmap, overlayX, overlayY, overlayWidth, overlayHeight); + + } + return combinedBitmap; + } + + public MultiIcon ToIcon() + { + var iconSizes = new[] + { + new Size(256, 256), + new Size(64, 64), + new Size(48, 48), + new Size(32, 32), + new Size(24, 24), + new Size(16, 16) + }; + var multiIcon = new MultiIcon(); + var icon = multiIcon.Add("Icon1"); + + foreach (var size in iconSizes) + { + Bitmap bitmap = new Bitmap(size.Width, size.Height); + using (var g = Graphics.FromImage(bitmap)) + { + g.SmoothingMode = SmoothingMode.None; + g.InterpolationMode = InterpolationMode.NearestNeighbor; + g.PixelOffsetMode = PixelOffsetMode.HighQuality; + g.CompositingQuality = CompositingQuality.AssumeLinear; + g.DrawImage(_originalBitmap, new Rectangle(0, 0, size.Width, size.Height)); + } + + icon.Add(bitmap); + + if (size.Width >= 256 && size.Height >= 256) + { + icon[icon.Count - 1].IconImageFormat = IconImageFormat.PNG; + } + bitmap.Dispose(); + } + + multiIcon.SelectedIndex = 0; + + return multiIcon; + } + + public MultiIcon ToIconOverlay() + { + var iconSizes = new[] + { + new Size(256, 256), + new Size(64, 64), + new Size(48, 48), + new Size(32, 32), + new Size(24, 24), + new Size(16, 16) + }; + var multiIcon = new MultiIcon(); + var icon = multiIcon.Add("Icon1"); + + foreach (var size in iconSizes) + { + Bitmap bitmapOverlay = ToBitmapOverlay(_originalBitmap, ProfileToUse.ProfileTightestBitmap, size.Width, size.Height); + icon.Add(bitmapOverlay); + + if (size.Width >= 256 && size.Height >= 256) + { + icon[icon.Count - 1].IconImageFormat = IconImageFormat.PNG; + } + + bitmapOverlay.Dispose(); + } + + multiIcon.SelectedIndex = 0; + + return multiIcon; + } // ReSharper disable once FunctionComplexityOverflow // ReSharper disable once CyclomaticComplexity diff --git a/HeliosPlus/ShortcutRepository.cs b/HeliosPlus/ShortcutRepository.cs index 33edc84..7208a4b 100644 --- a/HeliosPlus/ShortcutRepository.cs +++ b/HeliosPlus/ShortcutRepository.cs @@ -18,7 +18,7 @@ namespace HeliosPlus { #region Class Variables // Common items to the class - private static List _allShortcuts = new List(); + private static List _allShortcuts = new List(); public static Version Version = new Version(1, 0, 0); // Other constants that are useful private static string _shortcutStorageJsonPath = Path.Combine(Program.AppDataPath, $"Shortcuts"); @@ -38,21 +38,21 @@ namespace HeliosPlus if (LoadShortcuts() && ShortcutCount > 0) { // Work out the starting NextShortcutId value - long max = _allShortcuts.Max(item => item.Id); + long max = _allShortcuts.Max(item => item.Id); _lastShortcutId = Convert.ToUInt32(max); } else _lastShortcutId = 0; } - public ShortcutRepository(Shortcut shortcut) : this() + public ShortcutRepository(ShortcutItem shortcut) : this() { - if (shortcut is Shortcut) + if (shortcut is ShortcutItem) AddShortcut(shortcut); } #endregion #region Class Properties - public static List AllShortcuts + public static List AllShortcuts { get { @@ -61,7 +61,7 @@ namespace HeliosPlus if (LoadShortcuts() && ShortcutCount > 0) { // Work out the starting NextShortcutId value - long max = _allShortcuts.Max(item => item.Id); + long max = _allShortcuts.Max(item => item.Id); _lastShortcutId = Convert.ToUInt32(max); } else @@ -83,9 +83,9 @@ namespace HeliosPlus #endregion #region Class Methods - public static bool AddShortcut(Shortcut shortcut) + public static bool AddShortcut(ShortcutItem shortcut) { - if (!(shortcut is Shortcut)) + if (!(shortcut is ShortcutItem)) return false; // Doublecheck if it already exists @@ -93,7 +93,7 @@ namespace HeliosPlus if (ContainsShortcut(shortcut)) { // We update the existing Shortcut with the data over - Shortcut shortcutToUpdate = GetShortcut(shortcut.Id); + ShortcutItem shortcutToUpdate = GetShortcut(shortcut.Id); shortcut.CopyTo(shortcutToUpdate); } else @@ -118,14 +118,14 @@ namespace HeliosPlus } - public static bool RemoveShortcut(Shortcut shortcut) + public static bool RemoveShortcut(ShortcutItem shortcut) { - if (!(shortcut is Shortcut)) + if (!(shortcut is ShortcutItem)) return false; // Remove the Shortcut Icons from the Cache - List shortcutsToRemove = _allShortcuts.FindAll(item => item.Id.Equals(shortcut.Id)); - foreach (Shortcut shortcutToRemove in shortcutsToRemove) + List shortcutsToRemove = _allShortcuts.FindAll(item => item.Id.Equals(shortcut.Id)); + foreach (ShortcutItem shortcutToRemove in shortcutsToRemove) { try { @@ -158,8 +158,8 @@ namespace HeliosPlus return false; // Remove the Shortcut Icons from the Cache - List shortcutsToRemove = _allShortcuts.FindAll(item => item.Name.Equals(shortcutName)); - foreach (Shortcut shortcutToRemove in shortcutsToRemove) + List shortcutsToRemove = _allShortcuts.FindAll(item => item.Name.Equals(shortcutName)); + foreach (ShortcutItem shortcutToRemove in shortcutsToRemove) { try { @@ -192,8 +192,8 @@ namespace HeliosPlus return false; // Remove the Shortcut Icons from the Cache - List shortcutsToRemove = _allShortcuts.FindAll(item => item.Id.Equals(shortcutId)); - foreach (Shortcut shortcutToRemove in shortcutsToRemove) + List shortcutsToRemove = _allShortcuts.FindAll(item => item.Id.Equals(shortcutId)); + foreach (ShortcutItem shortcutToRemove in shortcutsToRemove) { try { @@ -220,12 +220,12 @@ namespace HeliosPlus } - public static bool ContainsShortcut(Shortcut shortcut) + public static bool ContainsShortcut(ShortcutItem shortcut) { - if (!(shortcut is Shortcut)) + if (!(shortcut is ShortcutItem)) return false; - foreach (Shortcut testShortcut in _allShortcuts) + foreach (ShortcutItem testShortcut in _allShortcuts) { if (testShortcut.Id.Equals(shortcut.Id)) return true; @@ -239,7 +239,7 @@ namespace HeliosPlus if (String.IsNullOrWhiteSpace(shortcutName)) return false; - foreach (Shortcut testShortcut in _allShortcuts) + foreach (ShortcutItem testShortcut in _allShortcuts) { if (testShortcut.Name.Equals(shortcutName)) return true; @@ -254,7 +254,7 @@ namespace HeliosPlus if (shortcutId == 0) return true; - foreach (Shortcut testShortcut in _allShortcuts) + foreach (ShortcutItem testShortcut in _allShortcuts) { if (testShortcut.Id.Equals(shortcutId)) return true; @@ -265,12 +265,12 @@ namespace HeliosPlus } - public static Shortcut GetShortcut(string shortcutName) + public static ShortcutItem GetShortcut(string shortcutName) { if (String.IsNullOrWhiteSpace(shortcutName)) return null; - foreach (Shortcut testShortcut in _allShortcuts) + foreach (ShortcutItem testShortcut in _allShortcuts) { if (testShortcut.Name.Equals(shortcutName)) return testShortcut; @@ -279,12 +279,12 @@ namespace HeliosPlus return null; } - public static Shortcut GetShortcut(uint shortcutId) + public static ShortcutItem GetShortcut(uint shortcutId) { if (shortcutId == 0) return null; - foreach (Shortcut testShortcut in _allShortcuts) + foreach (ShortcutItem testShortcut in _allShortcuts) { if (testShortcut.Id.Equals(shortcutId)) return testShortcut; @@ -309,10 +309,10 @@ namespace HeliosPlus if (!string.IsNullOrWhiteSpace(json)) { - List shortcuts = new List(); + List shortcuts = new List(); try { - _allShortcuts = JsonConvert.DeserializeObject>(json, new JsonSerializerSettings + _allShortcuts = JsonConvert.DeserializeObject>(json, new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore, NullValueHandling = NullValueHandling.Ignore, @@ -327,9 +327,9 @@ namespace HeliosPlus } // Lookup all the Profile Names in the Saved Profiles - foreach (Shortcut updatedShortcut in _allShortcuts) + foreach (ShortcutItem updatedShortcut in _allShortcuts) { - foreach (Profile profile in Profile.AllSavedProfiles) + foreach (ProfileItem profile in ProfileItem.AllSavedProfiles) { if (profile.Name.Equals(updatedShortcut.ProfileName)) @@ -387,7 +387,7 @@ namespace HeliosPlus return false; } - private static void SaveShortcutIconToCache(Shortcut shortcut) + private static void SaveShortcutIconToCache(ShortcutItem shortcut) { // Only add the rest of the options if the permanence is temporary @@ -431,14 +431,15 @@ namespace HeliosPlus MultiIcon shortcutIcon; try { - shortcutIcon = new ProfileIcon(shortcut.ProfileToUse).ToIconOverlay(shortcut.OriginalIconPath); + //shortcutIcon = new ProfileIcon(shortcut.ProfileToUse).ToIconOverlay(shortcut.OriginalIconPath); + shortcutIcon = shortcut.ToIconOverlay(); shortcutIcon.Save(shortcut.SavedShortcutIconCacheFilename, MultiIconFormat.ICO); } catch (Exception ex) { // If we fail to create an icon based on the original executable or game // Then we use the standard HeliosPlus profile one. - shortcutIcon = new ProfileIcon(shortcut.ProfileToUse).ToIcon(); + shortcutIcon = shortcut.ProfileToUse.ProfileIcon.ToIcon(); shortcutIcon.Save(shortcut.SavedShortcutIconCacheFilename, MultiIconFormat.ICO); } } diff --git a/HeliosPlus/UIForms/DisplayProfileForm.cs b/HeliosPlus/UIForms/DisplayProfileForm.cs index 07b7272..396a616 100644 --- a/HeliosPlus/UIForms/DisplayProfileForm.cs +++ b/HeliosPlus/UIForms/DisplayProfileForm.cs @@ -13,11 +13,11 @@ namespace HeliosPlus.UIForms { internal partial class DisplayProfileForm : Form { - private Profile _selectedProfile; - private List _savedProfiles = new List(); + private ProfileItem _selectedProfile; + private List _savedProfiles = new List(); private string _saveOrRenameMode = "save"; private static bool _inDialog = false; - private static Profile _profileToLoad = null; + private static ProfileItem _profileToLoad = null; private ProfileAdaptor _profileAdaptor; public DisplayProfileForm() @@ -27,7 +27,7 @@ namespace HeliosPlus.UIForms _profileAdaptor = new ProfileAdaptor(); } - public DisplayProfileForm(Profile profileToLoad) : this() + public DisplayProfileForm(ProfileItem profileToLoad) : this() { _profileToLoad = profileToLoad; } @@ -85,7 +85,7 @@ namespace HeliosPlus.UIForms if (MessageBox.Show($"Are you sure you want to delete the '{_selectedProfile.Name}' Display Profile?", $"Delete '{_selectedProfile.Name}' Display Profile?", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.No) return; - Profile profileToDelete = _selectedProfile; + ProfileItem profileToDelete = _selectedProfile; string profileToDeleteFilename = _selectedProfile.SavedProfileCacheFilename; // remove the profile from the imagelistview @@ -120,7 +120,7 @@ namespace HeliosPlus.UIForms ilv_saved_profiles.Items[ilvItemToSelect].Selected = true; // select the - foreach (Profile newSelectedProfile in _savedProfiles) + foreach (ProfileItem newSelectedProfile in _savedProfiles) { if (newSelectedProfile.Name.Equals(ilv_saved_profiles.Items[ilvItemToSelect].Text)) { @@ -132,13 +132,13 @@ namespace HeliosPlus.UIForms { // We now only have an unsaved current profile, and no saved ones // So we need to change the mode - ChangeSelectedProfile(Profile.CurrentProfile); + ChangeSelectedProfile(ProfileItem.CurrentProfile); } // Then save the profiles so we always have it updated // Generating the imagelistview images automatically as we save. - Profile.SaveAllProfiles(_savedProfiles); + ProfileItem.SaveAllProfiles(_savedProfiles); } private void RefreshDisplayProfileUI() @@ -153,7 +153,7 @@ namespace HeliosPlus.UIForms { ImageListViewItem newItem = null; bool foundCurrentProfileInLoadedProfiles = false; - foreach (Profile loadedProfile in _savedProfiles) + foreach (ProfileItem loadedProfile in _savedProfiles) { bool thisLoadedProfileIsAlreadyHere = (from item in ilv_saved_profiles.Items where item.Text == loadedProfile.Name select item.Text).Any(); if (!thisLoadedProfileIsAlreadyHere) @@ -166,7 +166,7 @@ namespace HeliosPlus.UIForms ilv_saved_profiles.Items.Add(newItem, _profileAdaptor); } - if (Profile.CurrentProfile.Equals(loadedProfile)) + if (ProfileItem.CurrentProfile.Equals(loadedProfile)) { // We have already saved the selected profile! // so we need to show the selected profile @@ -179,7 +179,7 @@ namespace HeliosPlus.UIForms // found a matching profile, then we need to show the current // Profile if (!foundCurrentProfileInLoadedProfiles) - ChangeSelectedProfile(Profile.CurrentProfile); + ChangeSelectedProfile(ProfileItem.CurrentProfile); // Check if we were loading a profile to edit // If so, select that instead of all that other stuff above! @@ -192,7 +192,7 @@ namespace HeliosPlus.UIForms // If there are no profiles at all then we are starting from scratch! // Show the profile in the DV window // Use the current profile name in the label and the save name - ChangeSelectedProfile(Profile.CurrentProfile); + ChangeSelectedProfile(ProfileItem.CurrentProfile); } // Restart updating the saved_profiles listview @@ -213,7 +213,7 @@ namespace HeliosPlus.UIForms // and the app will automatically recognise that things have changed. // Reload the profiles in case we swapped to another program to change it - Profile.UpdateCurrentProfile(); + ProfileItem.UpdateCurrentProfile(); // Refresh the Profile UI RefreshDisplayProfileUI(); } @@ -221,15 +221,15 @@ namespace HeliosPlus.UIForms private void DisplayProfileForm_Load(object sender, EventArgs e) { // Load all the profiles to prepare things - _savedProfiles = (List)Profile.LoadAllProfiles(); + _savedProfiles = (List)ProfileItem.LoadAllProfiles(); // Update the Current Profile - Profile.UpdateCurrentProfile(); + ProfileItem.UpdateCurrentProfile(); // Refresh the Profile UI RefreshDisplayProfileUI(); } - private void ChangeSelectedProfile(Profile profile) + private void ChangeSelectedProfile(ProfileItem profile) { // And we need to update the actual selected profile too! @@ -241,7 +241,7 @@ namespace HeliosPlus.UIForms // And update the save/rename textbox txt_profile_save_name.Text = _selectedProfile.Name; - if (_selectedProfile.Equals(Profile.CurrentProfile)) + if (_selectedProfile.Equals(ProfileItem.CurrentProfile)) { if (_savedProfiles.Contains(_selectedProfile)) { @@ -281,7 +281,7 @@ namespace HeliosPlus.UIForms } - private void RefreshImageListView(Profile profile) + private void RefreshImageListView(ProfileItem profile) { ilv_saved_profiles.ClearSelection(); IEnumerable matchingImageListViewItems = (from item in ilv_saved_profiles.Items where item.Text == profile.Name select item); @@ -305,7 +305,7 @@ namespace HeliosPlus.UIForms } // Check we're not already using the name - foreach (Profile savedProfile in Profile.AllSavedProfiles) + foreach (ProfileItem savedProfile in ProfileItem.AllSavedProfiles) { //if (String.Equals(txt_profile_save_name.Text, savedProfile.Name, StringComparison.InvariantCultureIgnoreCase)) if (savedProfile.Name.Equals(txt_profile_save_name.Text)) @@ -322,7 +322,7 @@ namespace HeliosPlus.UIForms // We're in 'save' mode! // Check we're not already saving this profile - foreach (Profile savedProfile in Profile.AllSavedProfiles) + foreach (ProfileItem savedProfile in ProfileItem.AllSavedProfiles) { //if (String.Equals(txt_profile_save_name.Text, savedProfile.Name, StringComparison.InvariantCultureIgnoreCase)) if (savedProfile.Equals(_selectedProfile)) @@ -394,7 +394,7 @@ namespace HeliosPlus.UIForms // Then save the profiles so we always have it updated // Generating the imagelistview images automatically as we save. - Profile.SaveAllProfiles(_savedProfiles); + ProfileItem.SaveAllProfiles(_savedProfiles); // now update the profiles image listview //ilv_saved_profiles.Refresh(); @@ -403,7 +403,7 @@ namespace HeliosPlus.UIForms private void ilv_saved_profiles_ItemClick(object sender, ItemClickEventArgs e) { - foreach (Profile savedProfile in _savedProfiles) + foreach (ProfileItem savedProfile in _savedProfiles) { if (savedProfile.Name == e.Item.Text) { @@ -416,7 +416,7 @@ namespace HeliosPlus.UIForms private void btn_view_current_Click(object sender, EventArgs e) { // Reload the profiles in case we swapped to another program to change it - Profile.UpdateCurrentProfile(); + ProfileItem.UpdateCurrentProfile(); // Refresh the Profile UI RefreshDisplayProfileUI(); } diff --git a/HeliosPlus/UIForms/ProfileAdaptor.cs b/HeliosPlus/UIForms/ProfileAdaptor.cs index 2630801..5eb930d 100644 --- a/HeliosPlus/UIForms/ProfileAdaptor.cs +++ b/HeliosPlus/UIForms/ProfileAdaptor.cs @@ -45,9 +45,9 @@ namespace HeliosPlus.UIForms { string profileName = key.ToString(); - Profile profileToUse = null; + ProfileItem profileToUse = null; - foreach (Profile profileToTest in Profile.AllSavedProfiles) + foreach (ProfileItem profileToTest in ProfileItem.AllSavedProfiles) { if (profileToTest.Name == profileName) { @@ -58,7 +58,7 @@ namespace HeliosPlus.UIForms if (profileToUse == null) { - profileToUse = Profile.CurrentProfile; + profileToUse = ProfileItem.CurrentProfile; } Image.GetThumbnailImageAbort myCallback = new Image.GetThumbnailImageAbort(() => { return false; }); @@ -139,9 +139,9 @@ namespace HeliosPlus.UIForms try { string profileName = (string)key; - Profile profileToUse = null; + ProfileItem profileToUse = null; - foreach (Profile profileToTest in Profile.AllSavedProfiles) + foreach (ProfileItem profileToTest in ProfileItem.AllSavedProfiles) { if (profileToTest.Name == profileName) { @@ -152,7 +152,7 @@ namespace HeliosPlus.UIForms if (profileToUse == null) { - profileToUse = Profile.CurrentProfile; + profileToUse = ProfileItem.CurrentProfile; } // Get file info diff --git a/HeliosPlus/UIForms/ShortcutAdaptor.cs b/HeliosPlus/UIForms/ShortcutAdaptor.cs index 9cb45c2..2fc6030 100644 --- a/HeliosPlus/UIForms/ShortcutAdaptor.cs +++ b/HeliosPlus/UIForms/ShortcutAdaptor.cs @@ -42,7 +42,7 @@ namespace HeliosPlus.UIForms try { - Shortcut shortcut = (Shortcut) key; + ShortcutItem shortcut = (ShortcutItem) key; if (shortcut == null) { @@ -79,7 +79,7 @@ namespace HeliosPlus.UIForms try { - Shortcut shortcutName = (Shortcut) key; + ShortcutItem shortcutName = (ShortcutItem) key; return shortcutName.Name; } catch @@ -135,7 +135,7 @@ namespace HeliosPlus.UIForms try { - Shortcut shortcut = (Shortcut) key; + ShortcutItem shortcut = (ShortcutItem) key; // Get file info if (shortcut.ShortcutBitmap is Bitmap) diff --git a/HeliosPlus/UIForms/ShortcutForm.cs b/HeliosPlus/UIForms/ShortcutForm.cs index dfa4bd9..5d95001 100644 --- a/HeliosPlus/UIForms/ShortcutForm.cs +++ b/HeliosPlus/UIForms/ShortcutForm.cs @@ -21,9 +21,9 @@ namespace HeliosPlus.UIForms List _allSteamGames; private ProfileAdaptor _profileAdaptor; - private List _loadedProfiles = new List(); - private Profile _profileToUse= null; - private Shortcut _shortcutToEdit = null; + private List _loadedProfiles = new List(); + private ProfileItem _profileToUse= null; + private ShortcutItem _shortcutToEdit = null; private bool _isNewShortcut = false; private bool _isUnsaved = false; private bool _saveNameAutomatic = true; @@ -43,14 +43,14 @@ namespace HeliosPlus.UIForms // existing Shortcut) if (_shortcutToEdit == null) { - _shortcutToEdit = new Shortcut(); + _shortcutToEdit = new ShortcutItem(); _isNewShortcut = true; } } - public ShortcutForm(Shortcut shortcutToEdit) : this() + public ShortcutForm(ShortcutItem shortcutToEdit) : this() { _shortcutToEdit = shortcutToEdit; _isNewShortcut = false; @@ -141,7 +141,7 @@ namespace HeliosPlus.UIForms } } - public Shortcut Shortcut + public ShortcutItem Shortcut { get => _shortcutToEdit; } @@ -269,7 +269,7 @@ namespace HeliosPlus.UIForms } // Check the profile is set and that it's still valid - if (!(_profileToUse is Profile)) + if (!(_profileToUse is ProfileItem)) { MessageBox.Show( @"You need to select a Display Profile to use with this shortcut. Please select one from the list of Display Profiles on the left of the screen.", @@ -471,7 +471,7 @@ namespace HeliosPlus.UIForms private bool canEnableSaveButton() { if ((txt_shortcut_save_name.Text.Length > 0) && - _profileToUse is Profile && + _profileToUse is ProfileItem && (rb_no_game.Checked || rb_launcher.Checked && _gameId > 0 || rb_standalone.Checked && txt_executable.Text.Length > 0)) @@ -491,7 +491,7 @@ namespace HeliosPlus.UIForms private void suggestShortcutName() { - if (_saveNameAutomatic && _profileToUse is Profile) + if (_saveNameAutomatic && _profileToUse is ProfileItem) { if (rb_no_game.Checked) { @@ -588,7 +588,7 @@ namespace HeliosPlus.UIForms } - private void RefreshImageListView(Profile profile) + private void RefreshImageListView(ProfileItem profile) { ilv_saved_profiles.ClearSelection(); IEnumerable matchingImageListViewItems = (from item in ilv_saved_profiles.Items where item.Text == profile.Name select item); @@ -603,12 +603,12 @@ namespace HeliosPlus.UIForms { // Load all the profiles to prepare things - _loadedProfiles = (List)Profile.LoadAllProfiles(); + _loadedProfiles = (List)ProfileItem.LoadAllProfiles(); bool foundCurrentProfileInLoadedProfiles = false; - foreach (Profile loadedProfile in _loadedProfiles) + foreach (ProfileItem loadedProfile in _loadedProfiles) { - if (Profile.CurrentProfile.Equals(loadedProfile)) + if (ProfileItem.CurrentProfile.Equals(loadedProfile)) { // We have already saved the selected profile! // so we need to show the selected profile @@ -647,7 +647,7 @@ namespace HeliosPlus.UIForms Icon icoAppIcon = Icon.ExtractAssociatedIcon(game.GameIconPath); // We first try high quality icons - Bitmap extractedBitmap = Shortcut.ExtractVistaIcon(icoAppIcon); + Bitmap extractedBitmap = ShortcutItem.ExtractVistaIcon(icoAppIcon); if (extractedBitmap == null) extractedBitmap = icoAppIcon.ToBitmap(); il_games.Images.Add(extractedBitmap); @@ -821,7 +821,7 @@ namespace HeliosPlus.UIForms private void ilv_saved_profiles_ItemClick(object sender, ItemClickEventArgs e) { - foreach (Profile loadedProfile in _loadedProfiles) + foreach (ProfileItem loadedProfile in _loadedProfiles) { if (loadedProfile.Name == e.Item.Text) { @@ -831,7 +831,7 @@ namespace HeliosPlus.UIForms } - private void ChangeSelectedProfile(Profile profile) + private void ChangeSelectedProfile(ProfileItem profile) { // If the profile is null then return // (this happens when a new blank shortcut is created @@ -844,7 +844,7 @@ namespace HeliosPlus.UIForms // We also need to load the saved profile name to show the user lbl_profile_shown.Text = _profileToUse.Name; - if (_profileToUse.Equals(Profile.CurrentProfile)) + if (_profileToUse.Equals(ProfileItem.CurrentProfile)) { lbl_profile_shown_subtitle.Text = "(Current Display Profile in use)"; } @@ -881,7 +881,7 @@ namespace HeliosPlus.UIForms ImageListViewItem newItem = null; bool foundCurrentProfileInLoadedProfiles = false; - foreach (Profile loadedProfile in _loadedProfiles) + foreach (ProfileItem loadedProfile in _loadedProfiles) { bool thisLoadedProfileIsAlreadyHere = (from item in ilv_saved_profiles.Items where item.Text == loadedProfile.Name select item.Text).Any(); if (!thisLoadedProfileIsAlreadyHere) @@ -900,7 +900,7 @@ namespace HeliosPlus.UIForms // found a matching profile, then we need to show the current // Profile if (!foundCurrentProfileInLoadedProfiles) - ChangeSelectedProfile(Profile.CurrentProfile); + ChangeSelectedProfile(ProfileItem.CurrentProfile); // Check if we were loading a profile to edit // If so, select that instead of all that other stuff above! diff --git a/HeliosPlus/UIForms/ShortcutLibraryForm.cs b/HeliosPlus/UIForms/ShortcutLibraryForm.cs index a146eb1..c90e693 100644 --- a/HeliosPlus/UIForms/ShortcutLibraryForm.cs +++ b/HeliosPlus/UIForms/ShortcutLibraryForm.cs @@ -22,7 +22,7 @@ namespace HeliosPlus.UIForms private ShortcutAdaptor _shortcutAdaptor; private ImageListViewItem _selectedShortcutILVItem = null; - private Shortcut _selectedShortcut = null; + private ShortcutItem _selectedShortcut = null; private ShortcutRepository _shortcutRepository = new ShortcutRepository(); public ShortcutLibraryForm() @@ -50,7 +50,7 @@ namespace HeliosPlus.UIForms private void ShortcutLibraryForm_Load(object sender, EventArgs e) { // Load all the shortcuts we have saved earlier - List _savedShortcuts = ShortcutRepository.AllShortcuts; + List _savedShortcuts = ShortcutRepository.AllShortcuts; // Refresh the Shortcut Library UI RefreshShortcutLibraryUI(); } @@ -64,28 +64,33 @@ namespace HeliosPlus.UIForms ilv_saved_shortcuts.SuspendLayout(); ImageListViewItem newItem = null; - ilv_saved_shortcuts.Items.Clear(); - foreach (Shortcut loadedShortcut in ShortcutRepository.AllShortcuts) + foreach (ShortcutItem loadedShortcut in ShortcutRepository.AllShortcuts) { - newItem = new ImageListViewItem(loadedShortcut, loadedShortcut.Name); - ilv_saved_shortcuts.Items.Add(newItem, _shortcutAdaptor); - - if (_selectedShortcut != null && _selectedShortcut is Shortcut) - RefreshImageListView(_selectedShortcut); + bool thisLoadedShortcutIsAlreadyHere = (from item in ilv_saved_shortcuts.Items where item.Text == loadedShortcut.Name select item.Text).Any(); + if (!thisLoadedShortcutIsAlreadyHere) + { + //loadedProfile.SaveProfileImageToCache(); + //newItem = new ImageListViewItem(loadedProfile.SavedProfileCacheFilename, loadedProfile.Name); + //newItem = new ImageListViewItem(loadedProfile, loadedProfile.Name); + newItem = new ImageListViewItem(loadedShortcut, loadedShortcut.Name); + //ilv_saved_profiles.Items.Add(newItem); + ilv_saved_shortcuts.Items.Add(newItem, _shortcutAdaptor); + } } + if (_selectedShortcut != null && _selectedShortcut is ShortcutItem) + RefreshImageListView(_selectedShortcut); + // Restart updating the saved_profiles listview ilv_saved_shortcuts.ResumeLayout(); } + // Refresh the image list view - //RefreshImageListView(profile); + //RefreshImageListView(_selectedShortcut); } - - - - private void RefreshImageListView(Shortcut shortcut) + private void RefreshImageListView(ShortcutItem shortcut) { ilv_saved_shortcuts.ClearSelection(); IEnumerable matchingImageListViewItems = (from item in ilv_saved_shortcuts.Items where item.Text == shortcut.Name select item); @@ -98,7 +103,7 @@ namespace HeliosPlus.UIForms } - private Shortcut GetShortcutFromName(string shortcutName) + private ShortcutItem GetShortcutFromName(string shortcutName) { return (from item in ShortcutRepository.AllShortcuts where item.Name == shortcutName select item).First(); } @@ -209,6 +214,11 @@ namespace HeliosPlus.UIForms if (MessageBox.Show($"Are you sure you want to delete the '{_selectedShortcut.Name}' Shortcut?", $"Delete '{_selectedShortcut.Name}' Shortcut?", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.No) return; + // remove the profile from the imagelistview + int currentIlvIndex = ilv_saved_shortcuts.SelectedItems[0].Index; + ilv_saved_shortcuts.Items.RemoveAt(currentIlvIndex); + + // Remove the shortcut ShortcutRepository.RemoveShortcut(_selectedShortcut); _selectedShortcut = null; diff --git a/HeliosPlus/Validators.cs b/HeliosPlus/Validators.cs index 89f4795..1dc1232 100644 --- a/HeliosPlus/Validators.cs +++ b/HeliosPlus/Validators.cs @@ -23,7 +23,7 @@ namespace HeliosPlus var profile = optionProfile.Value(); // Create an array of display profiles we have - var profiles = Profile.LoadAllProfiles().ToArray(); + var profiles = ProfileItem.LoadAllProfiles().ToArray(); // Check if the user supplied a --profile option using the profiles' ID var profileIndex = profiles.Length > 0 ? Array.FindIndex(profiles, p => p.Id.Equals(profile, StringComparison.InvariantCultureIgnoreCase)) : -1; // If the profileID wasn't there, maybe they used the profile name?