diff --git a/DisplayMagician/DisplayMagician.csproj b/DisplayMagician/DisplayMagician.csproj
index 68ba785..821dcb2 100644
--- a/DisplayMagician/DisplayMagician.csproj
+++ b/DisplayMagician/DisplayMagician.csproj
@@ -108,6 +108,9 @@
+
+ Component
+
@@ -262,9 +265,6 @@
1.2.0.1
-
- 1.9.0
-
1.11.33
@@ -292,6 +292,12 @@
13.0.1
+
+ 2.1.0
+
+
+ 2.1.0
+
4.7.9
diff --git a/DisplayMagician/HotkeySelector.cs b/DisplayMagician/HotkeySelector.cs
new file mode 100644
index 0000000..8903483
--- /dev/null
+++ b/DisplayMagician/HotkeySelector.cs
@@ -0,0 +1,537 @@
+#region Copyright
+
+/*
+ * Developer : Willy Kimura (WK).
+ * Library : HotkeySelector.
+ * License : MIT.
+ *
+ * Copied and repurposed to help with DisplayMagician by Terry MacDonald
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using System.Diagnostics;
+using System.Windows.Forms;
+using System.ComponentModel;
+
+namespace DisplayMagician
+{
+ ///
+ /// Provides support for enabling standard Windows controls
+ /// and User controls to select hotkeys at runtime.
+ /// Combined with the class,
+ /// you can easily enable the selection and registering of
+ /// hotkeys for a seamless end-user experience.
+ ///
+ [DebuggerStepThrough]
+ [Description("Provides support for enabling standard Windows controls " +
+ "and User controls to select hotkeys at runtime.")]
+ public partial class HotkeySelector : Component
+ {
+ #region Constructor
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public HotkeySelector() { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public HotkeySelector(IContainer container)
+ {
+ container.Add(this);
+
+ //InitializeComponent();
+ }
+
+ #endregion
+
+ #region Fields
+
+ // These variables store the selected hotkey and modifier key(s).
+ private Keys _hotkey = Keys.None;
+ //private Keys _modifiers = Keys.None;
+
+ // ArrayLists used to enforce the use of proper modifiers.
+ // Shift+A isn't a valid hotkey, for instance.
+ private ArrayList _needNonShiftModifier = null;
+ private ArrayList _needNonAltGrModifier = null;
+
+ // Stores the list of enabled hotkey selection controls.
+ private List _controls = new List();
+
+ #endregion
+
+ #region Properties
+
+ #region Public
+
+ ///
+ /// Gets or sets the text to be displayed in a
+ /// control when no hotkey has been set.
+ /// (Preferred default text is "None")
+ ///
+ public string EmptyHotkeyText { get; set; } = "None";
+
+ ///
+ /// Gets or sets the text to be displayed in a control
+ /// when an invalid or unsupported hotkey is pressed.
+ /// (Preferred default text is "(Unsupported)")
+ ///
+ public string InvalidHotkeyText { get; set; } = "Unsupported";
+
+ #endregion
+
+ #endregion
+
+ #region Methods
+
+ #region Public
+
+ ///
+ /// Enables a control for hotkey selection and previewing.
+ /// This will make use of the control's Text property to
+ /// preview the current hotkey selected.
+ ///
+ /// The control to enable.
+ public bool Enable(Control control)
+ {
+ try
+ {
+ control.Text = EmptyHotkeyText;
+
+ control.KeyPress += new KeyPressEventHandler(OnKeyPress);
+ control.KeyDown += new KeyEventHandler(OnKeyDown);
+ control.KeyUp += new KeyEventHandler(OnKeyUp);
+
+ ResetModifiers();
+
+ try
+ {
+ _controls.Add(control);
+ }
+ catch (Exception) { }
+
+ return true;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Enables a control for hotkey selection and previewing.
+ /// This will make use of the control's Text property to
+ /// preview the current hotkey selected.
+ ///
+ /// The control to enable.
+ /// Assign the default Keys to be previewed in the control.
+ public bool Enable(Control control, Keys hotkey)
+ {
+ try
+ {
+ Enable(control);
+
+ _hotkey = hotkey;
+
+ Refresh(control);
+
+ return true;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Disables a control for hotkey selection and previewing.
+ ///
+ /// The control to disable.
+ /// Clear the control's previewed keys?
+ public bool Disable(Control control, bool clearKeys = true)
+ {
+ try
+ {
+ control.KeyPress -= OnKeyPress;
+ control.KeyDown -= OnKeyDown;
+ control.KeyUp -= OnKeyUp;
+
+ if (clearKeys)
+ control.Text = string.Empty;
+
+ try
+ {
+ if (_controls.Contains(control))
+ _controls.Remove(control);
+ }
+ catch (Exception) { }
+
+ return true;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether a specific
+ /// control is enabled for hotkey selection.
+ ///
+ /// The control to determine.
+ public bool IsEnabled(Control control)
+ {
+ if (_controls.Contains(control))
+ return true;
+ else
+ return false;
+ }
+
+ ///
+ /// Sets a hotkey selection to be previewed in a control.
+ /// Thsi does not automatically enable the control for
+ /// hotkey selection. For this, please use the method.
+ ///
+ /// The control to set.
+ /// Provide a standard key selection.
+ /// Provide a modifier key selection.
+ public bool Set(Control control, Keys hotkey)
+ {
+ try
+ {
+ _hotkey = hotkey;
+
+ Refresh(control);
+
+ return true;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Clears the currently previewed hotkey
+ /// selection displayed in a control.
+ ///
+ public void Clear(Control control)
+ {
+ this._hotkey = Keys.None;
+
+ Refresh(control);
+ }
+
+ ///
+ /// (Variant of the method)
+ /// Clears the currently previewed hotkey
+ /// selection displayed in a control.
+ ///
+ public void Reset(Control control)
+ {
+ this._hotkey = Keys.None;
+
+ Refresh(control);
+ }
+
+ ///
+ /// [Helper] Converts keys or key combinations to their string types.
+ ///
+ /// The hotkey to convert.
+ public string Convert(Keys hotkey)
+ {
+ try
+ {
+ _hotkey = hotkey;
+
+ string parsedHotkey = string.Empty;
+
+ // No modifier or shift only, and a hotkey that needs another modifier.
+ if ((_hotkey == Keys.Shift || _hotkey == Keys.None))
+ {
+ if (_needNonShiftModifier != null && _needNonShiftModifier.Contains((int)this._hotkey))
+ {
+ if (this._hotkey == Keys.None)
+ {
+ // Set Ctrl+Alt as the modifier unless Ctrl+Alt+ won't work.
+ if (_needNonAltGrModifier.Contains((int)this._hotkey) == false)
+ {
+ this._hotkey = Keys.Alt | Keys.Control;
+ }
+ else
+ {
+ // ...In that case, use Shift+Alt instead.
+ this._hotkey = Keys.Alt | Keys.Shift;
+ }
+ }
+ else
+ {
+ // User pressed Shift and an invalid key (e.g. a letter or a number),
+ // that needs another set of modifier keys.
+ this._hotkey = Keys.None;
+ }
+ }
+ }
+
+ // Without this code, pressing only Ctrl
+ // will show up as "Control + ControlKey", etc.
+ if (this._hotkey == Keys.Menu || /* Alt */
+ this._hotkey == Keys.ShiftKey ||
+ this._hotkey == Keys.ControlKey)
+ {
+ this._hotkey = Keys.None;
+ }
+
+ if (this._hotkey == Keys.None)
+ {
+ // LWin/RWin don't work as hotkeys...
+ // (neither do they work as modifier keys in .NET 2.0).
+ if (_hotkey == Keys.None || _hotkey == Keys.LWin || _hotkey == Keys.RWin)
+ {
+ parsedHotkey = string.Empty;
+ }
+ else
+ {
+ parsedHotkey = this._hotkey.ToString();
+ }
+ }
+ else
+ {
+ parsedHotkey = this._hotkey.ToString();
+ }
+
+ return parsedHotkey;
+ }
+ catch (Exception)
+ {
+ return string.Empty;
+ }
+ }
+
+ #endregion
+
+ #region Private
+
+ ///
+ /// Resets the hotkey modifiers to their defaults.
+ ///
+ private void ResetModifiers()
+ {
+ // Fill the ArrayLists that contain
+ // all invalid hotkey combinations.
+ _needNonShiftModifier = new ArrayList();
+ _needNonAltGrModifier = new ArrayList();
+
+ PopulateModifierLists();
+ }
+
+ ///
+ /// Populates the ArrayLists specifying disallowed Hotkeys
+ /// such as Shift+A, Ctrl+Alt+4 (produces 'dollar' sign).
+ ///
+ private void PopulateModifierLists()
+ {
+ // Shift + 0 - 9, A - Z.
+ for (Keys k = Keys.D0; k <= Keys.Z; k++)
+ _needNonShiftModifier.Add((int)k);
+
+ // Shift + Numpad keys.
+ for (Keys k = Keys.NumPad0; k <= Keys.NumPad9; k++)
+ _needNonShiftModifier.Add((int)k);
+
+ // Shift + Misc (,;<./ etc).
+ for (Keys k = Keys.Oem1; k <= Keys.OemBackslash; k++)
+ _needNonShiftModifier.Add((int)k);
+
+ // Shift + Space, PgUp, PgDn, End, Home.
+ for (Keys k = Keys.Space; k <= Keys.Home; k++)
+ _needNonShiftModifier.Add((int)k);
+
+ // Misc keys that we can't loop through.
+ _needNonShiftModifier.Add((int)Keys.Insert);
+ _needNonShiftModifier.Add((int)Keys.Help);
+ _needNonShiftModifier.Add((int)Keys.Multiply);
+ _needNonShiftModifier.Add((int)Keys.Add);
+ _needNonShiftModifier.Add((int)Keys.Subtract);
+ _needNonShiftModifier.Add((int)Keys.Divide);
+ _needNonShiftModifier.Add((int)Keys.Decimal);
+ _needNonShiftModifier.Add((int)Keys.Return);
+ _needNonShiftModifier.Add((int)Keys.Escape);
+ _needNonShiftModifier.Add((int)Keys.NumLock);
+ _needNonShiftModifier.Add((int)Keys.Scroll);
+ _needNonShiftModifier.Add((int)Keys.Pause);
+
+ // Ctrl+Alt + 0 - 9.
+ for (Keys k = Keys.D0; k <= Keys.D9; k++)
+ _needNonAltGrModifier.Add((int)k);
+ }
+
+ ///
+ /// Refreshes the previewed hotkey combination displayed in a control.
+ ///
+ ///
+ /// The control providing hotkey selection.
+ ///
+ private void Refresh(Control control)
+ {
+ Refresh(control, false);
+ }
+
+ ///
+ /// Refreshes the previewed hotkey combination displayed in a control.
+ ///
+ ///
+ /// The control providing hotkey selection.
+ ///
+ ///
+ /// Specifies whether this function is
+ /// called internally or by the user.
+ ///
+ private void Refresh(Control control, bool internalCall)
+ {
+ try
+ {
+ string parsedHotkey = string.Empty;
+
+ // No hotkey set.
+ if (this._hotkey == Keys.None)
+ {
+ control.Text = EmptyHotkeyText;
+
+ return;
+ }
+
+ // LWin/RWin don't work as hotkeys...
+ // (neither do they work as modifier keys in .NET 2.0).
+ if (this._hotkey == Keys.LWin || this._hotkey == Keys.RWin)
+ {
+ control.Text = InvalidHotkeyText;
+
+ return;
+ }
+
+ // Only validate input if it comes from the user.
+ if (internalCall == false)
+ {
+ // No modifier or shift only, and a hotkey that needs another modifier.
+ if ((this._hotkey == Keys.Shift || this._hotkey == Keys.None) &&
+ this._needNonShiftModifier.Contains((int)this._hotkey))
+ {
+ if (this._hotkey == Keys.None)
+ {
+ // Set Ctrl+Alt as the modifier unless Ctrl+Alt+ won't work.
+ if (_needNonAltGrModifier.Contains((int)this._hotkey) == false)
+ {
+ this._hotkey |= Keys.Alt | Keys.Control;
+ }
+ else
+ {
+ // ...In that case, use Shift+Alt instead.
+ this._hotkey |= Keys.Alt | Keys.Shift;
+ }
+ }
+ else
+ {
+ // User pressed Shift and an invalid key (e.g. a letter or a number),
+ // that needs another set of modifier keys.
+ this._hotkey = Keys.None;
+
+ control.Text = this._hotkey.ToString() + $" + {InvalidHotkeyText}";
+
+ return;
+ }
+ }
+ }
+
+ // Without this code, pressing only Ctrl
+ // will show up as "Control + ControlKey", etc.
+ if (this._hotkey == Keys.Menu || /* Alt */
+ this._hotkey == Keys.ShiftKey ||
+ this._hotkey == Keys.ControlKey)
+ {
+ this._hotkey = Keys.None;
+ }
+
+ // A final compilation of the processed keys in string format.
+ parsedHotkey = this._hotkey.ToString();
+
+ control.Text = parsedHotkey;
+
+ return;
+ }
+ catch (Exception) { }
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Events
+
+ #region Private
+
+ ///
+ /// Fires when a key is pressed down. Here, we'll want to update the Text
+ /// property to notify the user what key combination is currently pressed.
+ ///
+ private void OnKeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyData == Keys.Delete || e.KeyData == (Keys.Control | Keys.Delete))
+ Reset((Control)sender);
+
+ if (e.KeyData == (Keys.Shift | Keys.Insert))
+ {
+ this._hotkey = Keys.Shift;
+
+ e.Handled = true;
+ }
+
+ // Clear the current hotkey.
+ if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete)
+ {
+ Reset((Control)sender);
+
+ return;
+ }
+ else
+ {
+ this._hotkey = e.KeyCode;
+
+ Refresh((Control)sender);
+ }
+ }
+
+ ///
+ /// Fires when all keys are released. If the current hotkey isn't valid, reset it.
+ /// Otherwise, do nothing and keep the Text and hotkey as it was.
+ ///
+ private void OnKeyUp(object sender, KeyEventArgs e)
+ {
+ if (this._hotkey == Keys.None && Control.ModifierKeys == Keys.None)
+ {
+ Reset((Control)sender);
+
+ return;
+ }
+ }
+
+ ///
+ /// Prevents anything entered in Input controls from being displayed.
+ /// Without this, a "A" key press would appear as "aControl, Alt + A".
+ ///
+ private void OnKeyPress(object sender, KeyPressEventArgs e)
+ {
+ e.Handled = true;
+ }
+
+ #endregion
+
+ #endregion
+ }
+}
diff --git a/DisplayMagician/Program.cs b/DisplayMagician/Program.cs
index 1e87e73..8f0c3e5 100644
--- a/DisplayMagician/Program.cs
+++ b/DisplayMagician/Program.cs
@@ -17,7 +17,7 @@ using DesktopNotifications;
using System.Runtime.Serialization;
using NLog.Config;
using System.Collections.Generic;
-using WK.Libraries.HotkeyListenerNS;
+using NHotkey.WindowsForms;
namespace DisplayMagician {
@@ -45,7 +45,6 @@ namespace DisplayMagician {
public static bool WaitingForGameToExit = false;
public static ProgramSettings AppProgramSettings;
public static MainForm AppMainForm;
- public static HotkeyListener HotkeyListener;
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private static SharedLogger sharedLogger;
@@ -206,8 +205,6 @@ namespace DisplayMagician {
Application.SetCompatibleTextRenderingDefault(false);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
- // Create a program-wide HotKeyListener
- HotkeyListener = new HotkeyListener();
logger.Debug($"Setting up commandline processing configuration");
var app = new CommandLineApplication
diff --git a/DisplayMagicianShared/DisplayMagicianShared.csproj b/DisplayMagicianShared/DisplayMagicianShared.csproj
index b804433..110cdbd 100644
--- a/DisplayMagicianShared/DisplayMagicianShared.csproj
+++ b/DisplayMagicianShared/DisplayMagicianShared.csproj
@@ -104,9 +104,6 @@
1.2.0.1
-
- 1.9.0
-
1.0.2.1-beta
@@ -121,6 +118,12 @@
12.0.3
+
+ 2.1.0
+
+
+ 2.1.0
+
4.7.8