This is due to Windows behaviour, and is not an AutoHotkey bug.
The hotkey is detected and sends the key-down/up event as requested, but
the OS does not respond as you expect it to.
AutoHotkey does send some extra NumLock key events you did not ask for, but if it didn't, things would be
worse. This is the related code (and comments):
Code: Select all
// This handles the troublesome Numlock key, which on some (most/all?) keyboards
// will change state independent of the keyboard's indicator light even if its
// keydown and up events are suppressed. This is certainly true on the
// MS Natural Elite keyboard using default drivers on WinXP. SetKeyboardState()
// doesn't resolve this, so the only alternative to the below is to use the
// Win9x method of setting the Numlock state explicitly whenever the key is released.
// That might be complicated by the fact that the unexpected state change described
// here can't be detected by GetKeyboardState() and such (it sees the state indicated
// by the numlock light on the keyboard, which is wrong). In addition, doing it this
// way allows Numlock to be a prefix key for something like Numpad7, which would
// otherwise be impossible because Numpad7 would become NumpadHome the moment
// Numlock was pressed down. Note: this problem doesn't appear to affect Capslock
// or Scrolllock for some reason, possibly hardware or driver related.
// Note: the check for KEY_IGNORE isn't strictly necessary, but here just for safety
// in case this is ever called for a key that should be ignored. If that were
// to happen and we didn't check for it, and endless loop of keyboard events
// might be caused due to the keybd events sent below.
if (aHook == g_KeybdHook)
{
KBDLLHOOKSTRUCT &event = *(PKBDLLHOOKSTRUCT)lParam;
if (aVK == VK_NUMLOCK && !aKeyUp && !IsIgnored(event.dwExtraInfo))
{
// This seems to undo the faulty indicator light problem and toggle
// the key back to the state it was in prior to when the user pressed it.
// Originally, I had two keydowns and before that some keyups too, but
// testing reveals that only a single key-down is needed. UPDATE:
// It appears that all 4 of these key events are needed to make it work
// in every situation, especially the case when ForceNumlock is on but
// numlock isn't used for any hotkeys.
// Note: The only side-effect I've discovered of this method is that the
// indicator light can't be toggled after the program is exitted unless the
// key is pressed twice:
KeyEvent(KEYUP, VK_NUMLOCK);
KeyEvent(KEYDOWNANDUP, VK_NUMLOCK);
KeyEvent(KEYDOWN, VK_NUMLOCK);
}
UpdateKeybdState(event, aVK, aSC, aKeyUp, true);
}
I need to have this hotkey setup because I need the NumLock key to behave differently based on some global variables.
That's faulty logic. This hotkey setup is what you are trying to use to achieve your end goal, but obviously this setup isn't working. So why do you need to have this setup and not some other setup which works?
When you want a key to have its native function,
don't override it. Overriding a key and then
sending that same key is guaranteed to have some kind of side-effect, whether it's how this or other scripts treat the key, how some other application treats the key, or (as in this case) how the OS treats the key.
There are two ways to override a key only when you actually need to:
- Use the Hotkey command to register/enable the hotkey when it is needed and unregister/disable it when it is not.
- Use the #If directive (above the hotkey) with an expression which evaluates to true while the hotkey is needed and false at any other time.