diff --git a/DisplayMagician/DesktopNotificationActivator.cs b/DisplayMagician/DesktopNotificationActivator.cs index 0460ac9..4caed1c 100644 --- a/DisplayMagician/DesktopNotificationActivator.cs +++ b/DisplayMagician/DesktopNotificationActivator.cs @@ -31,46 +31,52 @@ namespace DisplayMagician // Parse the query string (using NuGet package QueryString.NET) QueryString args = QueryString.Parse(invokedArgs); - // See what action is being requested - switch (args["action"]) + foreach (QueryStringParameter myArg in args) { - // Open the image - case "open": - - // Open the Main DisplayMagician Window - //OpenWindowIfNeeded(); - Program.AppMainForm.openApplicationWindow(); - - - break; - - // Background: Quick reply to the conversation - case "exit": - - // Exit the application (overriding the close restriction) - Program.AppMainForm.exitApplication(); - - break; - - case "stop": - - MessageBox.Show("User just asked DisplayMagician to stop monitoring the game"); - /*// Get the response the user typed - string msg = userInput["tbReply"]; - - // And send this message - SendMessage(msg); - - // If there's no windows open, exit the app - if (App.Current.Windows.Count == 0) + if (myArg.Name.Equals("action",StringComparison.InvariantCultureIgnoreCase)) + { + // See what action is being requested + switch (args["action"].ToLowerInvariant()) { - Application.Current.Shutdown(); - }*/ + // Open the image + case "open": - break; + // Open the Main DisplayMagician Window + //OpenWindowIfNeeded(); + Program.AppMainForm.openApplicationWindow(); - default: - break; + + break; + + // Background: Quick reply to the conversation + case "exit": + + // Exit the application (overriding the close restriction) + Program.AppMainForm.exitApplication(); + + break; + + case "stop": + + MessageBox.Show("User just asked DisplayMagician to stop monitoring the game"); + /*// Get the response the user typed + string msg = userInput["tbReply"]; + + // And send this message + SendMessage(msg); + + // If there's no windows open, exit the app + if (App.Current.Windows.Count == 0) + { + Application.Current.Shutdown(); + }*/ + + break; + + default: + break; + } + } } }); } diff --git a/DisplayMagician/Program.cs b/DisplayMagician/Program.cs index a090d66..af52eb5 100644 --- a/DisplayMagician/Program.cs +++ b/DisplayMagician/Program.cs @@ -30,6 +30,7 @@ namespace DisplayMagician { internal static class Program { internal static string AppDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DisplayMagician"); + public static string AppStartupPath = Application.StartupPath; public static string AppIconPath = Path.Combine(Program.AppDataPath, $"Icons"); public static string AppProfilePath = Path.Combine(Program.AppDataPath, $"Profiles"); public static string AppShortcutPath = Path.Combine(Program.AppDataPath, $"Shortcuts"); @@ -39,6 +40,7 @@ namespace DisplayMagician { public static string AppSteamIconFilename = Path.Combine(AppIconPath, @"Steam.ico"); public static string AppUplayIconFilename = Path.Combine(AppIconPath, @"Uplay.ico"); public static string AppEpicIconFilename = Path.Combine(AppIconPath, @"Epic.ico"); + public static bool AppToastActivated = false; public static bool WaitingForGameToExit = false; public static ProgramSettings AppProgramSettings; public static MainForm AppMainForm; @@ -133,7 +135,11 @@ namespace DisplayMagician { Application.SetCompatibleTextRenderingDefault(false); - var app = new CommandLineApplication(); + var app = new CommandLineApplication + { + AllowArgumentSeparator = true, + UnrecognizedArgumentHandling = UnrecognizedArgumentHandling.StopParsingAndCollect, + }; //app.Name = "HeliosDM+"; //app.Name = Assembly.GetEntryAssembly().GetName().Name; @@ -210,6 +216,22 @@ namespace DisplayMagician { app.OnExecute(() => { + // Add a workaround to handle the weird way that Windows tell us that DisplayMagician + // was started from a Notification Toast when closed (Windows 10) + // Due to the way that CommandLineUtils library works we need to handle this as + // 'Remaining Arguments' + if (app.RemainingArguments != null && app.RemainingArguments.Count > 0) + { + foreach (string myArg in app.RemainingArguments) + { + if (myArg.Equals("-ToastActivated")) + { + Program.AppToastActivated = true; + break; + } + + } + } Console.WriteLine("Starting Normally..."); StartUpApplication(); return 0; diff --git a/DisplayMagician/Resources/applogo.png b/DisplayMagician/Resources/applogo.png new file mode 100644 index 0000000..e4e35f2 Binary files /dev/null and b/DisplayMagician/Resources/applogo.png differ diff --git a/DisplayMagician/ShortcutRepository.cs b/DisplayMagician/ShortcutRepository.cs index f05e85f..f739551 100644 --- a/DisplayMagician/ShortcutRepository.cs +++ b/DisplayMagician/ShortcutRepository.cs @@ -2,6 +2,7 @@ using DisplayMagician.GameLibraries; using DisplayMagician.InterProcess; using DisplayMagicianShared; +using Microsoft.Toolkit.Uwp.Notifications; using Newtonsoft.Json; using System; using System.Collections.Generic; @@ -14,6 +15,8 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; +using Windows.Data.Xml.Dom; +using Windows.UI.Notifications; namespace DisplayMagician { @@ -567,7 +570,6 @@ namespace DisplayMagician notifyIcon = new NotifyIcon { Icon = Properties.Resources.DisplayMagician, - //Text = string.Format("DisplayMagician: Waiting for the Game {} to exit...", steamGameToRun.Name), Visible = true }; Application.DoEvents(); @@ -592,6 +594,7 @@ namespace DisplayMagician Application.DoEvents(); } + // Now start the main game, and wait if we have to if (shortcutToUse.Category.Equals(ShortcutCategory.Application)) { @@ -654,11 +657,29 @@ namespace DisplayMagician } Application.DoEvents(); + // Now we want to tell the user we're running an application! + // Construct the Windows toast content + ToastContentBuilder tcBuilder = new ToastContentBuilder() + .AddToastActivationInfo("notify=runningApplication", ToastActivationType.Foreground) + .AddText($"Running {processNameToLookFor} Shortcut", hintMaxLines: 1) + .AddText($"Waiting for all {processNameToLookFor} windows to exit..."); + //.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop"); + ToastContent toastContent = tcBuilder.Content; + // Make sure to use Windows.Data.Xml.Dom + var doc = new XmlDocument(); + doc.LoadXml(toastContent.GetContent()); + // And create the toast notification + var toast = new ToastNotification(doc); + // Remove any other Notifications from us + DesktopNotifications.DesktopNotificationManagerCompat.History.Clear(); + // And then show this notification + DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast); + // Wait an extra few seconds to give the application time to settle down Thread.Sleep(2000); // if we have things to monitor, then we should start to wait for them - Console.WriteLine($"Waiting for application {processNameToLookFor} to exit."); + Console.WriteLine($"Waiting for all {processNameToLookFor} windows to exit."); logger.Debug($"ShortcutRepository/RunShortcut - waiting for application {processNameToLookFor} to exit."); if (processesToMonitor.Count > 0) { @@ -734,6 +755,24 @@ namespace DisplayMagician notifyIcon.Text = $"DisplayMagician: Running {steamGameToRun.Name.Substring(0, 41)}..."; Application.DoEvents(); + // Now we want to tell the user we're running a game! + // Construct the Windows toast content + ToastContentBuilder tcBuilder = new ToastContentBuilder() + .AddToastActivationInfo("notify=runningSteamGame", ToastActivationType.Foreground) + .AddText($"Running {shortcutToUse.GameName} Shortcut", hintMaxLines: 1) + .AddText($"Waiting for the Steam Game {shortcutToUse.GameName} to exit..."); + //.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop"); + ToastContent toastContent = tcBuilder.Content; + // Make sure to use Windows.Data.Xml.Dom + var doc = new XmlDocument(); + doc.LoadXml(toastContent.GetContent()); + // And create the toast notification + var toast = new ToastNotification(doc); + // Remove any other Notifications from us + DesktopNotifications.DesktopNotificationManagerCompat.History.Clear(); + // And then show this notification + DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast); + // Wait 5 seconds for the game process to spawn Thread.Sleep(5000); // Wait for the game to exit @@ -807,6 +846,24 @@ namespace DisplayMagician notifyIcon.Text = $"DisplayMagician: Running {uplayGameToRun.Name.Substring(0, 41)}..."; Application.DoEvents(); + // Now we want to tell the user we're running a game! + // Construct the Windows toast content + ToastContentBuilder tcBuilder = new ToastContentBuilder() + .AddToastActivationInfo("notify=runningUplayGame", ToastActivationType.Foreground) + .AddText($"Running {shortcutToUse.GameName} Shortcut", hintMaxLines: 1) + .AddText($"Waiting for the Uplay Game {shortcutToUse.GameName} to exit..."); + //.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop"); + ToastContent toastContent = tcBuilder.Content; + // Make sure to use Windows.Data.Xml.Dom + var doc = new XmlDocument(); + doc.LoadXml(toastContent.GetContent()); + // And create the toast notification + var toast = new ToastNotification(doc); + // Remove any other Notifications from us + DesktopNotifications.DesktopNotificationManagerCompat.History.Clear(); + // And then show this notification + DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast); + // Wait 5 seconds for the game process to spawn Thread.Sleep(5000); @@ -854,6 +911,32 @@ namespace DisplayMagician Application.DoEvents(); } + // Remove any other Notifications from us + DesktopNotifications.DesktopNotificationManagerCompat.History.Clear(); + + // Only replace the notification if we're minimised + if (Program.AppProgramSettings.MinimiseOnStart) + { + // Remind the user that DisplayMagician is running the in background + // Construct the toast content + ToastContentBuilder tcBuilder = new ToastContentBuilder() + .AddToastActivationInfo("notify=minimiseStart&action=open", ToastActivationType.Foreground) + .AddText("DisplayMagician is minimised", hintMaxLines: 1) + .AddButton("Open", ToastActivationType.Background, "notify=minimiseStart&action=open"); + ToastContent toastContent = tcBuilder.Content; + // Make sure to use Windows.Data.Xml.Dom + var doc = new XmlDocument(); + doc.LoadXml(toastContent.GetContent()); + + // And create the toast notification + var toast = new ToastNotification(doc); + toast.SuppressPopup = true; + + // And then show it + DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast); + } + + // Stop the pre-started startPrograms that we'd started earlier if (startProgramsToStop.Count > 0) { diff --git a/DisplayMagician/UIForms/MainForm.Designer.cs b/DisplayMagician/UIForms/MainForm.Designer.cs index ad5f075..ad59a9c 100644 --- a/DisplayMagician/UIForms/MainForm.Designer.cs +++ b/DisplayMagician/UIForms/MainForm.Designer.cs @@ -31,7 +31,6 @@ this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); this.splitContainer1 = new System.Windows.Forms.SplitContainer(); - this.btn_toast = new System.Windows.Forms.Button(); this.btn_settings = new System.Windows.Forms.Button(); this.lbl_create_profile = new System.Windows.Forms.Label(); this.btn_setup_display_profiles = new System.Windows.Forms.Button(); @@ -72,7 +71,6 @@ // // splitContainer1.Panel1 // - this.splitContainer1.Panel1.Controls.Add(this.btn_toast); this.splitContainer1.Panel1.Controls.Add(this.btn_settings); this.splitContainer1.Panel1.Controls.Add(this.lbl_create_profile); this.splitContainer1.Panel1.Controls.Add(this.btn_setup_display_profiles); @@ -88,16 +86,6 @@ this.splitContainer1.Panel2.Controls.Add(this.pb_game_shortcut); this.splitContainer1.TabStop = false; // - // btn_toast - // - resources.ApplyResources(this.btn_toast, "btn_toast"); - this.btn_toast.FlatAppearance.MouseDownBackColor = System.Drawing.Color.IndianRed; - this.btn_toast.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Brown; - this.btn_toast.ForeColor = System.Drawing.Color.White; - this.btn_toast.Name = "btn_toast"; - this.btn_toast.UseVisualStyleBackColor = true; - this.btn_toast.Click += new System.EventHandler(this.btn_toast_Click); - // // btn_settings // resources.ApplyResources(this.btn_settings, "btn_settings"); @@ -315,6 +303,5 @@ private System.Windows.Forms.Label lbl_create_profile; private System.Windows.Forms.Label lbl_create_shortcut; private System.Windows.Forms.Button btn_settings; - private System.Windows.Forms.Button btn_toast; } } \ No newline at end of file diff --git a/DisplayMagician/UIForms/MainForm.cs b/DisplayMagician/UIForms/MainForm.cs index d2b5113..3b82cc8 100644 --- a/DisplayMagician/UIForms/MainForm.cs +++ b/DisplayMagician/UIForms/MainForm.cs @@ -54,9 +54,9 @@ namespace DisplayMagician.UIForms // Remind the user that DisplayMagician is running the in background // Construct the toast content ToastContentBuilder tcBuilder = new ToastContentBuilder() - .AddToastActivationInfo("notify=minimiseStart", ToastActivationType.Foreground) - .AddText("DisplayMagician has started minimised!", hintMaxLines: 1) - .AddButton("Open DisplayMagician", ToastActivationType.Background, "notify=minimiseStart&action=open"); + .AddToastActivationInfo("notify=minimiseStart&action=open", ToastActivationType.Foreground) + .AddText("DisplayMagician is minimised", hintMaxLines: 1) + .AddButton("Open", ToastActivationType.Background, "notify=minimiseStart&action=open"); ToastContent toastContent = tcBuilder.Content; // Make sure to use Windows.Data.Xml.Dom var doc = new XmlDocument(); @@ -65,8 +65,12 @@ namespace DisplayMagician.UIForms // And create the toast notification var toast = new ToastNotification(doc); + // Remove any other Notifications from us + DesktopNotifications.DesktopNotificationManagerCompat.History.Clear(); + // And then show it - DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast); + DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast); + } else { @@ -131,6 +135,9 @@ namespace DisplayMagician.UIForms // And create the toast notification var toast = new ToastNotification(doc); + // Remove any other Notifications from us + DesktopNotifications.DesktopNotificationManagerCompat.History.Clear(); + // And then show it DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast); } @@ -448,24 +455,5 @@ namespace DisplayMagician.UIForms cb_minimise_notification_area.Checked = false; } - private void btn_toast_Click(object sender, EventArgs e) - { - // Construct the toast content - ToastContentBuilder tcBuilder = new ToastContentBuilder() - .AddToastActivationInfo("notify=runningGame", ToastActivationType.Foreground) - .AddText("This is the notification title!", hintMaxLines: 1) - .AddText("This is the description") - .AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop"); - ToastContent toastContent = tcBuilder.Content; - // Make sure to use Windows.Data.Xml.Dom - var doc = new XmlDocument(); - doc.LoadXml(toastContent.GetContent()); - - // And create the toast notification - var toast = new ToastNotification(doc); - - // And then show it - DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast); - } } } diff --git a/DisplayMagician/UIForms/MainForm.resx b/DisplayMagician/UIForms/MainForm.resx index d66daf8..bc8b02f 100644 --- a/DisplayMagician/UIForms/MainForm.resx +++ b/DisplayMagician/UIForms/MainForm.resx @@ -132,39 +132,6 @@ Horizontal - - Top - - - Flat - - - NoControl - - - 364, 12 - - - 75, 23 - - - 8 - - - Show Toast - - - btn_toast - - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - splitContainer1.Panel1 - - - 0 - Top, Right @@ -193,7 +160,7 @@ splitContainer1.Panel1 - 1 + 0 None @@ -226,7 +193,7 @@ splitContainer1.Panel1 - 2 + 1 None @@ -259,7 +226,7 @@ splitContainer1.Panel1 - 3 + 2 Fill @@ -10807,7 +10774,7 @@ splitContainer1.Panel1 - 4 + 3 splitContainer1.Panel1 @@ -10834,7 +10801,7 @@ NoControl - 220, 237 + 220, 239 343, 22 @@ -10873,7 +10840,7 @@ NoControl - 234, 354 + 234, 357 332, 20 @@ -10906,7 +10873,7 @@ Microsoft Sans Serif, 9.75pt - 12, 355 + 12, 358 25, 16 @@ -10942,7 +10909,7 @@ Microsoft Sans Serif, 21.75pt - 212, 164 + 212, 166 360, 50 @@ -10975,7 +10942,7 @@ NoControl - 700, 351 + 700, 354 75, 23 @@ -63407,7 +63374,7 @@ Exit DisplayMagician - 219, 148 + 219, 126 Text diff --git a/Icon3-AppLogo.afphoto b/Icon3-AppLogo.afphoto new file mode 100644 index 0000000..3ca2d1e Binary files /dev/null and b/Icon3-AppLogo.afphoto differ