diff --git a/Greenshot/Helpers/CaptureHelper.cs b/Greenshot/Helpers/CaptureHelper.cs
index 0007727ef..ea7707f1f 100644
--- a/Greenshot/Helpers/CaptureHelper.cs
+++ b/Greenshot/Helpers/CaptureHelper.cs
@@ -552,7 +552,10 @@ namespace Greenshot.Helpers {
notifyIconClassicMessageHandler.ShowErrorMessage(eventArgs.Message, 10000);
break;
case SurfaceMessageTyp.Info:
- notifyIconClassicMessageHandler.ShowInfoMessage(eventArgs.Message, 10000);
+ notifyIconClassicMessageHandler.ShowInfoMessage(eventArgs.Message, 10000, () =>
+ {
+ Log.Info("Clicked!");
+ });
break;
case SurfaceMessageTyp.FileSaved:
case SurfaceMessageTyp.UploadedUri:
diff --git a/Greenshot/releases/innosetup/setup.iss b/Greenshot/releases/innosetup/setup.iss
index 5933fd823..bf4485edf 100644
--- a/Greenshot/releases/innosetup/setup.iss
+++ b/Greenshot/releases/innosetup/setup.iss
@@ -189,10 +189,11 @@ Root: HKLM; Subkey: Software\Classes\Greenshot\DefaultIcon; ValueType: string; V
Root: HKLM; Subkey: Software\Classes\Greenshot\shell\open\command; ValueType: string; ValueName: ""; ValueData: """{app}\Greenshot.EXE"" --openfile ""%1"""; Permissions: admins-modify; Flags: uninsdeletevalue noerror; Check: not IsRegularUser
[Icons]
-Name: {group}\{#ExeName}; Filename: {app}\{#ExeName}.exe; WorkingDir: {app}
-Name: {group}\Uninstall {#ExeName}; Filename: {uninstallexe}; WorkingDir: {app}; AppUserModelID: "{#ExeName}.{#ExeName}"
+Name: {group}\{#ExeName}; Filename: {app}\{#ExeName}.exe; WorkingDir: {app}; AppUserModelID: "{#ExeName}"
+Name: {group}\Uninstall {#ExeName}; Filename: {uninstallexe}; WorkingDir: {app};
Name: {group}\Readme.txt; Filename: {app}\readme.txt; WorkingDir: {app}
Name: {group}\License.txt; Filename: {app}\license.txt; WorkingDir: {app}
+
[Languages]
Name: en; MessagesFile: compiler:Default.isl
Name: cn; MessagesFile: Languages\ChineseSimplified.isl
diff --git a/GreenshotWin10Plugin/Native/DesktopBridgeHelpers.cs b/GreenshotWin10Plugin/Native/DesktopBridgeHelpers.cs
new file mode 100644
index 000000000..0c7728ee0
--- /dev/null
+++ b/GreenshotWin10Plugin/Native/DesktopBridgeHelpers.cs
@@ -0,0 +1,53 @@
+// ******************************************************************
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
+// ******************************************************************
+
+using System.Runtime.InteropServices;
+using System.Text;
+using GreenshotPlugin.Core;
+
+namespace GreenshotWin10Plugin.Native
+{
+ ///
+ /// Code from https://github.com/qmatteoq/DesktopBridgeHelpers/edit/master/DesktopBridge.Helpers/Helpers.cs
+ ///
+ public static class DesktopBridgeHelpers
+ {
+ const long AppModelErrorNoPackage = 15700L;
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
+ static extern int GetCurrentPackageFullName(ref int packageFullNameLength, StringBuilder packageFullName);
+
+ private static bool? _isRunningAsUwp;
+ public static bool IsRunningAsUwp()
+ {
+ if (_isRunningAsUwp != null) return _isRunningAsUwp.Value;
+
+ if (WindowsVersion.IsWindows7OrLower)
+ {
+ _isRunningAsUwp = false;
+ }
+ else
+ {
+ int length = 0;
+ StringBuilder sb = new StringBuilder(0);
+ GetCurrentPackageFullName(ref length, sb);
+
+ sb = new StringBuilder(length);
+ int result = GetCurrentPackageFullName(ref length, sb);
+
+ _isRunningAsUwp = result != AppModelErrorNoPackage;
+ }
+
+ return _isRunningAsUwp.Value;
+ }
+ }
+}
diff --git a/GreenshotWin10Plugin/Native/DesktopNotificationHistoryCompat.cs b/GreenshotWin10Plugin/Native/DesktopNotificationHistoryCompat.cs
new file mode 100644
index 000000000..f536755ab
--- /dev/null
+++ b/GreenshotWin10Plugin/Native/DesktopNotificationHistoryCompat.cs
@@ -0,0 +1,109 @@
+// ******************************************************************
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
+// ******************************************************************
+
+using System.Collections.Generic;
+using Windows.UI.Notifications;
+
+namespace GreenshotWin10Plugin.Native
+{
+ ///
+ /// Manages the toast notifications for an app including the ability the clear all toast history and removing individual toasts.
+ ///
+ public sealed class DesktopNotificationHistoryCompat
+ {
+ private readonly string _applicationUserModelId;
+ private readonly ToastNotificationHistory _history;
+
+ ///
+ /// Do not call this. Instead, call to obtain an instance.
+ ///
+ ///
+ internal DesktopNotificationHistoryCompat(string applicationUserModelId)
+ {
+ _applicationUserModelId = applicationUserModelId;
+ _history = ToastNotificationManager.History;
+ }
+
+ ///
+ /// Removes all notifications sent by this app from action center.
+ ///
+ public void Clear()
+ {
+ if (_applicationUserModelId != null)
+ {
+ _history.Clear(_applicationUserModelId);
+ }
+ else
+ {
+ _history.Clear();
+ }
+ }
+
+ ///
+ /// Gets all notifications sent by this app that are currently still in Action Center.
+ ///
+ /// A collection of toasts.
+ public IReadOnlyList GetHistory()
+ {
+ return _applicationUserModelId != null ? _history.GetHistory(_applicationUserModelId) : _history.GetHistory();
+ }
+
+ ///
+ /// Removes an individual toast, with the specified tag label, from action center.
+ ///
+ /// The tag label of the toast notification to be removed.
+ public void Remove(string tag)
+ {
+ if (_applicationUserModelId != null)
+ {
+ _history.Remove(tag, string.Empty, _applicationUserModelId);
+ }
+ else
+ {
+ _history.Remove(tag);
+ }
+ }
+
+ ///
+ /// Removes a toast notification from the action using the notification's tag and group labels.
+ ///
+ /// The tag label of the toast notification to be removed.
+ /// The group label of the toast notification to be removed.
+ public void Remove(string tag, string group)
+ {
+ if (_applicationUserModelId != null)
+ {
+ _history.Remove(tag, group, _applicationUserModelId);
+ }
+ else
+ {
+ _history.Remove(tag, group);
+ }
+ }
+
+ ///
+ /// Removes a group of toast notifications, identified by the specified group label, from action center.
+ ///
+ /// The group label of the toast notifications to be removed.
+ public void RemoveGroup(string group)
+ {
+ if (_applicationUserModelId != null)
+ {
+ _history.RemoveGroup(group, _applicationUserModelId);
+ }
+ else
+ {
+ _history.RemoveGroup(group);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotWin10Plugin/Native/DesktopNotificationManagerCompat.cs b/GreenshotWin10Plugin/Native/DesktopNotificationManagerCompat.cs
index 703768582..a30c0ff3e 100644
--- a/GreenshotWin10Plugin/Native/DesktopNotificationManagerCompat.cs
+++ b/GreenshotWin10Plugin/Native/DesktopNotificationManagerCompat.cs
@@ -11,37 +11,31 @@
// ******************************************************************
using System;
-using System.Collections;
-using System.Collections.Generic;
using System.Diagnostics;
-using System.Linq;
using System.Runtime.InteropServices;
-using System.Text;
using Windows.UI.Notifications;
-using GreenshotPlugin.Core;
namespace GreenshotWin10Plugin.Native
{
- public class DesktopNotificationManagerCompat
+ public static class DesktopNotificationManagerCompat
{
public const string TOAST_ACTIVATED_LAUNCH_ARG = "-ToastActivated";
private static bool _registeredAumidAndComServer;
- private static string _aumid;
+ private static string _applicationUserModelId;
private static bool _registeredActivator;
///
- /// If not running under the Desktop Bridge, you must call this method to register your AUMID with the Compat library and to
+ /// If not running under the Desktop Bridge, you must call this method to register your applicationUserModelId (AUMID) with the Compat library and to
/// register your COM CLSID and EXE in LocalServer32 registry. Feel free to call this regardless, and we will no-op if running
/// under Desktop Bridge. Call this upon application startup, before calling any other APIs.
///
- /// An AUMID that uniquely identifies your application.
- public static void RegisterAumidAndComServer(string aumid)
- where T : NotificationActivator
+ /// An applicationUserModelId (AUMID) that uniquely identifies your application.
+ public static void RegisterAumidAndComServer(string applicationUserModelId) where T : NotificationActivator
{
- if (string.IsNullOrWhiteSpace(aumid))
+ if (string.IsNullOrWhiteSpace(applicationUserModelId))
{
- throw new ArgumentException("You must provide an AUMID.", nameof(aumid));
+ throw new ArgumentException("You must provide an Application User Model Id (AUMID).", nameof(applicationUserModelId));
}
// If running as Desktop Bridge
@@ -50,29 +44,41 @@ namespace GreenshotWin10Plugin.Native
// Clear the AUMID since Desktop Bridge doesn't use it, and then we're done.
// Desktop Bridge apps are registered with platform through their manifest.
// Their LocalServer32 key is also registered through their manifest.
- _aumid = null;
+ _applicationUserModelId = null;
_registeredAumidAndComServer = true;
return;
}
- _aumid = aumid;
+ _applicationUserModelId = applicationUserModelId;
- String exePath = Process.GetCurrentProcess().MainModule.FileName;
- RegisterComServer(exePath);
+ string exePath = Process.GetCurrentProcess().MainModule?.FileName;
+ if (exePath != null)
+ {
+ RegisterComServer(exePath);
+ }
_registeredAumidAndComServer = true;
}
- private static void RegisterComServer(string exePath)
- where T : NotificationActivator
+ ///
+ /// Register the application an a com server
+ ///
+ /// type to register for
+ /// string
+ private static void RegisterComServer(string exePath) where T : NotificationActivator
{
// We register the EXE to start up when the notification is activated
- string regString = $"SOFTWARE\\Classes\\CLSID\\{{{typeof(T).GUID}}}\\LocalServer32";
- var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(regString);
+ var guid = typeof(T).GUID;
+ if (guid == null)
+ {
+ throw new ArgumentException("You must provide an Guid on your NotificationActivator.");
+ }
+ string regString = $"SOFTWARE\\Classes\\CLSID\\{{{guid}}}\\LocalServer32";
+ using var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(regString);
// Include a flag so we know this was a toast activation and should wait for COM to process
// We also wrap EXE path in quotes for extra security
- key.SetValue(null, '"' + exePath + '"' + " " + TOAST_ACTIVATED_LAUNCH_ARG);
+ key?.SetValue(null, '"' + exePath + '"' + " " + TOAST_ACTIVATED_LAUNCH_ARG);
}
///
@@ -84,26 +90,23 @@ namespace GreenshotWin10Plugin.Native
// Register type
var regService = new RegistrationServices();
- regService.RegisterTypeForComClients(
- typeof(T),
- RegistrationClassContext.LocalServer,
- RegistrationConnectionType.MultipleUse);
+ regService.RegisterTypeForComClients(typeof(T), RegistrationClassContext.LocalServer, RegistrationConnectionType.MultipleUse);
_registeredActivator = true;
}
///
- /// Creates a toast notifier. You must have called first (and also if you're a classic Win32 app), or this will throw an exception.
+ /// Creates a toast notifier. You must have called first (and also if you're a classic Win32 app), or this will throw an exception.
///
- ///
+ /// ToastNotifier
public static ToastNotifier CreateToastNotifier()
{
EnsureRegistered();
- if (_aumid != null)
+ if (_applicationUserModelId != null)
{
// Non-Desktop Bridge
- return ToastNotificationManager.CreateToastNotifier(_aumid);
+ return ToastNotificationManager.CreateToastNotifier(_applicationUserModelId);
}
// Desktop Bridge
@@ -111,7 +114,7 @@ namespace GreenshotWin10Plugin.Native
}
///
- /// Gets the object. You must have called first (and also if you're a classic Win32 app), or this will throw an exception.
+ /// Gets the object. You must have called first (and also if you're a classic Win32 app), or this will throw an exception.
///
public static DesktopNotificationHistoryCompat History
{
@@ -119,10 +122,13 @@ namespace GreenshotWin10Plugin.Native
{
EnsureRegistered();
- return new DesktopNotificationHistoryCompat(_aumid);
+ return new DesktopNotificationHistoryCompat(_applicationUserModelId);
}
}
+ ///
+ /// Checks if the AUMID is correctly registered, if not this throws an exception
+ ///
private static void EnsureRegistered()
{
// If not registered AUMID yet
@@ -153,232 +159,6 @@ namespace GreenshotWin10Plugin.Native
///
/// Gets a boolean representing whether http images can be used within toasts. This is true if running under Desktop Bridge.
///
- public static bool CanUseHttpImages { get { return DesktopBridgeHelpers.IsRunningAsUwp(); } }
-
- ///
- /// Code from https://github.com/qmatteoq/DesktopBridgeHelpers/edit/master/DesktopBridge.Helpers/Helpers.cs
- ///
- private static class DesktopBridgeHelpers
- {
- const long APPMODEL_ERROR_NO_PACKAGE = 15700L;
-
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
- static extern int GetCurrentPackageFullName(ref int packageFullNameLength, StringBuilder packageFullName);
-
- private static bool? _isRunningAsUwp;
- public static bool IsRunningAsUwp()
- {
- if (_isRunningAsUwp != null) return _isRunningAsUwp.Value;
-
- if (WindowsVersion.IsWindows7OrLower)
- {
- _isRunningAsUwp = false;
- }
- else
- {
- int length = 0;
- StringBuilder sb = new StringBuilder(0);
- GetCurrentPackageFullName(ref length, sb);
-
- sb = new StringBuilder(length);
- int result = GetCurrentPackageFullName(ref length, sb);
-
- _isRunningAsUwp = result != APPMODEL_ERROR_NO_PACKAGE;
- }
-
- return _isRunningAsUwp.Value;
- }
- }
- }
-
- ///
- /// Manages the toast notifications for an app including the ability the clear all toast history and removing individual toasts.
- ///
- public sealed class DesktopNotificationHistoryCompat
- {
- private string _aumid;
- private ToastNotificationHistory _history;
-
- ///
- /// Do not call this. Instead, call to obtain an instance.
- ///
- ///
- internal DesktopNotificationHistoryCompat(string aumid)
- {
- _aumid = aumid;
- _history = ToastNotificationManager.History;
- }
-
- ///
- /// Removes all notifications sent by this app from action center.
- ///
- public void Clear()
- {
- if (_aumid != null)
- {
- _history.Clear(_aumid);
- }
- else
- {
- _history.Clear();
- }
- }
-
- ///
- /// Gets all notifications sent by this app that are currently still in Action Center.
- ///
- /// A collection of toasts.
- public IReadOnlyList GetHistory()
- {
- return _aumid != null ? _history.GetHistory(_aumid) : _history.GetHistory();
- }
-
- ///
- /// Removes an individual toast, with the specified tag label, from action center.
- ///
- /// The tag label of the toast notification to be removed.
- public void Remove(string tag)
- {
- if (_aumid != null)
- {
- _history.Remove(tag, string.Empty, _aumid);
- }
- else
- {
- _history.Remove(tag);
- }
- }
-
- ///
- /// Removes a toast notification from the action using the notification's tag and group labels.
- ///
- /// The tag label of the toast notification to be removed.
- /// The group label of the toast notification to be removed.
- public void Remove(string tag, string group)
- {
- if (_aumid != null)
- {
- _history.Remove(tag, group, _aumid);
- }
- else
- {
- _history.Remove(tag, group);
- }
- }
-
- ///
- /// Removes a group of toast notifications, identified by the specified group label, from action center.
- ///
- /// The group label of the toast notifications to be removed.
- public void RemoveGroup(string group)
- {
- if (_aumid != null)
- {
- _history.RemoveGroup(group, _aumid);
- }
- else
- {
- _history.RemoveGroup(group);
- }
- }
- }
-
- ///
- /// Apps must implement this activator to handle notification activation.
- ///
- public abstract class NotificationActivator : NotificationActivator.INotificationActivationCallback
- {
- public void Activate(string appUserModelId, string invokedArgs, NOTIFICATION_USER_INPUT_DATA[] data, uint dataCount)
- {
- OnActivated(invokedArgs, new NotificationUserInput(data), appUserModelId);
- }
-
- ///
- /// This method will be called when the user clicks on a foreground or background activation on a toast. Parent app must implement this method.
- ///
- /// The arguments from the original notification. This is either the launch argument if the user clicked the body of your toast, or the arguments from a button on your toast.
- /// Text and selection values that the user entered in your toast.
- /// Your AUMID.
- public abstract void OnActivated(string arguments, NotificationUserInput userInput, string appUserModelId);
-
- // These are the new APIs for Windows 10
- #region NewAPIs
- [StructLayout(LayoutKind.Sequential), Serializable]
- public struct NOTIFICATION_USER_INPUT_DATA
- {
- [MarshalAs(UnmanagedType.LPWStr)]
- public string Key;
-
- [MarshalAs(UnmanagedType.LPWStr)]
- public string Value;
- }
-
- [ComImport,
- Guid("53E31837-6600-4A81-9395-75CFFE746F94"), ComVisible(true),
- InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- public interface INotificationActivationCallback
- {
- void Activate(
- [In, MarshalAs(UnmanagedType.LPWStr)]
- string appUserModelId,
- [In, MarshalAs(UnmanagedType.LPWStr)]
- string invokedArgs,
- [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]
- NOTIFICATION_USER_INPUT_DATA[] data,
- [In, MarshalAs(UnmanagedType.U4)]
- uint dataCount);
- }
- #endregion
- }
-
- ///
- /// Text and selection values that the user entered on your notification. The Key is the ID of the input, and the Value is what the user entered.
- ///
- public class NotificationUserInput : IReadOnlyDictionary
- {
- private NotificationActivator.NOTIFICATION_USER_INPUT_DATA[] _data;
-
- internal NotificationUserInput(NotificationActivator.NOTIFICATION_USER_INPUT_DATA[] data)
- {
- _data = data;
- }
-
- public string this[string key] => _data.First(i => i.Key == key).Value;
-
- public IEnumerable Keys => _data.Select(i => i.Key);
-
- public IEnumerable Values => _data.Select(i => i.Value);
-
- public int Count => _data.Length;
-
- public bool ContainsKey(string key)
- {
- return _data.Any(i => i.Key == key);
- }
-
- public IEnumerator> GetEnumerator()
- {
- return _data.Select(i => new KeyValuePair(i.Key, i.Value)).GetEnumerator();
- }
-
- public bool TryGetValue(string key, out string value)
- {
- foreach (var item in _data)
- {
- if (item.Key == key)
- {
- value = item.Value;
- return true;
- }
- }
-
- value = null;
- return false;
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
+ public static bool CanUseHttpImages => DesktopBridgeHelpers.IsRunningAsUwp();
}
}
\ No newline at end of file
diff --git a/GreenshotWin10Plugin/Native/GreenshotNotificationActivator.cs b/GreenshotWin10Plugin/Native/GreenshotNotificationActivator.cs
index 74922476f..d2da5f4c9 100644
--- a/GreenshotWin10Plugin/Native/GreenshotNotificationActivator.cs
+++ b/GreenshotWin10Plugin/Native/GreenshotNotificationActivator.cs
@@ -24,7 +24,9 @@ using log4net;
namespace GreenshotWin10Plugin.Native
{
- // The GUID CLSID must be unique to your app. Create a new GUID if copying this code.
+ ///
+ /// This implements the NotificationActivator
+ ///
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(INotificationActivationCallback))]
[Guid("F48E86D3-E34C-4DB7-8F8F-9A0EA55F0D08"), ComVisible(true)]
diff --git a/GreenshotWin10Plugin/Native/INotificationActivationCallback.cs b/GreenshotWin10Plugin/Native/INotificationActivationCallback.cs
new file mode 100644
index 000000000..59dd61443
--- /dev/null
+++ b/GreenshotWin10Plugin/Native/INotificationActivationCallback.cs
@@ -0,0 +1,35 @@
+// ******************************************************************
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
+// ******************************************************************
+
+using System.Runtime.InteropServices;
+using GreenshotWin10Plugin.Native.Structs;
+
+namespace GreenshotWin10Plugin.Native
+{
+ ///
+ /// This is the interface which allows your notifications to be clicked, which active the application
+ ///
+ [ComImport, Guid("53E31837-6600-4A81-9395-75CFFE746F94"),
+ ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface INotificationActivationCallback
+ {
+ void Activate(
+ [In, MarshalAs(UnmanagedType.LPWStr)]
+ string appUserModelId,
+ [In, MarshalAs(UnmanagedType.LPWStr)]
+ string invokedArgs,
+ [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]
+ NotificationUserInputData[] data,
+ [In, MarshalAs(UnmanagedType.U4)]
+ uint dataCount);
+ }
+}
diff --git a/GreenshotWin10Plugin/Native/NotificationActivator.cs b/GreenshotWin10Plugin/Native/NotificationActivator.cs
new file mode 100644
index 000000000..bedf3f5f4
--- /dev/null
+++ b/GreenshotWin10Plugin/Native/NotificationActivator.cs
@@ -0,0 +1,35 @@
+// ******************************************************************
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
+// ******************************************************************
+
+using GreenshotWin10Plugin.Native.Structs;
+
+namespace GreenshotWin10Plugin.Native
+{
+ ///
+ /// Apps must implement this activator to handle notification activation.
+ ///
+ public abstract class NotificationActivator : INotificationActivationCallback
+ {
+ public void Activate(string appUserModelId, string invokedArgs, NotificationUserInputData[] data, uint dataCount)
+ {
+ OnActivated(invokedArgs, new NotificationUserInput(data), appUserModelId);
+ }
+
+ ///
+ /// This method will be called when the user clicks on a foreground or background activation on a toast. Parent app must implement this method.
+ ///
+ /// The arguments from the original notification. This is either the launch argument if the user clicked the body of your toast, or the arguments from a button on your toast.
+ /// Text and selection values that the user entered in your toast.
+ /// Your AUMID.
+ public abstract void OnActivated(string arguments, NotificationUserInput userInput, string appUserModelId);
+ }
+}
\ No newline at end of file
diff --git a/GreenshotWin10Plugin/Native/NotificationUserInput.cs b/GreenshotWin10Plugin/Native/NotificationUserInput.cs
new file mode 100644
index 000000000..57b184c70
--- /dev/null
+++ b/GreenshotWin10Plugin/Native/NotificationUserInput.cs
@@ -0,0 +1,70 @@
+// ******************************************************************
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
+// ******************************************************************
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using GreenshotWin10Plugin.Native.Structs;
+
+namespace GreenshotWin10Plugin.Native
+{
+ ///
+ /// Text and selection values that the user entered on your notification. The Key is the ID of the input, and the Value is what the user entered.
+ ///
+ public class NotificationUserInput : IReadOnlyDictionary
+ {
+ private readonly NotificationUserInputData[] _notificationUserInputData;
+
+ internal NotificationUserInput(NotificationUserInputData[] notificationUserInputData)
+ {
+ _notificationUserInputData = notificationUserInputData;
+ }
+
+ public string this[string key] => _notificationUserInputData.First(i => i.Key == key).Value;
+
+ public IEnumerable Keys => _notificationUserInputData.Select(i => i.Key);
+
+ public IEnumerable Values => _notificationUserInputData.Select(i => i.Value);
+
+ public int Count => _notificationUserInputData.Length;
+
+ public bool ContainsKey(string key)
+ {
+ return _notificationUserInputData.Any(i => i.Key == key);
+ }
+
+ public IEnumerator> GetEnumerator()
+ {
+ return _notificationUserInputData.Select(i => new KeyValuePair(i.Key, i.Value)).GetEnumerator();
+ }
+
+ public bool TryGetValue(string key, out string value)
+ {
+ foreach (var item in _notificationUserInputData)
+ {
+ if (item.Key == key)
+ {
+ value = item.Value;
+ return true;
+ }
+ }
+
+ value = null;
+ return false;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotWin10Plugin/Native/Structs/NotificationUserInputData.cs b/GreenshotWin10Plugin/Native/Structs/NotificationUserInputData.cs
new file mode 100644
index 000000000..357aaa378
--- /dev/null
+++ b/GreenshotWin10Plugin/Native/Structs/NotificationUserInputData.cs
@@ -0,0 +1,30 @@
+// ******************************************************************
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
+// ******************************************************************
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace GreenshotWin10Plugin.Native.Structs
+{
+ ///
+ /// See NOTIFICATION_USER_INPUT_DATA structure
+ ///
+ [StructLayout(LayoutKind.Sequential), Serializable]
+ public struct NotificationUserInputData
+ {
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string Key;
+
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string Value;
+ }
+}
diff --git a/GreenshotWin10Plugin/ToastNotificationService.cs b/GreenshotWin10Plugin/ToastNotificationService.cs
index 05d930bc8..4af060bf9 100644
--- a/GreenshotWin10Plugin/ToastNotificationService.cs
+++ b/GreenshotWin10Plugin/ToastNotificationService.cs
@@ -44,7 +44,7 @@ namespace GreenshotWin10Plugin
public ToastNotificationService()
{
// Register AUMID and COM server (for Desktop Bridge apps, this no-ops)
- DesktopNotificationManagerCompat.RegisterAumidAndComServer("Greenshot.Greenshot");
+ DesktopNotificationManagerCompat.RegisterAumidAndComServer("Greenshot");
// Register COM server and activator type
DesktopNotificationManagerCompat.RegisterActivator();
@@ -68,9 +68,10 @@ namespace GreenshotWin10Plugin
/// This creates the actual toast
///
/// string
+ /// milliseconds until the toast timeouts
/// Action called when clicked
/// Action called when the toast is closed
- private void ShowMessage(string message, Action onClickAction, Action onClosedAction)
+ private void ShowMessage(string message, int timeout, Action onClickAction, Action onClosedAction)
{
// Do not inform the user if this is disabled
if (!CoreConfiguration.ShowTrayNotification)
@@ -104,7 +105,11 @@ namespace GreenshotWin10Plugin
}
// Create the toast and attach event listeners
- var toast = new ToastNotification(toastXml);
+ var toast = new ToastNotification(toastXml)
+ {
+ ExpiresOnReboot = true,
+ ExpirationTime = timeout > 0 ? DateTimeOffset.Now.AddMilliseconds(timeout) : (DateTimeOffset?)null
+ };
void ToastActivatedHandler(ToastNotification toastNotification, object sender)
{
@@ -155,17 +160,17 @@ namespace GreenshotWin10Plugin
public void ShowWarningMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
{
- ShowMessage(message, onClickAction, onClosedAction);
+ ShowMessage(message, timeout, onClickAction, onClosedAction);
}
public void ShowErrorMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
{
- ShowMessage(message, onClickAction, onClosedAction);
+ ShowMessage(message, timeout, onClickAction, onClosedAction);
}
public void ShowInfoMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
{
- ShowMessage(message, onClickAction, onClosedAction);
+ ShowMessage(message, timeout, onClickAction, onClosedAction);
}
}
}