mirror of
https://github.com/Hofknecht/SystemTrayMenu.git
synced 2024-07-09 08:16:41 +12:00
Refactor hotkey registration
Allow function registrations besides the actual hotkey registration.
This commit is contained in:
parent
637cc46e7e
commit
215c263052
|
@ -7,16 +7,21 @@ namespace SystemTrayMenu.Handler
|
|||
using System;
|
||||
using System.Windows.Input;
|
||||
using SystemTrayMenu.DataClasses;
|
||||
using SystemTrayMenu.Helpers;
|
||||
using SystemTrayMenu.UserInterface;
|
||||
using SystemTrayMenu.Utilities;
|
||||
using static SystemTrayMenu.Helpers.GlobalHotkeys;
|
||||
|
||||
internal class KeyboardInput : IDisposable
|
||||
{
|
||||
private GlobalHotkeys.IHotkeyRegistration? hotkeyRegistration;
|
||||
private readonly IHotkeyFunction hotkeyFunction = Create();
|
||||
|
||||
private Menu? focussedMenu;
|
||||
|
||||
public KeyboardInput()
|
||||
{
|
||||
hotkeyFunction.KeyPressed += (_) => HotKeyPressed?.Invoke();
|
||||
}
|
||||
|
||||
internal event Action? HotKeyPressed;
|
||||
|
||||
internal event Action<RowData?>? RowSelectionChanged;
|
||||
|
@ -27,7 +32,7 @@ namespace SystemTrayMenu.Handler
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
GlobalHotkeys.Unregister(hotkeyRegistration);
|
||||
hotkeyFunction.Unregister();
|
||||
}
|
||||
|
||||
internal bool RegisterHotKey(string hotKeyString)
|
||||
|
@ -36,15 +41,13 @@ namespace SystemTrayMenu.Handler
|
|||
{
|
||||
try
|
||||
{
|
||||
hotkeyRegistration = GlobalHotkeys.Register(hotKeyString);
|
||||
hotkeyFunction.Register(hotKeyString);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
Log.Warn($"Hotkey cannot be set: '{hotKeyString}'", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
hotkeyRegistration.KeyPressed += (_) => HotKeyPressed?.Invoke();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -21,22 +21,30 @@ namespace SystemTrayMenu.Helpers
|
|||
private static readonly Window Window = new();
|
||||
private static readonly HwndSource HWnd;
|
||||
|
||||
private static readonly List<HotkeyRegistration> Registrations = new();
|
||||
private static readonly Dictionary<int, HotkeyRegistration> Registrations = new();
|
||||
private static readonly object CriticalSectionLock = new();
|
||||
|
||||
private static IHotkeyFunction? lastCreatedHotkeyFunction; // TODO: Remove this hack! See: GetLastCreatedHotkeyFunction
|
||||
|
||||
static GlobalHotkeys()
|
||||
{
|
||||
HWnd = HwndSource.FromHwnd(new WindowInteropHelper(Window).EnsureHandle());
|
||||
HWnd.AddHook(Hook);
|
||||
}
|
||||
|
||||
internal interface IHotkeyRegistration
|
||||
internal interface IHotkeyFunction
|
||||
{
|
||||
event Action<IHotkeyRegistration>? KeyPressed;
|
||||
event Action<IHotkeyFunction>? KeyPressed;
|
||||
|
||||
ModifierKeys GetModifierKeys();
|
||||
|
||||
Key GetKey();
|
||||
|
||||
void Register(ModifierKeys modifiers, Key key);
|
||||
|
||||
void Register(string hotKeyString);
|
||||
|
||||
void Unregister();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -45,161 +53,11 @@ namespace SystemTrayMenu.Helpers
|
|||
/// </summary>
|
||||
internal static bool IsEnabled { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Registers a global hotkey.
|
||||
/// Function is thread safe.
|
||||
/// Throws an InvalidOperationException on error.
|
||||
/// The caller needs to call UnregisterHotkey to free up ressources.
|
||||
/// </summary>
|
||||
/// <param name="modifiers">Hotkey modifiers.</param>
|
||||
/// <param name="key">Hotkey major key.</param>
|
||||
/// <returns>Registration interface.</returns>
|
||||
internal static IHotkeyRegistration Register(ModifierKeys modifiers, Key key)
|
||||
{
|
||||
int virtualKeyCode = KeyInterop.VirtualKeyFromKey(key);
|
||||
int id = 0;
|
||||
|
||||
lock (CriticalSectionLock)
|
||||
{
|
||||
foreach (var reg in Registrations)
|
||||
{
|
||||
if (id <= reg.Id)
|
||||
{
|
||||
id = reg.Id + 1; // TODO: Rework to re-use gaps
|
||||
}
|
||||
}
|
||||
|
||||
if (!NativeMethods.User32RegisterHotKey(HWnd.Handle, id, (uint)modifiers, (uint)virtualKeyCode))
|
||||
{
|
||||
string errorHint = NativeMethods.GetLastErrorHint();
|
||||
throw new InvalidOperationException(Translator.GetText("Could not register the hot key.") + " (" + errorHint + ")");
|
||||
}
|
||||
}
|
||||
|
||||
HotkeyRegistration registration = new()
|
||||
{
|
||||
Id = id,
|
||||
Modifiers = modifiers,
|
||||
Key = key,
|
||||
};
|
||||
Registrations.Add(registration);
|
||||
return registration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a global hotkey.
|
||||
/// Function is thread safe.
|
||||
/// Throws an InvalidOperationException on error.
|
||||
/// The caller needs to call UnregisterHotkey to free up ressources.
|
||||
/// </summary>
|
||||
/// <param name="hotKeyString">Hotkey string representation.</param>
|
||||
/// <returns>Registration interface.</returns>
|
||||
internal static IHotkeyRegistration Register(string hotKeyString)
|
||||
{
|
||||
var (modifiers, key) = ParseKeysAndModifiersFromString(hotKeyString);
|
||||
return Register(modifiers, key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a global hotkey in a thread safe manner.
|
||||
/// Function is thread safe.
|
||||
/// </summary>
|
||||
/// <param name="registration">Registration interface.</param>
|
||||
/// <returns>true: Success or false: Failure.</returns>
|
||||
internal static bool Unregister(IHotkeyRegistration? registration)
|
||||
{
|
||||
if (registration == null || registration is not HotkeyRegistration reg || !Registrations.Contains(reg))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
lock (CriticalSectionLock)
|
||||
{
|
||||
if (!NativeMethods.User32UnregisterHotKey(HWnd.Handle, reg.Id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Registrations.Remove(reg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static bool Reassign(IHotkeyRegistration? registration, ModifierKeys modifiers, Key key)
|
||||
{
|
||||
if (registration == null || registration is not HotkeyRegistration reg || !Registrations.Contains(reg))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (modifiers == reg.Modifiers && key == reg.Key)
|
||||
{
|
||||
return true; // Yes, nothing changed, but we return true as requested key is properly registered even when unchanged.
|
||||
}
|
||||
|
||||
int virtualKeyCode = KeyInterop.VirtualKeyFromKey(key);
|
||||
int id = 0;
|
||||
|
||||
lock (CriticalSectionLock)
|
||||
{
|
||||
foreach (var regs in Registrations)
|
||||
{
|
||||
if (id <= regs.Id)
|
||||
{
|
||||
id = reg.Id + 1; // TODO: Rework to re-use gaps
|
||||
}
|
||||
}
|
||||
|
||||
if (!NativeMethods.User32RegisterHotKey(HWnd.Handle, id, (uint)modifiers, (uint)virtualKeyCode))
|
||||
{
|
||||
string errorHint = NativeMethods.GetLastErrorHint();
|
||||
throw new InvalidOperationException(Translator.GetText("Could not register the hot key.") + " (" + errorHint + ")");
|
||||
}
|
||||
|
||||
// In case unregister failes, unfortunately registration remains
|
||||
// but will not trigger anything as we change our hotkey registration.
|
||||
// However, this means the hotkey keeps being registered with this application
|
||||
// and the key combination will not be availalbe for re-registration till app restart.
|
||||
// TODO: Decide how to handle this? Restart App? Try keep old registartion and not update it?
|
||||
if (!NativeMethods.User32UnregisterHotKey(HWnd.Handle, reg.Id))
|
||||
{
|
||||
Log.Info("Hotkey registration cannot unregister key " + reg.Modifiers.ToString() + " with modifiers " + reg.Modifiers.ToString());
|
||||
}
|
||||
|
||||
reg.Id = id;
|
||||
reg.Modifiers = modifiers;
|
||||
reg.Key = key;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static bool Reassign(IHotkeyRegistration? registration, string hotKeyString)
|
||||
{
|
||||
var (modifiers, key) = ParseKeysAndModifiersFromString(hotKeyString);
|
||||
return Reassign(registration, modifiers, key);
|
||||
}
|
||||
internal static IHotkeyFunction Create() => lastCreatedHotkeyFunction = new HotkeyFunction();
|
||||
|
||||
// TODO: Instead of searching for the registration, it should be passed to the caller instead.
|
||||
// Only this ensures caller and registrator are talking about the SAME registration.
|
||||
internal static IHotkeyRegistration? FindRegistration(string hotKeyString)
|
||||
{
|
||||
var (modifiers, key) = ParseKeysAndModifiersFromString(hotKeyString);
|
||||
|
||||
lock (CriticalSectionLock)
|
||||
{
|
||||
foreach (var registration in Registrations)
|
||||
{
|
||||
if (modifiers == registration.Modifiers && key == registration.Key)
|
||||
{
|
||||
return registration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
internal static IHotkeyFunction? GetLastCreatedHotkeyFunction() => lastCreatedHotkeyFunction;
|
||||
|
||||
internal static ModifierKeys ModifierKeysFromString(string modifiersString)
|
||||
{
|
||||
|
@ -386,7 +244,7 @@ namespace SystemTrayMenu.Helpers
|
|||
HotkeyRegistration? reg = null;
|
||||
lock (CriticalSectionLock)
|
||||
{
|
||||
foreach (var registration in Registrations)
|
||||
foreach (var (id, registration) in Registrations)
|
||||
{
|
||||
if (modifiers == registration.Modifiers && key == registration.Key)
|
||||
{
|
||||
|
@ -403,21 +261,152 @@ namespace SystemTrayMenu.Helpers
|
|||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
private class HotkeyRegistration : IHotkeyRegistration
|
||||
/// <summary>
|
||||
/// Registers a global hotkey.
|
||||
/// Function is thread safe.
|
||||
/// Throws an InvalidOperationException on error.
|
||||
/// The caller needs to call Unregister to free up ressources.
|
||||
/// </summary>
|
||||
/// <param name="modifiers">Hotkey modifiers.</param>
|
||||
/// <param name="key">Hotkey major key.</param>
|
||||
/// <returns>Hotkey registration.</returns>
|
||||
private static HotkeyRegistration Register(ModifierKeys modifiers, Key key)
|
||||
{
|
||||
public event Action<IHotkeyRegistration>? KeyPressed;
|
||||
HotkeyRegistration registration;
|
||||
int virtualKeyCode = KeyInterop.VirtualKeyFromKey(key);
|
||||
int id = 0;
|
||||
|
||||
internal int Id { get; set; }
|
||||
lock (CriticalSectionLock)
|
||||
{
|
||||
while (Registrations.ContainsKey(id))
|
||||
{
|
||||
id++;
|
||||
}
|
||||
|
||||
internal ModifierKeys Modifiers { get; set; }
|
||||
if (!NativeMethods.User32RegisterHotKey(HWnd.Handle, id, (uint)modifiers, (uint)virtualKeyCode))
|
||||
{
|
||||
string errorHint = NativeMethods.GetLastErrorHint();
|
||||
throw new InvalidOperationException(Translator.GetText("Could not register the hot key.") + " (" + errorHint + ")");
|
||||
}
|
||||
|
||||
internal Key Key { get; set; }
|
||||
registration = new()
|
||||
{
|
||||
Id = id,
|
||||
Modifiers = modifiers,
|
||||
Key = key,
|
||||
};
|
||||
Registrations.Add(id, registration);
|
||||
}
|
||||
|
||||
public ModifierKeys GetModifierKeys() => Modifiers;
|
||||
return registration;
|
||||
}
|
||||
|
||||
public Key GetKey() => Key;
|
||||
/// <summary>
|
||||
/// Unregisters a global hotkey.
|
||||
/// Function is thread safe.
|
||||
/// </summary>
|
||||
/// <param name="registration">Hotkey registration.</param>
|
||||
private static void Unregister(HotkeyRegistration registration)
|
||||
{
|
||||
lock (CriticalSectionLock)
|
||||
{
|
||||
if (Registrations.ContainsValue(registration))
|
||||
{
|
||||
if (!NativeMethods.User32UnregisterHotKey(HWnd.Handle, registration.Id))
|
||||
{
|
||||
Log.Info("Hotkey registration cannot unregister key " + registration.Modifiers.ToString() + " with modifiers " + registration.Modifiers.ToString());
|
||||
}
|
||||
|
||||
internal void OnKeyPressed() => KeyPressed?.Invoke(this);
|
||||
// In case unregister failes, unfortunately registration remains
|
||||
// but will not trigger anything as we remove the hotkey registration.
|
||||
// However, this means the hotkey keeps being registered with this application
|
||||
// and the key combination will not be availalbe for re-registration till app restart.
|
||||
// TODO: Decide how to handle this? Restart App? Try keep old registartion and not update it?
|
||||
Registrations.Remove(registration.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a new global hotkey and unregisters the old one.
|
||||
/// Function is thread safe.
|
||||
/// Throws an InvalidOperationException on error.
|
||||
/// The caller needs to call Unregister to free up ressources in case a new registration is returned.
|
||||
/// </summary>
|
||||
/// <param name="registration">Old hotkey registration.</param>
|
||||
/// <param name="modifiers">Hotkey modifiers.</param>
|
||||
/// <param name="key">Hotkey key.</param>
|
||||
/// <returns>New hotkey registration or null (nothing changed).</returns>
|
||||
private static HotkeyRegistration? Reassign(HotkeyRegistration registration, ModifierKeys modifiers, Key key)
|
||||
{
|
||||
if (!Registrations.ContainsValue(registration) ||
|
||||
(modifiers == registration.Modifiers && key == registration.Key))
|
||||
{
|
||||
// Either registration is not valid or
|
||||
// nothing would as requested key is already properly registered.
|
||||
return null;
|
||||
}
|
||||
|
||||
HotkeyRegistration reg = Register(modifiers, key);
|
||||
Unregister(registration);
|
||||
return reg;
|
||||
}
|
||||
|
||||
private class HotkeyRegistration
|
||||
{
|
||||
public event Action? KeyPressed;
|
||||
|
||||
internal int Id { get; init; }
|
||||
|
||||
internal ModifierKeys Modifiers { get; init; }
|
||||
|
||||
internal Key Key { get; init; }
|
||||
|
||||
internal void OnKeyPressed() => KeyPressed?.Invoke();
|
||||
}
|
||||
|
||||
private class HotkeyFunction : IHotkeyFunction
|
||||
{
|
||||
public event Action<IHotkeyFunction>? KeyPressed;
|
||||
|
||||
internal HotkeyRegistration? Registration { get; set; }
|
||||
|
||||
public void Unregister()
|
||||
{
|
||||
if (Registration != null)
|
||||
{
|
||||
GlobalHotkeys.Unregister(Registration);
|
||||
Registration = null;
|
||||
}
|
||||
}
|
||||
|
||||
public ModifierKeys GetModifierKeys() => Registration?.Modifiers ?? ModifierKeys.None;
|
||||
|
||||
public Key GetKey() => Registration?.Key ?? Key.None;
|
||||
|
||||
public void Register(ModifierKeys modifiers, Key key)
|
||||
{
|
||||
if (Registration == null)
|
||||
{
|
||||
Registration = GlobalHotkeys.Register(modifiers, key);
|
||||
Registration.KeyPressed += () => KeyPressed?.Invoke(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
HotkeyRegistration? reg = Reassign(Registration, modifiers, key);
|
||||
if (reg != null)
|
||||
{
|
||||
Registration = reg;
|
||||
Registration.KeyPressed += () => KeyPressed?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Register(string hotKeyString)
|
||||
{
|
||||
var (modifiers, key) = ParseKeysAndModifiersFromString(hotKeyString);
|
||||
Register(modifiers, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
private readonly IList<int> needNonAltGrModifier = new List<int>();
|
||||
|
||||
// These variables store the current hotkey and modifier(s)
|
||||
private IHotkeyRegistration? hotkeyRegistration;
|
||||
private IHotkeyFunction? hotkeyFunction;
|
||||
private Key hotkey = Key.None;
|
||||
private ModifierKeys modifiers = ModifierKeys.None;
|
||||
private Action? handler;
|
||||
|
@ -67,7 +67,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
};
|
||||
|
||||
PopulateModifierLists();
|
||||
SetHotkeyRegistration((IHotkeyRegistration?)null);
|
||||
SetHotkeyRegistration((IHotkeyFunction?)null);
|
||||
}
|
||||
|
||||
public static string HotkeyToString(ModifierKeys modifierKeyCode, Key key)
|
||||
|
@ -99,40 +99,41 @@ namespace SystemTrayMenu.UserInterface
|
|||
public override string ToString() => HotkeyToString(modifiers, hotkey);
|
||||
|
||||
/// <summary>
|
||||
/// Set the registration interface the control is working on.
|
||||
/// Set the hotkey function the control is working on.
|
||||
/// </summary>
|
||||
/// <param name="registration">Registration interface.</param>
|
||||
internal void SetHotkeyRegistration(IHotkeyRegistration? registration)
|
||||
/// <param name="hotkeyFunction">Hotkey function interface.</param>
|
||||
internal void SetHotkeyRegistration(IHotkeyFunction? hotkeyFunction)
|
||||
{
|
||||
hotkeyRegistration = registration;
|
||||
if (hotkeyRegistration != null)
|
||||
this.hotkeyFunction = hotkeyFunction;
|
||||
UpdateHotkeyRegistration();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the hotkey function the control is working on.
|
||||
/// </summary>
|
||||
/// <param name="hotkeyFunction">Hotkey function interface.</param>
|
||||
internal void UpdateHotkeyRegistration()
|
||||
{
|
||||
hotkey = hotkeyFunction?.GetKey() ?? Key.None;
|
||||
modifiers = hotkeyFunction?.GetModifierKeys() ?? ModifierKeys.None;
|
||||
|
||||
if (modifiers == ModifierKeys.None && hotkey == Key.None)
|
||||
{
|
||||
hotkey = hotkeyRegistration.GetKey();
|
||||
modifiers = hotkeyRegistration.GetModifierKeys();
|
||||
Background = Brushes.LightGreen;
|
||||
Background = SystemColors.ControlBrush;
|
||||
}
|
||||
else
|
||||
{
|
||||
hotkey = Key.None;
|
||||
modifiers = ModifierKeys.None;
|
||||
Background = SystemColors.ControlBrush;
|
||||
Background = Brushes.LightGreen;
|
||||
}
|
||||
|
||||
Text = HotkeyToLocalizedString(modifiers, hotkey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the registration interface the control is working on.
|
||||
/// The registration interface is looked up by given hotkey combination string.
|
||||
/// </summary>
|
||||
/// <param name="hotkeyString">Hotkey combination string.</param>
|
||||
internal void SetHotkeyRegistration(string hotkeyString) => SetHotkeyRegistration(FindRegistration(hotkeyString));
|
||||
|
||||
/// <summary>
|
||||
/// Change the hotkey to given combination.
|
||||
/// </summary>
|
||||
/// <param name="hotkeyString">Hotkey combination string.</param>
|
||||
internal void ChangeHotkey(string hotkeyString) => Reassign(hotkeyRegistration, hotkeyString);
|
||||
internal void ChangeHotkey(string hotkeyString) => hotkeyFunction?.Register(hotkeyString);
|
||||
|
||||
/// <summary>
|
||||
/// Register a hotkey.
|
||||
|
@ -151,7 +152,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
|
||||
try
|
||||
{
|
||||
hotkeyRegistration = Register(modifiers, key);
|
||||
hotkeyFunction?.Register(modifiers, key);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
|
@ -161,7 +162,10 @@ namespace SystemTrayMenu.UserInterface
|
|||
}
|
||||
|
||||
this.handler = handler;
|
||||
hotkeyRegistration.KeyPressed += (_) => handler.Invoke();
|
||||
if (hotkeyFunction != null)
|
||||
{
|
||||
hotkeyFunction.KeyPressed += (_) => handler.Invoke();
|
||||
}
|
||||
|
||||
Background = Brushes.LightGreen;
|
||||
return 1;
|
||||
|
@ -172,17 +176,16 @@ namespace SystemTrayMenu.UserInterface
|
|||
/// </summary>
|
||||
private void ResetHotkey()
|
||||
{
|
||||
hotkey = Key.None;
|
||||
modifiers = ModifierKeys.None;
|
||||
Redraw(false);
|
||||
hotkeyFunction?.Unregister();
|
||||
UpdateHotkeyRegistration();
|
||||
}
|
||||
|
||||
private void HandlePreviewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
// Handle some misc keys, such as Delete and Shift+Insert
|
||||
ModifierKeys modifiers = Keyboard.Modifiers;
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Back:
|
||||
case Key.Delete:
|
||||
ResetHotkey();
|
||||
e.Handled = true;
|
||||
|
@ -199,58 +202,45 @@ namespace SystemTrayMenu.UserInterface
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redraws the TextBox when necessary.
|
||||
/// </summary>
|
||||
/// <param name="bCalledProgramatically">Specifies whether this function was called by the Hotkey/HotkeyModifiers properties or by the user.</param>
|
||||
private void Redraw(bool bCalledProgramatically)
|
||||
// TODO: Instead of Redraw this seem to act more like an input filter for valid combinations?
|
||||
// Maybe move to places right before Register() calls of the hotkeyFunction
|
||||
private void Redraw()
|
||||
{
|
||||
// No hotkey set
|
||||
if (hotkey == Key.None)
|
||||
// No modifier or shift only, AND a hotkey that needs another modifier
|
||||
if ((modifiers == ModifierKeys.Shift || modifiers == ModifierKeys.None) && needNonShiftModifier.Contains((int)hotkey))
|
||||
{
|
||||
Text = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
// Only validate input if it comes from the user
|
||||
if (bCalledProgramatically == false)
|
||||
{
|
||||
// No modifier or shift only, AND a hotkey that needs another modifier
|
||||
if ((modifiers == ModifierKeys.Shift || modifiers == ModifierKeys.None) && needNonShiftModifier.Contains((int)hotkey))
|
||||
if (modifiers == ModifierKeys.None)
|
||||
{
|
||||
if (modifiers == ModifierKeys.None)
|
||||
// Set Ctrl+Alt as the modifier unless Ctrl+Alt+<key> won't work...
|
||||
if (needNonAltGrModifier.Contains((int)hotkey) == false)
|
||||
{
|
||||
// Set Ctrl+Alt as the modifier unless Ctrl+Alt+<key> won't work...
|
||||
if (needNonAltGrModifier.Contains((int)hotkey) == false)
|
||||
{
|
||||
modifiers = ModifierKeys.Alt | ModifierKeys.Control;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ... in that case, use Shift+Alt instead.
|
||||
modifiers = ModifierKeys.Alt | ModifierKeys.Shift;
|
||||
}
|
||||
modifiers = ModifierKeys.Alt | ModifierKeys.Control;
|
||||
}
|
||||
else
|
||||
{
|
||||
// User pressed Shift and an invalid key (e.g. a letter or a number),
|
||||
// that needs another set of modifier keys
|
||||
hotkey = Key.None;
|
||||
Text = string.Empty;
|
||||
return;
|
||||
// ... in that case, use Shift+Alt instead.
|
||||
modifiers = ModifierKeys.Alt | ModifierKeys.Shift;
|
||||
}
|
||||
}
|
||||
|
||||
// Check all Ctrl+Alt keys
|
||||
if (modifiers == (ModifierKeys.Alt | ModifierKeys.Control) && needNonAltGrModifier.Contains((int)hotkey))
|
||||
else
|
||||
{
|
||||
// Ctrl+Alt+4 etc won't work; reset hotkey and tell the user
|
||||
// User pressed Shift and an invalid key (e.g. a letter or a number),
|
||||
// that needs another set of modifier keys
|
||||
hotkey = Key.None;
|
||||
Text = string.Empty;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check all Ctrl+Alt keys
|
||||
if (modifiers == (ModifierKeys.Alt | ModifierKeys.Control) && needNonAltGrModifier.Contains((int)hotkey))
|
||||
{
|
||||
// Ctrl+Alt+4 etc won't work; reset hotkey and tell the user
|
||||
hotkey = Key.None;
|
||||
Text = string.Empty;
|
||||
return;
|
||||
}
|
||||
|
||||
// I have no idea why this is needed, but it is. Without this code, pressing only Ctrl
|
||||
// will show up as "Control + ControlKey", etc.
|
||||
if (hotkey == Key.LeftAlt || hotkey == Key.RightAlt ||
|
||||
|
@ -327,8 +317,8 @@ namespace SystemTrayMenu.UserInterface
|
|||
{
|
||||
modifiers = Keyboard.Modifiers;
|
||||
hotkey = e.Key;
|
||||
Reassign(hotkeyRegistration, modifiers, hotkey);
|
||||
Redraw(false);
|
||||
hotkeyFunction?.Register(modifiers, hotkey);
|
||||
UpdateHotkeyRegistration();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,7 +333,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
{
|
||||
modifiers = Keyboard.Modifiers;
|
||||
hotkey = e.Key;
|
||||
Redraw(false);
|
||||
UpdateHotkeyRegistration();
|
||||
}
|
||||
else if (hotkey == Key.None && modifiers == ModifierKeys.None)
|
||||
{
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
|
||||
checkBoxCheckForUpdates.IsChecked = Settings.Default.CheckForUpdates;
|
||||
|
||||
textBoxHotkey.SetHotkeyRegistration(Settings.Default.HotKey);
|
||||
textBoxHotkey.SetHotkeyRegistration(GlobalHotkeys.GetLastCreatedHotkeyFunction());
|
||||
|
||||
InitializeLanguage();
|
||||
void InitializeLanguage()
|
||||
|
|
Loading…
Reference in a new issue