Modifier key as dynamic hotkeys

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
raron
Posts: 37
Joined: 11 Aug 2014, 00:50

Modifier key as dynamic hotkeys

Post by raron » 11 Sep 2021, 02:46

Hi.

So, I'm not too sure how useful this is. It's just a normal AHK hotkey field but used in a (cumbersome) way so modifier keys can be used as hotkeys. Baiscally just a WIP / test.
  • Any normal AHK hotkey should work
  • Modifier keys (Shift, Ctrl, Alt) alone or in combination works (mostly...)
  • No distinction between left / right Shift or Ctrl. Pretty sure same for left / right Alt, but I only have the Alt-gr key (which is ctrl+alt)
  • Not the Win key, not sure how to use that.
It might not be quite 100% trustworhty. I've noticed the occasional stuck Ctrl key at times... (possibly others, not tested that extensively)

For modifier combos, the rule seems to be: The last key visible in the hotkey edit field is the last one you have to press down but release first for it to register both key-down and key-up.
(if you switch it up and press it down not-last or first, and still release it first, it's tricked into firing only the "key up" event).

Btw, you can even have modifier wildcard on the modifier. So if you define Ctrl as a hotkey, then it will fire even with any other modifier keys (alt-ctrl etc).

I haven't tried this with more than one hotkey yet btw.

Btw I know about evilC's AppFactory library viewtopic.php?f=65&t=33070
I actually haven't looked too close at it, but I know it's a lot more refined with more features (mouse/joystick buttons etc). So you're probably better off using that :)

I just wanted to see where I could go with this (plus I wanted something simple-ish).

The code:

Code: Select all

; Modifiers as dynamic hotkey Test 4
; 2021.09.11 raron

#SingleInstance, force
;#InstallKeybdHook
;#UseHook On
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

;SendLevel, 2

wTitle      := "Modifiers as dynamic hotkey Test"
key_hotkey1 := "q" ; initial hotkey
wildcard    := "" ; try "*" to ignore modifiers (even on modifiers!)
GUIactiveID := 0

Gui, New
Gui, Add, Hotkey, x50 y100 w150 gHotkey1Change vhkField1, % key_hotkey1
Gui, Add, Button, x220 y100 gBtnClicked, Activate hotkey

Gui, Show, w400 h300, % wTitle
OnExit, GuiClose

Gosub SetHotkey1

Return

GuiClose:
ExitApp



; To keep a modifier visible in the hotkey control after key up
Hotkey1Change:
  ;MsgBox % " test: " . hkField1 ; seems to "use up" the hotkey edit field

  if (hkField1 == "+") {
    GuiControl,, hkField1, % "SHIFT"
    return
  }

  if (hkField1 == "^")  {
    GuiControl,, hkField1, % "CTRL"
    return
  }

  if (hkField1 == "!") {
    GuiControl,, hkField1, % "ALT"
    return
  }

  if (hkField1 == "+^") {
    GuiControl,, hkField1, % "+CTRL"
    return
  }

  if (hkField1 == "+!") {
    GuiControl,, hkField1, % "+ALT"
    return
  }

  if (hkField1 == "^!") {
    GuiControl,, hkField1, % "^ALT"
    return
  }

  if (hkField1 == "+^!") {
    GuiControl,, hkField1, % "+!CTRL"
    return
  }

return


BtnClicked:
  ; Remove old hotkey
  Hotkey, % wildcard . key_hotkey1,,    Off ; UseErrorLevel
  Hotkey, % wildcard . key_hotkey1 . " up",, Off ; UseErrorLevel
  ; Get new hotkey
  GuiControlGet, key_hotkey1,, hkField1
  ; Set new hotkey
SetHotkey1:
  Hotkey, % wildcard . key_hotkey1   , hotkey1_down, On
  Hotkey, % wildcard . key_hotkey1 . " up", hotkey1_up,   On
Return


hotkey1_down:
  msgbox % "You hold down " . key_hotkey1
  SendKeyDownIfActiveGui(key_hotkey1)
  ;send a
  ;KeyWait, % key_hotkey1
Return

hotkey1_up:
  msgbox % "You released " . key_hotkey1
  SendKeyUpIfActiveGui(key_hotkey1)
  ;send b
Return


; Also send hotkey if GUI is in focus / active (in case of redefining hotkeys)
 SendKeyDownIfActiveGui(thehotkey)
 {
  global wTitle, GUIactiveID
	GUIactiveID := WinActive(wTitle)
	if (GUIactiveID != 0) {
		Send % "{" . thehotkey . " down}"
    sleep 50 ; to allow the GUI to reliably(ish) receive the key(?)
	}
}

SendKeyUpIfActiveGui(thehotkey)
{
  global wTitle, GUIactiveID
  if (GUIactiveID != 0) {
    Send % "{" . thehotkey . " up}"
    GUIactiveID := 0
  }
}

Return to “Scripts and Functions (v1)”