mirror of
https://github.com/Hofknecht/SystemTrayMenu.git
synced 2024-09-06 20:51:15 +12:00
Initial reassign of hotkeys
This commit is contained in:
parent
ce2d9772f6
commit
637cc46e7e
3 changed files with 79 additions and 43 deletions
|
@ -39,6 +39,12 @@ namespace SystemTrayMenu.Helpers
|
||||||
Key GetKey();
|
Key GetKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether hotkeys are enabled
|
||||||
|
/// (e.g. during user configuration dialog).
|
||||||
|
/// </summary>
|
||||||
|
internal static bool IsEnabled { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers a global hotkey.
|
/// Registers a global hotkey.
|
||||||
/// Function is thread safe.
|
/// Function is thread safe.
|
||||||
|
@ -57,9 +63,9 @@ namespace SystemTrayMenu.Helpers
|
||||||
{
|
{
|
||||||
foreach (var reg in Registrations)
|
foreach (var reg in Registrations)
|
||||||
{
|
{
|
||||||
if (id < reg.Id)
|
if (id <= reg.Id)
|
||||||
{
|
{
|
||||||
id = reg.Id;
|
id = reg.Id + 1; // TODO: Rework to re-use gaps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +108,7 @@ namespace SystemTrayMenu.Helpers
|
||||||
/// <returns>true: Success or false: Failure.</returns>
|
/// <returns>true: Success or false: Failure.</returns>
|
||||||
internal static bool Unregister(IHotkeyRegistration? registration)
|
internal static bool Unregister(IHotkeyRegistration? registration)
|
||||||
{
|
{
|
||||||
if (registration == null || registration is not HotkeyRegistration reg || Registrations.Contains(reg))
|
if (registration == null || registration is not HotkeyRegistration reg || !Registrations.Contains(reg))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -120,6 +126,61 @@ namespace SystemTrayMenu.Helpers
|
||||||
return true;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Instead of searching for the registration, it should be passed to the caller instead.
|
// 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.
|
// Only this ensures caller and registrator are talking about the SAME registration.
|
||||||
internal static IHotkeyRegistration? FindRegistration(string hotKeyString)
|
internal static IHotkeyRegistration? FindRegistration(string hotKeyString)
|
||||||
|
@ -316,7 +377,7 @@ namespace SystemTrayMenu.Helpers
|
||||||
const int WmHotkey = 0x0312;
|
const int WmHotkey = 0x0312;
|
||||||
|
|
||||||
// check if we got a hot key pressed.
|
// check if we got a hot key pressed.
|
||||||
if (msg == WmHotkey)
|
if (msg == WmHotkey && IsEnabled)
|
||||||
{
|
{
|
||||||
ModifierKeys modifiers = (ModifierKeys)((int)lParam & 0xFFFF);
|
ModifierKeys modifiers = (ModifierKeys)((int)lParam & 0xFFFF);
|
||||||
int virtualKeyCode = ((int)lParam >> 16) & 0xFFFF;
|
int virtualKeyCode = ((int)lParam >> 16) & 0xFFFF;
|
||||||
|
@ -346,7 +407,7 @@ namespace SystemTrayMenu.Helpers
|
||||||
{
|
{
|
||||||
public event Action<IHotkeyRegistration>? KeyPressed;
|
public event Action<IHotkeyRegistration>? KeyPressed;
|
||||||
|
|
||||||
internal int Id { get; init; }
|
internal int Id { get; set; }
|
||||||
|
|
||||||
internal ModifierKeys Modifiers { get; set; }
|
internal ModifierKeys Modifiers { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace SystemTrayMenu.UserInterface
|
||||||
private readonly IList<int> needNonAltGrModifier = new List<int>();
|
private readonly IList<int> needNonAltGrModifier = new List<int>();
|
||||||
|
|
||||||
// These variables store the current hotkey and modifier(s)
|
// These variables store the current hotkey and modifier(s)
|
||||||
private IHotkeyRegistration? hotkeyHandle;
|
private IHotkeyRegistration? hotkeyRegistration;
|
||||||
private Key hotkey = Key.None;
|
private Key hotkey = Key.None;
|
||||||
private ModifierKeys modifiers = ModifierKeys.None;
|
private ModifierKeys modifiers = ModifierKeys.None;
|
||||||
private Action? handler;
|
private Action? handler;
|
||||||
|
@ -48,11 +48,7 @@ namespace SystemTrayMenu.UserInterface
|
||||||
PreviewKeyDown += HandlePreviewKeyDown;
|
PreviewKeyDown += HandlePreviewKeyDown;
|
||||||
PreviewTextInput += HandlePreviewTextInput;
|
PreviewTextInput += HandlePreviewTextInput;
|
||||||
|
|
||||||
GotFocus += (_, _) =>
|
GotFocus += (_, _) => GlobalHotkeys.IsEnabled = false;
|
||||||
{
|
|
||||||
UnregisterHotKey();
|
|
||||||
Reassigning = true;
|
|
||||||
};
|
|
||||||
LostFocus += (_, _) =>
|
LostFocus += (_, _) =>
|
||||||
{
|
{
|
||||||
#if TODO // HOTKEY
|
#if TODO // HOTKEY
|
||||||
|
@ -66,18 +62,14 @@ namespace SystemTrayMenu.UserInterface
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Whether the hotkeys could be registered to the users content. This also applies if conflicts arise and the user decides to ignore these (i.e. not to register the conflicting hotkey).</returns>
|
/// <returns>Whether the hotkeys could be registered to the users content. This also applies if conflicts arise and the user decides to ignore these (i.e. not to register the conflicting hotkey).</returns>
|
||||||
RegisterHotkeys(false);
|
RegisterHotkeys(false);
|
||||||
#else
|
|
||||||
ReregisterHotKey();
|
|
||||||
#endif
|
#endif
|
||||||
Reassigning = false;
|
GlobalHotkeys.IsEnabled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
PopulateModifierLists();
|
PopulateModifierLists();
|
||||||
SetHotkeyRegistration((IHotkeyRegistration?)null);
|
SetHotkeyRegistration((IHotkeyRegistration?)null);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal bool Reassigning { get; private set; }
|
|
||||||
|
|
||||||
public static string HotkeyToString(ModifierKeys modifierKeyCode, Key key)
|
public static string HotkeyToString(ModifierKeys modifierKeyCode, Key key)
|
||||||
{
|
{
|
||||||
StringBuilder hotkeyString = new();
|
StringBuilder hotkeyString = new();
|
||||||
|
@ -112,11 +104,11 @@ namespace SystemTrayMenu.UserInterface
|
||||||
/// <param name="registration">Registration interface.</param>
|
/// <param name="registration">Registration interface.</param>
|
||||||
internal void SetHotkeyRegistration(IHotkeyRegistration? registration)
|
internal void SetHotkeyRegistration(IHotkeyRegistration? registration)
|
||||||
{
|
{
|
||||||
hotkeyHandle = registration;
|
hotkeyRegistration = registration;
|
||||||
if (hotkeyHandle != null)
|
if (hotkeyRegistration != null)
|
||||||
{
|
{
|
||||||
hotkey = hotkeyHandle.GetKey();
|
hotkey = hotkeyRegistration.GetKey();
|
||||||
modifiers = hotkeyHandle.GetModifierKeys();
|
modifiers = hotkeyRegistration.GetModifierKeys();
|
||||||
Background = Brushes.LightGreen;
|
Background = Brushes.LightGreen;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -140,12 +132,7 @@ namespace SystemTrayMenu.UserInterface
|
||||||
/// Change the hotkey to given combination.
|
/// Change the hotkey to given combination.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="hotkeyString">Hotkey combination string.</param>
|
/// <param name="hotkeyString">Hotkey combination string.</param>
|
||||||
internal void ChangeHotkey(string hotkeyString)
|
internal void ChangeHotkey(string hotkeyString) => Reassign(hotkeyRegistration, hotkeyString);
|
||||||
{
|
|
||||||
hotkey = KeyFromString(hotkeyString);
|
|
||||||
modifiers = ModifierKeysFromString(hotkeyString);
|
|
||||||
Redraw(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register a hotkey.
|
/// Register a hotkey.
|
||||||
|
@ -164,7 +151,7 @@ namespace SystemTrayMenu.UserInterface
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
hotkeyHandle = Register(modifiers, key);
|
hotkeyRegistration = Register(modifiers, key);
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
|
@ -174,26 +161,12 @@ namespace SystemTrayMenu.UserInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
hotkeyHandle.KeyPressed += (_) => handler.Invoke();
|
hotkeyRegistration.KeyPressed += (_) => handler.Invoke();
|
||||||
|
|
||||||
Background = Brushes.LightGreen;
|
Background = Brushes.LightGreen;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReregisterHotKey()
|
|
||||||
{
|
|
||||||
if (handler != null)
|
|
||||||
{
|
|
||||||
RegisterHotKey(modifiers, hotkey, handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UnregisterHotKey()
|
|
||||||
{
|
|
||||||
Unregister(hotkeyHandle);
|
|
||||||
hotkeyHandle = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clears the current hotkey and resets the TextBox.
|
/// Clears the current hotkey and resets the TextBox.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -354,6 +327,7 @@ namespace SystemTrayMenu.UserInterface
|
||||||
{
|
{
|
||||||
modifiers = Keyboard.Modifiers;
|
modifiers = Keyboard.Modifiers;
|
||||||
hotkey = e.Key;
|
hotkey = e.Key;
|
||||||
|
Reassign(hotkeyRegistration, modifiers, hotkey);
|
||||||
Redraw(false);
|
Redraw(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace SystemTrayMenu.UserInterface
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
using SystemTrayMenu.Helpers;
|
||||||
using SystemTrayMenu.Properties;
|
using SystemTrayMenu.Properties;
|
||||||
using SystemTrayMenu.UserInterface.FolderBrowseDialog;
|
using SystemTrayMenu.UserInterface.FolderBrowseDialog;
|
||||||
using SystemTrayMenu.Utilities;
|
using SystemTrayMenu.Utilities;
|
||||||
|
@ -445,7 +446,7 @@ namespace SystemTrayMenu.UserInterface
|
||||||
|
|
||||||
private void HandlePreviewKeyDown(object sender, KeyEventArgs e)
|
private void HandlePreviewKeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Key == Key.Escape && !textBoxHotkey.Reassigning)
|
if (e.Key == Key.Escape && GlobalHotkeys.IsEnabled)
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue