Skip to content

Commit

Permalink
Fix GetKeyName to support WPF's Key as base type.
Browse files Browse the repository at this point in the history
  • Loading branch information
topeterk committed May 26, 2023
1 parent 1c22c86 commit 60329d5
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 35 deletions.
46 changes: 26 additions & 20 deletions Helpers/GlobalHotkeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,19 +176,21 @@ internal static string HotkeyToLocalizedString(ModifierKeys modifiers, Key key)
return hotkeyString.ToString() + GetKeyName(key);
}

private static string GetKeyName(Key givenKey)
private static string GetKeyName(Key key)
{
StringBuilder keyName = new();
const uint numpad = 55;
const uint MAPVK_VK_TO_VSC = 0;
const uint KF_EXTENDED = 0x100;
const uint SCANCODE_SIMULATED = 0x200;
const uint scanCodeNumPad = 0x37;
const uint scanCodePause = 0x45;

Key virtualKey = givenKey;
StringBuilder keyName = new(100);
string keyString = string.Empty;

// Make VC's to real keys
switch (virtualKey)
switch (key)
{
case Key.Multiply:
if (NativeMethods.User32GetKeyNameText(numpad << 16, keyName, 100) > 0)
if (NativeMethods.User32GetKeyNameText(scanCodeNumPad << 16, keyName, keyName.Capacity) > 0)
{
keyString = keyName.ToString().Replace("*", string.Empty, StringComparison.InvariantCulture).Trim().ToLowerInvariant();
if (keyString.Contains('('))
Expand All @@ -201,7 +203,7 @@ private static string GetKeyName(Key givenKey)

return keyString + " *";
case Key.Divide:
if (NativeMethods.User32GetKeyNameText(numpad << 16, keyName, 100) > 0)
if (NativeMethods.User32GetKeyNameText(scanCodeNumPad << 16, keyName, keyName.Capacity) > 0)
{
keyString = keyName.ToString().Replace("*", string.Empty, StringComparison.InvariantCulture).Trim().ToLowerInvariant();
if (keyString.Contains('('))
Expand All @@ -215,11 +217,15 @@ private static string GetKeyName(Key givenKey)
return keyString + " /";
}

const uint MAPVK_VK_TO_VSC = 0;
uint scanCode = NativeMethods.User32MapVirtualKey((uint)virtualKey, MAPVK_VK_TO_VSC);
// Converting Windows Input Key Enums into Virtual-Key Codes into Scan Codes into Text
// - Windows Input Key Enums: https://learn.microsoft.com/en-us/dotnet/api/system.windows.input.key?view=windowsdesktop-7.0
// - Virtual-Key Codes: https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
// - Scan Codes: https://learn.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input#scan-codes
uint virtualKeyCode = (uint)KeyInterop.VirtualKeyFromKey(key);
uint scanCode = NativeMethods.User32MapVirtualKey(virtualKeyCode, MAPVK_VK_TO_VSC);

// because MapVirtualKey strips the extended bit for some keys
switch (virtualKey)
// Handle names of some special keys
switch (key)
{
case Key.Left:
case Key.Up:
Expand All @@ -232,18 +238,18 @@ private static string GetKeyName(Key givenKey)
case Key.Insert:
case Key.Delete:
case Key.NumLock:
scanCode |= 0x100; // set extended bit
scanCode |= KF_EXTENDED; // set extended bit (simulate origin from enhanced 101/102-key keyboard)
break;
case Key.PrintScreen: // PrintScreen
scanCode = 311;
case Key.PrintScreen:
scanCode = KF_EXTENDED | scanCodeNumPad;
break;
case Key.Pause: // PrintScreen
scanCode = 69;
case Key.Pause:
scanCode = scanCodePause;
break;
}

scanCode |= 0x200;
if (NativeMethods.User32GetKeyNameText(scanCode << 16, keyName, 100) != 0)
scanCode |= SCANCODE_SIMULATED;
if (NativeMethods.User32GetKeyNameText(scanCode << 16, keyName, keyName.Capacity) != 0)
{
string visibleName = keyName.ToString();
if (visibleName.Length > 1)
Expand All @@ -255,7 +261,7 @@ private static string GetKeyName(Key givenKey)
}
else
{
return givenKey.ToString();
return key.ToString();
}
}
}
Expand Down
29 changes: 14 additions & 15 deletions UserInterface/HotkeySelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,19 @@ public void Dispose()
GC.SuppressFinalize(this);
}

public override string ToString() => HotkeyToString(modifiers, hotkey);

/// <summary>
/// Used to get/set the hotkey (e.g. Key.A).
/// </summary>
/// <param name="hotkey">hotkey.</param>
public void SetHotkey(string hotkey)
{
this.hotkey = GlobalHotkeys.KeyFromString(hotkey);
modifiers = GlobalHotkeys.ModifierKeysFromString(hotkey);
Redraw(true);
}

/// <summary>
/// Register a hotkey.
/// </summary>
Expand All @@ -151,7 +164,6 @@ public int RegisterHotKey(ModifierKeys modifiers, Key key, Action handler)
return 0;
}


try
{
hook.RegisterHotKey(modifiers, key);
Expand Down Expand Up @@ -185,26 +197,13 @@ private void UnregisterHotKey()
/// <summary>
/// Clears the current hotkey and resets the TextBox.
/// </summary>
public void ResetHotkey()
private void ResetHotkey()
{
hotkey = Key.None;
modifiers = ModifierKeys.None;
Redraw(false);
}

/// <summary>
/// Used to get/set the hotkey (e.g. Key.A).
/// </summary>
/// <param name="hotkey">hotkey.</param>
public void SetHotkey(string hotkey)
{
this.hotkey = GlobalHotkeys.KeyFromString(hotkey);
modifiers = GlobalHotkeys.ModifierKeysFromString(hotkey);
Redraw(true);
}

public override string ToString() => HotkeyToString(modifiers, hotkey);

private void HandlePreviewKeyDown(object sender, KeyEventArgs e)
{
// Handle some misc keys, such as Delete and Shift+Insert
Expand Down

0 comments on commit 60329d5

Please sign in to comment.