轻松定义双击热键(或三击、四击等)

Plain text
复制到剪贴板
Open code in new window
EnlighterJS 3 Syntax Highlighter
; 来源:https://www.autohotkey.com/boards/viewtopic.php?f=6&t=95596
#Persistent
#NoEnv
#SingleInstance, force
SetTitleMatchMode, RegEx
SetBatchLines, -1
mk := new MultiHotkeys()
; Use hotkey command before definition to make context sensitive:
; Hotkey, IfWinActive, Notepad
mk.Add("d" , "t200" , "d") ; send d if the below times out
mk.Add("dd" , , "Test" , "Double hotkey") ; Calling functions
mk.Add("ddd" , , "Test" , "Triple hotkey!")
mk.Add("dddd" , , "Test" , "Quadruple hotkey!!")
mk.Add("{F1}{F1}" , , "Test2") ; Calling a label; F1 > F1
mk.Add("^{F1}{F1}" , , "Test3") ; Sending a string; Ctrl+F1 > F1
mk.Add("+t" , , "T") ; Capital T if Shift+t times out
mk.Add("+thisisatest" , "t1000", "Test" , "Hello," ,"World!") ; Sending 2 parameters ; Shift+t > hisisatest
mk.Add("#{Capslock}{F2}{F3}", "t800" , "Test" , "Wow, this is a long hotkey!") ; Win+Caps > F2 > F3
return
Test(param1:="",param2:="") {
global mk
str := mk.inputStr
if param1
str .= "`r`n" param1
if param2
str .= "`r`n" param2
tooltip, % str
SetTimer, Tooltipoff, -3000
return
TooltipOff:
tooltip
return
}
Test2:
msgbox, % A_ThisLabel "`r`n" mk.inputStr
return
;---------------------------------------------------------------------------------------------------------------------------------------
;
; Class_Multihotkeys.ahk v0.1 by evilmanimani
;
;
; Easily set up double, triple, or more hotkeys, and more for pseudo hotstrings, with a configurable timeout
; Can go functions with parameters, labels, or just send characters if it doesn't match a function/label
; If two input strings are similar i.e. (!aa, !aaa, !aaaa), it will trigger the shorter ones after the timeout
; , the longest will be triggered immediately.
;
; mh := new MultiHotkeys() to start
;
; The only public method is Add, see examples for details:
;
; - keys: string of letter keys, optionally starting with modifiers the modifier only needs to be held for the first key
; should support ~, but not really tested.
; - options: at the moment, only supports a timeout in milliseconds, this is the timeout period between each keypress
; of the full input string, entered as t400, t1000, etc; defaults to 400ms; the timeout applies to any configured
; input string that shares the same starting hotkey (the modifiers and first character)
; - function: either a function or label name, any other text not matching a function onr label will be sent as-is
; - params: if passing a Function, any amount of associated params are supported
;
;
Class MultiHotkeys {
__New(options:="") { ; not much for options here yet
this.ih := InputHook(Options)
this.KeyDict := {}
}
Add(keys, options:="", function :="", params*) {
static optLookup := {"T":"timeout","t":"timeout"}
for i, opt in StrSplit(options, A_Space) {
if optLookup.HasKey(SubStr(opt,1,1)) {
var := optLookup[SubStr(opt,1,1)]
%var% := SubStr(opt,2)
}
}
RegExMatch(keys, "O)^(?<mods>[~!^+#]{1,4})?(?<keys>.*)", keys)
mods := StrReplace(keys.mods,"~",,noHide)
keyStr := keys.keys
If IsFunc(function) {
if params
func := Func(function).Bind(params*)
else
func := Func(function)
}
if IsObject(keyStr) {
; to-do: put in support for simple remaps via passing an array, i.e. mp.Add({"aa":"b","bb":"c","cc":"d"},,"Test")
} else {
hotkeyFunc := ObjBindMethod(this,"HotkeyHandler")
pos := 1
loop {
pos := RegExMatch(keyStr,"({.*?})|(\w)",key,pos)
if (A_Index = 1) {
pos += StrLen(key)
firstKey := key
hk := ( noHide ? "~" : "$") . mods . RegExReplace(key, "[{}]")
HotKey, % hk, % hotkeyFunc
} else {
this.ih.KeyOpt(key, "+E+S")
pos += StrLen(key)
}
} Until (!key)
keyStr := StrReplace(keyStr, firstKey, , , 1)
keyStr := RegExReplace(keyStr, "[{}]")
for i, e in StrSplit(keys) {
if (e = "{")
this.ih.KeyOpt(e, "+E+S")
}
if !isObject(this.KeyDict[hk]) {
this.KeyDict[hk] := {}
this.KeyDict[hk].timeout := timeout ? Format("{:.1f}", timeout / 1000) : 0.4
}
this.KeyDict[hk][keyStr] := {}
this.KeyDict[hk][keyStr].function := func
this.KeyDict[hk][keyStr].funcName := function
if mods
this.KeyDict[hk][keyStr].mods := mods
}
}
HotkeyHandler() {
Suspend, On
thisHotkey := A_ThisHotkey
Mods := RegExReplace(thisHotkey, "i)^[~\$]*([!^+#]{0,4}).*$", "$1")
timeout := this.KeyDict[thisHotkey].timeout
loop {
matched := []
this.ih.Start()
EndReason := this.ih.Wait(timeout)
inputStr .= this.ih.EndKey
for k, v in this.KeyDict[thisHotkey] {
if IsObject(v) {
if InStr(k, inputStr)
matched.Push(k)
maxLen := StrLen(k) > maxLen ? StrLen(k) : maxLen
}
}
if ((matched.MaxIndex() = 1 && this.KeyDict[thisHotkey].HasKey(inputStr))
|| !EndReason || StrLen(inputStr) >= maxLen)
break
}
this.ih.Stop()
matchConfirm := []
for i, e in matched {
if this.KeyDict[thisHotkey][e].HasKey("mods") {
for _, char in StrSplit(mods) {
if InStr(this.KeyDict[thisHotkey][inputStr].mods,char) {
matchConfirm.Push(e)
continue 2
}
}
} else if !mods {
matchConfirm.Push(e)
}
}
if ((matched.MaxIndex() = 0 && this.KeyDict[thisHotkey].HasKey(""))
|| (this.KeyDict[thisHotkey].HasKey(matchConfirm.1) && (!Endreason || matchConfirm.MaxIndex() = 1))) {
this.inputStr := SubStr(thisHotkey,2) . inputStr
funcName := this.KeyDict[thisHotkey][inputStr].funcName
if IsFunc(funcName) {
this.KeyDict[thisHotkey][inputStr].function.Call()
} else if IsLabel(funcName) {
Gosub, % funcName
} else {
Send, % "{raw}" funcName
}
} else {
this.inputStr := ""
}
Suspend, Off
}
}
; 来源:https://www.autohotkey.com/boards/viewtopic.php?f=6&t=95596 #Persistent #NoEnv #SingleInstance, force SetTitleMatchMode, RegEx SetBatchLines, -1 mk := new MultiHotkeys() ; Use hotkey command before definition to make context sensitive: ; Hotkey, IfWinActive, Notepad mk.Add("d" , "t200" , "d") ; send d if the below times out mk.Add("dd" , , "Test" , "Double hotkey") ; Calling functions mk.Add("ddd" , , "Test" , "Triple hotkey!") mk.Add("dddd" , , "Test" , "Quadruple hotkey!!") mk.Add("{F1}{F1}" , , "Test2") ; Calling a label; F1 > F1 mk.Add("^{F1}{F1}" , , "Test3") ; Sending a string; Ctrl+F1 > F1 mk.Add("+t" , , "T") ; Capital T if Shift+t times out mk.Add("+thisisatest" , "t1000", "Test" , "Hello," ,"World!") ; Sending 2 parameters ; Shift+t > hisisatest mk.Add("#{Capslock}{F2}{F3}", "t800" , "Test" , "Wow, this is a long hotkey!") ; Win+Caps > F2 > F3 return Test(param1:="",param2:="") { global mk str := mk.inputStr if param1 str .= "`r`n" param1 if param2 str .= "`r`n" param2 tooltip, % str SetTimer, Tooltipoff, -3000 return TooltipOff: tooltip return } Test2: msgbox, % A_ThisLabel "`r`n" mk.inputStr return ;--------------------------------------------------------------------------------------------------------------------------------------- ; ; Class_Multihotkeys.ahk v0.1 by evilmanimani ; ; ; Easily set up double, triple, or more hotkeys, and more for pseudo hotstrings, with a configurable timeout ; Can go functions with parameters, labels, or just send characters if it doesn't match a function/label ; If two input strings are similar i.e. (!aa, !aaa, !aaaa), it will trigger the shorter ones after the timeout ; , the longest will be triggered immediately. ; ; mh := new MultiHotkeys() to start ; ; The only public method is Add, see examples for details: ; ; - keys: string of letter keys, optionally starting with modifiers the modifier only needs to be held for the first key ; should support ~, but not really tested. ; - options: at the moment, only supports a timeout in milliseconds, this is the timeout period between each keypress ; of the full input string, entered as t400, t1000, etc; defaults to 400ms; the timeout applies to any configured ; input string that shares the same starting hotkey (the modifiers and first character) ; - function: either a function or label name, any other text not matching a function onr label will be sent as-is ; - params: if passing a Function, any amount of associated params are supported ; ; Class MultiHotkeys { __New(options:="") { ; not much for options here yet this.ih := InputHook(Options) this.KeyDict := {} } Add(keys, options:="", function :="", params*) { static optLookup := {"T":"timeout","t":"timeout"} for i, opt in StrSplit(options, A_Space) { if optLookup.HasKey(SubStr(opt,1,1)) { var := optLookup[SubStr(opt,1,1)] %var% := SubStr(opt,2) } } RegExMatch(keys, "O)^(?<mods>[~!^+#]{1,4})?(?<keys>.*)", keys) mods := StrReplace(keys.mods,"~",,noHide) keyStr := keys.keys If IsFunc(function) { if params func := Func(function).Bind(params*) else func := Func(function) } if IsObject(keyStr) { ; to-do: put in support for simple remaps via passing an array, i.e. mp.Add({"aa":"b","bb":"c","cc":"d"},,"Test") } else { hotkeyFunc := ObjBindMethod(this,"HotkeyHandler") pos := 1 loop { pos := RegExMatch(keyStr,"({.*?})|(\w)",key,pos) if (A_Index = 1) { pos += StrLen(key) firstKey := key hk := ( noHide ? "~" : "$") . mods . RegExReplace(key, "[{}]") HotKey, % hk, % hotkeyFunc } else { this.ih.KeyOpt(key, "+E+S") pos += StrLen(key) } } Until (!key) keyStr := StrReplace(keyStr, firstKey, , , 1) keyStr := RegExReplace(keyStr, "[{}]") for i, e in StrSplit(keys) { if (e = "{") this.ih.KeyOpt(e, "+E+S") } if !isObject(this.KeyDict[hk]) { this.KeyDict[hk] := {} this.KeyDict[hk].timeout := timeout ? Format("{:.1f}", timeout / 1000) : 0.4 } this.KeyDict[hk][keyStr] := {} this.KeyDict[hk][keyStr].function := func this.KeyDict[hk][keyStr].funcName := function if mods this.KeyDict[hk][keyStr].mods := mods } } HotkeyHandler() { Suspend, On thisHotkey := A_ThisHotkey Mods := RegExReplace(thisHotkey, "i)^[~\$]*([!^+#]{0,4}).*$", "$1") timeout := this.KeyDict[thisHotkey].timeout loop { matched := [] this.ih.Start() EndReason := this.ih.Wait(timeout) inputStr .= this.ih.EndKey for k, v in this.KeyDict[thisHotkey] { if IsObject(v) { if InStr(k, inputStr) matched.Push(k) maxLen := StrLen(k) > maxLen ? StrLen(k) : maxLen } } if ((matched.MaxIndex() = 1 && this.KeyDict[thisHotkey].HasKey(inputStr)) || !EndReason || StrLen(inputStr) >= maxLen) break } this.ih.Stop() matchConfirm := [] for i, e in matched { if this.KeyDict[thisHotkey][e].HasKey("mods") { for _, char in StrSplit(mods) { if InStr(this.KeyDict[thisHotkey][inputStr].mods,char) { matchConfirm.Push(e) continue 2 } } } else if !mods { matchConfirm.Push(e) } } if ((matched.MaxIndex() = 0 && this.KeyDict[thisHotkey].HasKey("")) || (this.KeyDict[thisHotkey].HasKey(matchConfirm.1) && (!Endreason || matchConfirm.MaxIndex() = 1))) { this.inputStr := SubStr(thisHotkey,2) . inputStr funcName := this.KeyDict[thisHotkey][inputStr].funcName if IsFunc(funcName) { this.KeyDict[thisHotkey][inputStr].function.Call() } else if IsLabel(funcName) { Gosub, % funcName } else { Send, % "{raw}" funcName } } else { this.inputStr := "" } Suspend, Off } }
; 来源:https://www.autohotkey.com/boards/viewtopic.php?f=6&t=95596
#Persistent
#NoEnv
#SingleInstance, force
SetTitleMatchMode, RegEx
SetBatchLines, -1
mk := new MultiHotkeys()

