Skip to content

Instantly share code, notes, and snippets.

@KuroiLight
Created May 26, 2024 17:21
Show Gist options
  • Save KuroiLight/aea214c3ac299c1fbaf4e5f0345b2b1a to your computer and use it in GitHub Desktop.
Save KuroiLight/aea214c3ac299c1fbaf4e5f0345b2b1a to your computer and use it in GitHub Desktop.
;Author: KuroiLight - klomb - <kuroilight@openmailbox.org>
;Started On: 08/08/15
;License: Public Domain (http://www.unlicense.org/)
GetUserHotkey(enable := true) {
global __htky, __last_valid
static WH_KEYBOARD := 2, WH_MOUSE_LL := 14, KBHHandle := 0, MHHandle := 0, info
static MouseCallback := RegisterCallback("MouseProc",,3), KeyboardCallback := RegisterCallback("KeyboardProc",,3)
if(MHHandle) {
DllCall("UnhookWindowsHookEx", Ptr, MHHandle)
MHHandle := 0
}
if(KBHHandle) {
DllCall("UnhookWindowsHookEx", Ptr, KBHHandle)
KBHHandle := 0
}
if(enable) {
KBHHandle := DllCall("SetWindowsHookEx", Int, WH_KEYBOARD, Ptr, KeyboardCallback, Ptr, 0, Int, DllCall("GetCurrentThreadId")) ;application level kb hook (local)
MHHandle := DllCall("SetWindowsHookEx", Int, WH_MOUSE_LL, Ptr, MouseCallback, Ptr, 0, Int, 0) ;low level mouse hook (global)
Gui, _klhtkywin: New, -SysMenu -Border
Gui, font,, Consolas
Gui, Add, Text, Center vinfo, % "Press the key combination for your hotkey."
Gui, font, w800
Gui, Add, Text, Center v__htky, % " "
Gui, Show, Center Autosize
Gui, _klhtkywin: +LastFound
WinWaitClose,
return __last_valid
} else {
Gui, _klhtkywin:Cancel
}
}
KeyboardProc(code, wParam, lParam) {
if(code != 0)
return DllCall("CallNextHookEx", Ptr, 0, Int, code, Ptr, wParam, Ptr, lParam)
vk := wParam ;get vk
keydown := (0x80000000 & lParam) ? false : true ;get keyup bits only (bit 31)
sc := (lParam & 0x1FF0000) >> 16 ;get sc/ext bits only (bits 16-24)
ProcessKey(GetKeyName(Format("vk{1:x}sc{2:x}", vk, sc)), keydown)
return 1 ;block input, stops dinging
}
MouseProc(code, wParam, lParam) {
static mouse_buttons := {0x0201:"LButtonD", 0x0204:"RButtonD", 0x0207:"MButtonD", 0x20B:"XButtonD", 0x0202:"LButton", 0x0205:"RButton", 0x0208:"MButton", 0x20C:"XButton"}
if(code != 0)
return DllCall("CallNextHookEx", Ptr, 0, Int, code, Ptr, wParam, Ptr, lParam)
mouse_button := ""
for hex, name in mouse_buttons
if(wParam = hex)
mouse_button := StrReplace(name, "D", "", button_down) ;if D exists in name it will be removed and the button_down flag set to 1
if(mouse_button == "XButton")
mouse_button .= *(lParam+10) ;get the byte at the high-word in mouseData, which is either 1 or 2.
if(mouse_button)
ProcessKey(mouse_button, button_down)
return 0 ;dont block input
}
test_label:
return
ProcessKey(key, state) {
static keysdown := "", key_count := 0
global __last_valid
static regex_mods_all := "S)(?:Control|Shift|Alt|Win)*"
static def_map := {"Control":"^", "Shift":"+", "Alt":"!", "Win":"#"}
ahk_hotkey := ""
if(key = "")
return
if(state) {
if(RegExMatch(keysdown, "S)(?:^|\s)" . key . "(?:\s|$)"))
return ;return early
key_count++
keysdown .= (key_count > 1 ? " " : "") . key
tcount := key_count
for k, v in def_map {
if(InStr(keysdown, k)) {
if(tcount > 1)
ahk_hotkey .= v
else
ahk_hotkey .= k
tcount--
}
}
ahk_hotkey .= Trim(RegExReplace(keysdown, regex_mods_all))
Hotkey, %ahk_hotkey%, test_label, UseErrorLevel Off
if(ErrorLevel == 0)
__last_valid := ahk_hotkey
} else {
if(key_count = 1)
keysdown := StrReplace(keysdown, key)
else
keysdown := RegExReplace(keysdown, "S)(?:^|\s)" . key . "(?:(\s)|$)", "$1")
key_count--
if(__last_valid) {
GetUserHotkey(false) ;remove the hooks
MsgBox, 0x4,, % "You selected " . __last_valid . " as your hotkey.`nEnable passthrough? (no if you don't know what this is)"
IfMsgBox, Yes
__last_valid := "~" . __last_valid
Gui _klhtkywin:Destroy
}
}
GuiControl, _klhtkywin:Text, __htky, % StrReplace(__last_valid, "&", "&&")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment