Autohotkey - 双击组合键来运行部分 Ahk 代码

Autohotkey - 双击组合键来运行部分 Ahk 代码

有没有办法双击组合键来运行 Ahk 代码的一部分。

你可以做一个双击任何老鼠或者轻触设备。

但我喜欢做一个双击我所有的按键组合。

我正在使用 Windows 系统,我喜欢Autohotkey 语言。

这是我目前拥有的代码,我们始终欢迎好的想法。

#SingleInstance force

esc::exitapp

;[Click one Time] - <Ctrl & c> to <copy the text to Clipboard>
{Ctrl}c:: ;Part1 Code.
sendinput ^c
return

;[Double Click] - <Ctrl & (2x)c>  <copy the text to Clipboard> + <do a Doogle Search>
{Ctrl}cc:: ;Part2 Code.
sendinput ^c
sleep 150
run https://www.google.com/?q=%clipboard%
return

;[a Count of Clicks] <Ctrl & (3x)c>
{Ctrl}ccc:: ;Part3 Code.
;?
return

注意 - Hotkeystring <:*:{Ctrl}cv::> 和 Hotkey <{Ctrl}ccc::> 不起作用。

答案1

您可以在 Windows 系统上对所有按键组合进行双击或多次点击以运行 Ahk 代码的任何部分,(热键 cc::) - 如果您还想将其用于(热键字符串 :*:cv::),您可以稍微更改脚本。

使用这两个 Autohotkey 脚本您可以做到这一点。

  • 1:是否自动将所有按键组合复制到单个 Windows 注册表项。(您可以在后台运行此操作)

在屏幕上显示 Windows 注册表项的按键操作

  • 2: 然后,您可以仅使用该注册表项中的字符串值,并编写编码来执行任何操作。(注意 - 这个简单的示例脚本将在屏幕上显示您所有的键盘和鼠标移动 - 您可以通过双击 Ctrl+(2x)c 或 MultiClicks 3x 键进行测试)

HKEY_CURRENT_USER,software\GetKeypressValue,KeypressValue

DoubleClicks > if(KeypressValue="Ctrl + c, c")或者

MultiClicks > if(KeypressValue="Ctrl + c (3)")

在屏幕上显示按键

2 – 您甚至可以用其他语言编写脚本。(您只需要访问该单个注册表项。)

  • 微软 Visual Studio
  • Visual Basic
  • Turbo Pascal
  • Delphi 语言
  • C++

  • Python 语言

2——DoubleClickForAllKeystrokes.ahk