; Use hotkey command before definition to make context sensitive:
; Hotkey, IfWinActive, Notepad

mk.Add("d"                  , "t200" , "d")      ; send d if the below times out
mk.Add("dd"                 ,        , "Test"    , "Double hotkey") ; Calling functions
mk.Add("ddd"                ,        , "Test"    , "Triple hotkey!")
mk.Add("dddd"               ,        , "Test"    , "Quadruple hotkey!!")
mk.Add("{F1}{F1}"           ,        , "Test2")  ; Calling a label; F1 > F1
mk.Add("^{F1}{F1}"          ,        , "Test3")  ; Sending a string; Ctrl+F1 > F1
mk.Add("+t"                 ,        , "T")      ; Capital T if Shift+t times out
mk.Add("+thisisatest"       , "t1000", "Test"    , "Hello,"  ,"World!") ; Sending 2 parameters ; Shift+t > hisisatest
mk.Add("#{Capslock}{F2}{F3}", "t800" , "Test"    , "Wow, this is a long hotkey!") ; Win+Caps > F2 > F3
return

Test(param1:="",param2:="") {
    global mk
    str := mk.inputStr
    if param1
        str .= "`r`n" param1
    if param2
        str .= "`r`n" param2
    tooltip, % str
    SetTimer, Tooltipoff, -3000
    return
    TooltipOff:
    tooltip
    return
}

Test2:
msgbox, % A_ThisLabel "`r`n" mk.inputStr
return

;---------------------------------------------------------------------------------------------------------------------------------------
;
;   Class_Multihotkeys.ahk v0.1 by evilmanimani
;
;
;   Easily set up double, triple, or more hotkeys, and more for pseudo hotstrings, with a configurable timeout
;   Can go functions with parameters, labels, or just send characters if it doesn't match a function/label
;   If two input strings are similar i.e. (!aa, !aaa, !aaaa), it will trigger the shorter ones after the timeout
;   , the longest will be triggered immediately.
;
;   mh := new MultiHotkeys() to start
;   
;   The only public method is Add, see examples for details:
;   
;       - keys:        string of letter keys, optionally starting with modifiers the modifier only needs to be held for the first key
;                      should support ~, but not really tested.
;       - options:     at the moment, only supports a timeout in milliseconds, this is the timeout period between each keypress
;                      of the full input string, entered as t400, t1000, etc; defaults to 400ms; the timeout applies to any configured
;                      input string that shares the same starting hotkey (the modifiers and first character)
;       - function:    either a function or label name, any other text not matching a function onr label will be sent as-is
;       - params:      if passing a Function, any amount of associated params are supported
;
;
Class MultiHotkeys {

    __New(options:="") { ; not much for options here yet
        this.ih := InputHook(Options)
        this.KeyDict := {}
    }

    Add(keys, options:="", function :="", params*) {
        static optLookup := {"T":"timeout","t":"timeout"}
        for i, opt in StrSplit(options, A_Space) {
            if optLookup.HasKey(SubStr(opt,1,1)) {
                var := optLookup[SubStr(opt,1,1)]
                %var% := SubStr(opt,2)
            }
        }
        RegExMatch(keys, "O)^(?<mods>[~!^+#]{1,4})?(?<keys>.*)", keys)
        mods := StrReplace(keys.mods,"~",,noHide)
        keyStr := keys.keys
        If IsFunc(function) {
            if params
                func := Func(function).Bind(params*)
            else
                func := Func(function)
            
        }
        if IsObject(keyStr) {
            ; to-do: put in support for simple remaps via passing an array, i.e. mp.Add({"aa":"b","bb":"c","cc":"d"},,"Test")
        } else {
            hotkeyFunc := ObjBindMethod(this,"HotkeyHandler")
            pos := 1
            loop {
                pos := RegExMatch(keyStr,"({.*?})|(\w)",key,pos)
                if (A_Index = 1) {
                    pos += StrLen(key)
                    firstKey := key
                    hk := ( noHide ? "~" : "$") . mods . RegExReplace(key, "[{}]")
                    HotKey, % hk, % hotkeyFunc
                } else {
                    this.ih.KeyOpt(key, "+E+S")
                    pos += StrLen(key)
                }
            } Until (!key)
            
            keyStr := StrReplace(keyStr, firstKey, , , 1)
            keyStr := RegExReplace(keyStr, "[{}]")
            for i, e in StrSplit(keys) {
                if (e = "{")
                this.ih.KeyOpt(e, "+E+S")
            }
            if !isObject(this.KeyDict[hk]) {
                this.KeyDict[hk] := {}
                this.KeyDict[hk].timeout := timeout ? Format("{:.1f}", timeout / 1000) : 0.4
            }
            this.KeyDict[hk][keyStr] := {}
            this.KeyDict[hk][keyStr].function := func
            this.KeyDict[hk][keyStr].funcName := function
            if mods
                this.KeyDict[hk][keyStr].mods := mods
        }
    }

    HotkeyHandler() {
        Suspend, On
        thisHotkey := A_ThisHotkey
        Mods := RegExReplace(thisHotkey, "i)^[~\$]*([!^+#]{0,4}).*$", "$1")
        timeout := this.KeyDict[thisHotkey].timeout
        loop {
            matched := []
            this.ih.Start()
            EndReason := this.ih.Wait(timeout)
            inputStr .= this.ih.EndKey
            for k, v in this.KeyDict[thisHotkey] {
                if IsObject(v) {
                    if InStr(k, inputStr)
                        matched.Push(k)
                    maxLen := StrLen(k) > maxLen ? StrLen(k) : maxLen
                }
            }
            if ((matched.MaxIndex() = 1 && this.KeyDict[thisHotkey].HasKey(inputStr))
            || !EndReason || StrLen(inputStr) >= maxLen)
                break
        }
        this.ih.Stop()
        matchConfirm := []
        for i, e in matched {
            if this.KeyDict[thisHotkey][e].HasKey("mods") {
                for _, char in StrSplit(mods) {
                    if InStr(this.KeyDict[thisHotkey][inputStr].mods,char) {
                        matchConfirm.Push(e)
                        continue 2
                    }
                }
            } else if !mods {
                matchConfirm.Push(e)
            }
        }
        if ((matched.MaxIndex() = 0 && this.KeyDict[thisHotkey].HasKey(""))
            || (this.KeyDict[thisHotkey].HasKey(matchConfirm.1) && (!Endreason || matchConfirm.MaxIndex() = 1))) {
            this.inputStr := SubStr(thisHotkey,2) . inputStr
            funcName := this.KeyDict[thisHotkey][inputStr].funcName
            if IsFunc(funcName) {
                this.KeyDict[thisHotkey][inputStr].function.Call()
            } else if IsLabel(funcName) {
                Gosub, % funcName
            } else {
                Send, % "{raw}" funcName
            }
        } else {
            this.inputStr := ""
        }
        Suspend, Off
    }
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。