; [^ = Ctrl] [! = Alt] [+ = Shift] [# = Win]
; Press <esc> key to exit
; Press <f1> key to toggle between [Scan Pause] & [Scan] 
#SingleInstance force
Gui, +AlwaysOnTop -MaximizeBox ; 
Gui, Add, Text, center y10 h50 w300 vVar,  %KeypressValue%
Gui, Color, White
Gui, show
size=20
Gui, Font, s%size%
GuiControl, Font, var
Doloop=1

MainLanguages=us ; United States
TransLationTo=nl ; Dutch

GroupAdd, Browser, ahk_class Chrome_WidgetWin_1 ; Chrome or Iron
GroupAdd, Browser, ahk_class IEFrame            ; Internet Explorer
GroupAdd, Browser, ahk_class MozillaWindowClass ; FireFox
GroupAdd, Browser, ahk_class ApplicationFrameWindow ; Edge

While Doloop=1
{
RegRead, KeypressValue, HKEY_CURRENT_USER,software\GetKeypressValue,KeypressValue ; read KeypressValue


If not GetKeyState("Ctrl","P") and not GetKeyState("Alt","P") and not GetKeyState("LWin","P") and not GetKeyState("RWin","P")
{

;Note - All these Keystrokes will be execute after Release All the keys! 

;OneClick {Ctrl}+1x(c) - Copy Is the Default
;if (KeypressValue="Ctrl + c") ;use this for [1x=Ctrl + c][2x=Ctrl + c, c][3x=Ctrl + c (3)] [and many more]
;{
; Here you can put any Code. (Part 1)
; WriteReg_KeypressValue("OneClick - Is the Default Not Needed")
;}

;DoubleClick {Ctrl}+2x(c) - Copy + Google Search
if (KeypressValue="Ctrl + c, c") ;use this for [1x=Ctrl + c][2x=Ctrl + c, c][3x=Ctrl + c (3)] [and many more]
{
;Here you can put any Code. (Part 2)
;sendinput ^c ;Not needed comes from default. (OneClick)
WriteReg_KeypressValue("2x-Google Search")
If WinActive("ahk_group Browser")
{
sendinput ^c ;copy the selected text to clipboard memory
sleep 150
sendinput ^t ; CTRL+t make a new tab + goto address bar  - use CTRL+L for the active tab + goto address bar
sleep 150
texta = https://www.google.com/search?q=
textb = %clipboard% ;selected text
textc = &lr=lang_%MainLanguages%&hl=%MainLanguages%&num=100 ; google parameters

clipboard=%texta%%textb%%textc%
sleep 150
sendinput ^v ; paste the selected text 
sleep 250
send {enter}
clipboard=%textb%
} else {
sendinput ^c ;copy the selected text to clipboard memory
sleep 150
texta = https://www.google.com/?gfe_rd=cr&gws_rd=cr#q=
textb = %clipboard% ;selected text
textc = &lr=lang_%MainLanguages%&hl=%MainLanguages%&num=100 ; google parameters

clipboard=%texta%%textb%%textc%
run %clipboard%
clipboard=%textb%
}
}

;TripleClicks {Ctrl}+3x(c) - Copy + WikiPedia Search
if (KeypressValue="Ctrl + c (3)") ;use this for [1x=Ctrl c][2x=Ctrl c, c][3x=Ctrl c (3)] [and many more]
{
;Here you can put the Code For (Part 3)
;sendinput ^c ;Not needed comes from default. (OneClick)
WriteReg_KeypressValue("3x-Wiki Search")
If WinActive("ahk_group Browser")
{
sendinput ^c ;copy the selected text to clipboard memory
sleep 150
sendinput ^t ; CTRL+t make a new tab + goto address bar  - use CTRL+L for the active tab + goto address bar
sleep 150
texta = https://en.wikipedia.org/wiki/
textb = %clipboard% ;selected text

clipboard=%texta%%textb%
sleep 150
sendinput ^v ; paste the selected text 
sleep 250
sendinput {enter}
clipboard=%textb%
} else {
sendinput ^c ;copy the selected text to clipboard memory
sleep 150
texta = https://en.wikipedia.org/wiki/
textb = %clipboard% ;selected text

clipboard=%texta%%textb%
run %clipboard%
clipboard=%textb%
}

}

;MultiClicks {Ctrl}+4x(c) - Copy + Translate Text
if (KeypressValue="Ctrl + c (4)") ;use this for [1x=Ctrl c][2x=Ctrl c, c][3x=Ctrl c (4)] [and many more]
{
;Here you can put the Code For (Part 4)
;sendinput ^c ;Not needed comes from default. (OneClick)
WriteReg_KeypressValue("4x-TransLate Text")
If WinActive("ahk_group Browser")
{
sendinput ^c 
sleep 150
sendinput ^t ; CTRL+t this will [open a new tab] + goto adress bar
sleep 150
texta = https://translate.google.com/#auto/%TransLationTo%/
textb = %clipboard% ;selected text
clipboard=%texta%%textb%
sleep 150
sendinput ^v ; paste the selected text
sleep 150
sendinput {enter} 
clipboard=%textb%
} else {
sendinput ^c ;copy the selected text to clipboard memory
sleep 150
texta = https://translate.google.com/#auto/%TransLationTo%/
textb = %clipboard% ;selected text

clipboard=%texta%%textb%
run %clipboard%
clipboard=%textb%
}
}

} ;End GetKeyState


sleep 50
GuiControl,, var, %KeypressValue%

} ;End Loop


GuiControl,, var, "Scan Pause"
Gui, show

;-----------------------
~esc::exitapp

f1::
If Doloop=1
{
DoLoop := 0
}else{
reload
}
return

;-----------------------

WriteReg_KeypressValue(a)
{
RegWrite, REG_SZ, HKEY_CURRENT_USER,software\GetKeypressValue,KeypressValue,%a%  ;clear the KeypressValue
}

1——KeypressToREG.ahk

; For the Changelog you can look to the Bottom of the code.
; This code works with a getkeyname from a Dllcall (See Bottom Script- by Lexikos)
; KeypressToREG.ahk comes from KeypressOSD.ahk that was Created by Author RaptorX
; you can press the esc key to exit.

#SingleInstance force
#NoEnv
SetBatchLines, -1
ListLines, Off

; Settings
    global TransN                := 200      ; 0~255
    global ShowSingleKey         := True
    global ShowMouseButton       := True
    global ShowSingleModifierKey := True
    global ShowModifierKeyCount  := true
    global ShowStickyModKeyCount := false
    global DisplayTime           := 2000     ; In milliseconds
    global GuiPosition           := "Bottom" ; Top or Bottom
    global FontSize              := 50
    global GuiHeight             := 115

CreateGUI()
CreateHotkey()
pre_prefix := "" 
prefix := ""
pre_key := ""
_key := ""
key := ""
return

OnKeyPressed:
    try {
        key := GetKeyStr()
        ShowHotkey(key)
        SetTimer, HideGUI, % -1 * DisplayTime
    }
return

OnKeyUp:
return

_OnKeyUp:
    tickcount_start := A_TickCount
return


CreateGUI() {
    global

    Gui, +AlwaysOnTop -Caption +Owner +LastFound +E0x20
    Gui, Margin, 0, 0
    Gui, Color, Black
    Gui, Font, cWhite s%FontSize% bold, Arial
    Gui, Add, Text, vHotkeyText Center y20

    WinSet, Transparent, %TransN%
}

CreateHotkey() {
    Loop, 95
    {
        k := Chr(A_Index + 31)
        k := (k = " ") ? "Space" : k

        Hotkey, % "~*" k, OnKeyPressed
        Hotkey, % "~*" k " Up", _OnKeyUp
    }

    Loop, 24 ; F1-F24
    {
        Hotkey, % "~*F" A_Index, OnKeyPressed
        Hotkey, % "~*F" A_Index " Up", _OnKeyUp
    }

    Loop, 10 ; Numpad0 - Numpad9
    {
        Hotkey, % "~*Numpad" A_Index - 1, OnKeyPressed
        Hotkey, % "~*Numpad" A_Index - 1 " Up", _OnKeyUp
    }

    Otherkeys := "WheelDown|WheelUp|WheelLeft|WheelRight|XButton1|XButton2|Browser_Forward|Browser_Back|Browser_Refresh|Browser_Stop|Browser_Search|Browser_Favorites|Browser_Home|Volume_Mute|Volume_Down|Volume_Up|Media_Next|Media_Prev|Media_Stop|Media_Play_Pause|Launch_Mail|Launch_Media|Launch_App1|Launch_App2|Help|Sleep|PrintScreen|CtrlBreak|Break|AppsKey|NumpadDot|NumpadDiv|NumpadMult|NumpadAdd|NumpadSub|NumpadEnter|Tab|Enter|Esc|BackSpace"
               . "|Del|Insert|Home|End|PgUp|PgDn|Up|Down|Left|Right|ScrollLock|CapsLock|NumLock|Pause|sc145|sc146|sc046|sc123"
    Loop, parse, Otherkeys, |
    {
        Hotkey, % "~*" A_LoopField, OnKeyPressed
        Hotkey, % "~*" A_LoopField " Up", _OnKeyUp
    }

    If ShowMouseButton {
        Loop, Parse, % "LButton|MButton|RButton", |
            Hotkey, % "~*" A_LoopField, OnKeyPressed
    }

    for i, mod in ["Ctrl", "Shift", "Alt"] {
        Hotkey, % "~*" mod, OnKeyPressed
        Hotkey, % "~*" mod " Up", OnKeyUp
    }
    for i, mod in ["LWin", "RWin"]
        Hotkey, % "~*" mod, OnKeyPressed
}

ShowHotkey(HotkeyStr) {
    WinGetPos, ActWin_X, ActWin_Y, ActWin_W, ActWin_H, A
    if !ActWin_W
        throw

    text_w := (ActWin_W > A_ScreenWidth) ? A_ScreenWidth : ActWin_W

    ;remove this gui codeline if you want only to Write the Value to Windows registry
    ;GuiControl,     , HotkeyText, %HotkeyStr%
    ;GuiControl,     , HotkeyText, %HotkeyStr%

    RegWrite, REG_SZ, HKEY_CURRENT_USER,software\GetKeypressValue,KeypressValue,%HotkeyStr%
     HotkeyText :=""

    ;remove this gui codeline if you want only to Write the Value to Windows registry
    ;GuiControl, Move, HotkeyText, w%text_w% Center
    ;GuiControl, Move, HotkeyText, w%text_w% Center

    if (GuiPosition = "Top")
        gui_y := ActWin_Y
    else
        gui_y := (ActWin_Y+ActWin_H) - 115 - 50

    ;remove this gui codeline if you want only to Write the Value to Windows registry
    ;Gui, Show, NoActivate x%ActWin_X% y%gui_y% h%GuiHeight% w%text_w%
    ;Gui, Show, NoActivate x%ActWin_X% y%gui_y% h%GuiHeight% w%text_w%
}

GetKeyStr() {
    static modifiers := ["Ctrl", "Shift", "Alt", "LWin", "RWin"]
    static repeatCount := 1

    for i, mod in modifiers {
        if GetKeyState(mod)
            prefix .= mod " + "
    }

    if (!prefix && !ShowSingleKey)
        throw

    key := SubStr(A_ThisHotkey, 3)

    if (key ~= "i)^(Ctrl|Shift|Alt|LWin|RWin)$") {
        if !ShowSingleModifierKey {
            throw
        }
        key := ""
        prefix := RTrim(prefix, "+ ")

        if ShowModifierKeyCount {
            if !InStr(prefix, "+") && IsDoubleClickEx() {
                if (A_ThisHotKey != A_PriorHotKey) || ShowStickyModKeyCount {
                    if (++repeatCount > 1) {
                        prefix .= " ( * " repeatCount " )"
                    }
                } else {
                    repeatCount := 0
                }
            } else {
                repeatCount := 1
            }
        }
    } else {
        if ( StrLen(key) = 1 ) {
            key := GetKeyChar(key, "A")
        } else if ( SubStr(key, 1, 2) = "sc" ) {
            key := SpecialSC(key)
        } else if (key = "LButton") && IsDoubleClick() {
            key := "Double-Click"
        }
        _key := (key = "Double-Click") ? "LButton" : key

        static pre_prefix, pre_key, keyCount := 1
        global tickcount_start
        if (prefix && pre_prefix) && (A_TickCount-tickcount_start < 300) {
            if (prefix != pre_prefix) {
                result := pre_prefix pre_key ", " prefix key
            } else {
                keyCount := (key=pre_key) ? (keyCount+1) : 1
                key := (keyCount>2) ? (key " (" keyCount ")") : (pre_key ", " key)
            }
        } else {
            keyCount := 1
        }

        pre_prefix := prefix
        pre_key := _key

        repeatCount := 1
    }
    return result ? result : prefix . key
}

SpecialSC(sc) {
    static k := {sc046: "ScrollLock", sc145: "NumLock", sc146: "Pause", sc123: "Genius LuxeMate Scroll"}
    return k[sc]
}

; by Lexikos - https://autohotkey.com/board/topic/110808-getkeyname-for-other-languages/#entry682236
GetKeyChar(Key, WinTitle:=0) {
    thread := WinTitle=0 ? 0
        : DllCall("GetWindowThreadProcessId", "ptr", WinExist(WinTitle), "ptr", 0)
    hkl := DllCall("GetKeyboardLayout", "uint", thread, "ptr")
    vk := GetKeyVK(Key), sc := GetKeySC(Key)
    VarSetCapacity(state, 256, 0)
    VarSetCapacity(char, 4, 0)
    n := DllCall("ToUnicodeEx", "uint", vk, "uint", sc
        , "ptr", &state, "ptr", &char, "int", 2, "uint", 0, "ptr", hkl)
    return StrGet(&char, n, "utf-16")
}

IsDoubleClick(MSec = 300) {
    Return (A_ThisHotKey = A_PriorHotKey) && (A_TimeSincePriorHotkey < MSec)
}

IsDoubleClickEx(MSec = 300) {
    preHotkey := RegExReplace(A_PriorHotkey, "i) Up$")
    Return (A_ThisHotKey = preHotkey) && (A_TimeSincePriorHotkey < MSec)
}

HideGUI() {
    Gui, Hide
}

~esc::exitapp 

;---------------------------------------------
; ChangeLog : v2.22 (2017-02-25) - Now pressing the same combination keys continuously more than 2 times,
;                                  for example press Ctrl+V 3 times, will displayed as "Ctrl + v (3)"
;             v2.21 (2017-02-24) - Fixed LWin/RWin not poping up start menu
;             v2.20 (2017-02-24) - Added displaying continuous-pressed combination keys.
;                                  e.g.: With CTRL key held down, pressing K and U continuously will shown as "Ctrl + k, u"
;             v2.10 (2017-01-22) - Added ShowStickyModKeyCount option
;             v2.09 (2017-01-22) - Added ShowModifierKeyCount option
;             v2.08 (2017-01-19) - Fixed a bug
;             v2.07 (2017-01-19) - Added ShowSingleModifierKey option (default is True)
;             v2.06 (2016-11-23) - Added more keys. Thanks to SashaChernykh.
;             v2.05 (2016-10-01) - Fixed not detecting "Ctrl + ScrollLock/NumLock/Pause". Thanks to lexikos.
;             v2.04 (2016-10-01) - Added NumpadDot and AppsKey
;             v2.03 (2016-09-17) - Added displaying "Double-Click" of the left mouse button.
;             v2.02 (2016-09-16) - Added displaying mouse button, and 3 settings (ShowMouseButton, FontSize, GuiHeight)
;             v2.01 (2016-09-11) - Display non english keyboard layout characters when combine with modifer keys.
;             v2.00 (2016-09-01) - Removed the "Fade out" effect because of its buggy.
;                                - Added support for non english keyboard layout.
;                                - Added GuiPosition setting.
;             v1.00 (2013-10-11) - First release.
;--------------------------------------------

答案2

这其实不太简单,但只要努力就可以做到。

在您的示例中,对于前两部分,您在两种情况下都发送 ^c,我已经实现了与此非常接近的功能来复制 Word 中的隐藏文本。对于该用例,^c 是否在每次击键时执行并不重要,然后对于“第 2 部分”,如果第二个 ^c 在您认为的“双击时间”内执行(这是一个糟糕的命名法,因为没有人单击任何东西),那么隐藏文本也会被复制。我将其称为“双击时间”,而不是双击时间,无论如何,一个好的起始值大约是 500 毫秒。

示例 1

因此,在我的代码中,如果我按 ^c 一次,它就会复制。如果我第二次按 ^ca,在 500 毫秒内,它会复制隐藏文本(即双击)。如果我第二次按 ^ca,但距离上次按下已超过 500 毫秒,那么它只会再次复制(没有伤害,没有犯规)。

为此,您需要创建一个函数,该函数会为 ^c 热键(这是一个键阻止热键,即它没有波浪号)调用。在函数内部,使用一个静态变量来跟踪上次执行时间,然后将其与当前执行时间进行比较。根据比较结果,它会发送 ^c 或调用您想要执行的任何其他代码(或同时执行两者)。因此,这适用于上述代码的前两部分。

复制/粘贴的最佳时间

顺便说一句,您也可以在复制之前清除剪贴板,然后使用,ClipWait以尽量减少复制内容出现在剪贴板上所需的动态等待时间。这是两全其美的方法,既能实现最小延迟,又能实现最大可靠性。

示例 2

另一个可行的实现略有不同,即使用修饰键+按键(带有阻止热键定义)来调用一个函数,该函数计算在释放修饰键之前按下按键的次数。在示例 1 中,^c 会在您按下修饰键后立即执行^c。在下面的例子中,^c 不会被发送,直到你发布^c.

因此对于示例 2...

  • 如果你的按键序列是{Ctrl Down}{c down}{c up}{Ctrl Up},case 1 将执行
  • 如果你的按键序列是{Ctrl Down}{c down}{c up}{c down}{c up}{Ctrl Up},case 2 将执行
  • ...
  • 如果你的按键序列是{Ctrl Down}{c down}{c up}{c down}{c up}{c down}{c up}{c down}{c up}{c down}{c up}{Ctrl Up},case 5 将执行

在某些情况下,当我将其用于 5 个或更多选项时,我通常会显示一个工具提示或 GUI,其中包含所选选项。初始热键会触发工具提示/GUI 弹出并选择选项 1。按住 Ctrl(在此示例中)可保持 GUI 显示并且未选择选项。即,您必须完全松开热键修饰符(控制)才能完成序列(与上面的例子略有不同)。只要您按下修饰键,您就可以继续按下该键,它会增加所选的选项,然后您松开修饰键以完成选择。对于使用 GUI 的这种多按菜单,我也让它循环选项,所以如果只有 5 个选项或其他东西,那么如果您得到 6 个,它只会循环回到 1 并允许您循环选项,直到您得到您想要的那个。

对于某些情况,这种方式会更好,因为你希望通过按键来获得多个选项,而不需要它那么敏捷,因为它会等到你松开按键后才执行,而不是(示例 1)在你按下按键后立即跳转。

因此,实现此目的的一种方式如下:

首先,创建一个由热键触发的函数(例如 ^c)。该函数通过增加静态和/或全局变量(取决于您的代码设置)来跟踪按下了多少次键。

myOption := ((myOption="") || (myOption=0) || (myOption=6)) ? 1 : myOption+1         ; set comparison value to max number of options and this code will cycle through them

这里的三元运算符仅检查我们是否正在初始化(变量为空或 0)并将其设置为 1,或者我们是否已达到最大选项数 + 1,例如,在这种情况下 5+1=6 有 5 个可选选项,然后也重置为 1。否则(冒号后的值),只需将选定的选项增加 1。

第一个函数还通过异步方式调用第二个“处理程序”函数SetTimer(一次性调用,因此 SetTimer 将与某个负最小值一起使用,例如 -100)。这允许第一个函数退出,以便主线程可以继续执行,而第二个函数也继续运行。即,第二个函数可以运行,而第一个函数会针对每个符合热键定义的连续击键反复调用。如果将所有内容放入单个函数中,则执行不会在第一次完成,并且您无法通过热键定义检测连续的击键。(您仍然可以手动检测它们,但更直接的做法是仅使用预先存在的热键框架进行检测)

第二个处理函数有两个部分。第一部分只是一个循环,用于检查修饰符是否仍然有效。即

While GetKeyState("Control", "P")    ; wait for user to release modifier before continuing
    Sleep 10

一旦处理程序函数清除了 while 循环(即,一旦您松开修饰键),剩下要执行的就是您需要的任何函数代码,具体取决于选择了哪个选项。

这是使用第一个函数每次按下热键时增加的变量来选择的,即

If (myOption=1)
    function1()

Else If (myOption=2)
    function2()

...

Else If (myOption=5)
    function5()

为了使其正常工作,您还需要确保您的myOption变量范围在函数(共享或全局)之间是适当的。

逃生处理器

对于这个多选项设置,我最后要做的一件事是实现一个退出选项,以防我决定不执行任何选项。为此,我通常使用第三个函数作为退出处理程序,该函数在第一个函数中作为条件热键启用。

例如,设置一个 ^Escape 热键,如果按下 modifier+escape,则使用代码强制退出。这可以通过设置 myOption=0 并发送{modifier up}以强制退出处理程序循环,然后完成而不执行任何操作来实现。这会导致处理程序退出,除了禁用 Escape 处理程序的条件热键之外,没有其他操作。

线程,无计时器,False

最后需要注意的是,您可能需要在第一个调用函数中使用Thread, NoTimers, False,这会影响随后启动的线程,但需要允许前 15ms/1000 行代码立即被另一个热键调用中断。如果您没有这个,按键可能会出现“丢失”,或者您的工作进度可能会有所不同。

一般来说,尽管 AutoHotkey 有这么多花哨的功能,我还没有找到一种更简单的方法来使多按键宏工作,但是一旦你在一个可以调整以放入各种执行情况的框架中实现这样的东西,它就会运行得非常可靠。

相关内容