多进程热键——快速响应随时中止 v2.1

游戏中经常需要AHK热键可以随时启动、随时中止,且不能卡顿失效。

但是由于AHK是伪多线程的,后面的热键线程会中断前面未执行完毕的热键线程,从而造成前面线程的启动热键失效(因为热键一般只允许启动一个线程,执行完毕才能再次响应此热键)。

另外热键线程循环执行到中途想立即停止也做不到,必须等循环执行到某种判断可以跳出循环才能停止,这也有些不方便。

所以可以使用多进程来启动需要循环的热键子线程,这样可以随时中止子线程,也可以随意切换其他热键线程而不会造成卡住失效。

;-----------------------------------
; 多进程热键——快速响应随时中止 v2.1  By FeiYue
;
; 1、一般的多进程热键,每次按热键都会重新启动一个进程
;    这会造成热键响应延迟,和频繁启动、退出进程。
;    这个库利用线程叠加和双进程交替重启的设计解决了上述问题
;
; 2、Go.Go("标签名或函数名", 序号可省略)  启动子进程
;    Go.Go("清理标签或为空", 序号可省略)  停止子进程
;-----------------------------------

Class Go {  ;// 类开始

init() {
  static h:=Go.init()
  #NoEnv
  #NoTrayIcon
  #SingleInstance force
  #MaxThreads 255
  if (A_Args.Length()>0)
  {
    Suspend, On
    flag:="Ahk_Sub"
    s:=RegExReplace(A_Args[1], "\s")
    this.WinKill(flag "[" s "]")
    r:=this.Menu_Go.Bind(this)
    Menu, MyMenu, Add, Run, % r
    Gui, %flag%: Add, Text, 0x80 -Wrap
    Gui, %flag%: Menu, MyMenu
    Gui, %flag%: Show, Hide, % flag "[" s "]"
    return
    Ahk_SubGuiClose:
    Critical
    WinMenuSelectItem,,, 1&
    return
  }
  else
  {
    flag:="Ahk_Main"
    this.WinKill(flag)
    Gui, %flag%: Show, Hide, % flag
    OnExit(this.WinKill.Bind(this,"Ahk_Sub"))
    Menu, Tray, Icon
  }
}

Menu_Go() {
  ControlGetText, s
  s:=Trim(s)
  if (s="Reload")
  {
    WinGetTitle, s
    this.RunAhk(RegExReplace(s,"Ahk_Sub\[|]"))
    ExitApp
  }
  if IsLabel(s)
    Gosub, %s%
  else if IsFunc(s)
    %s%()
  Loop
    Sleep, 60000
}

WinKill(flag) {
  DetectHiddenWindows, On
  WinGet, list, List, % flag " ahk_class AutoHotkeyGUI"
  Loop % list
    IfWinExist, % "ahk_id " list%A_Index%
    {
      WinGet, pid, PID
      WinClose, ahk_class AutoHotkey ahk_pid %pid%,, 3
      IfWinExist,,, Process, Close, %pid%
    }
  DetectHiddenWindows, Off
}

RunAhk(s="") {
  if (A_IsCompiled)
    Run, "%A_ScriptFullPath%" /f %s%
  else
    Run, "%A_AhkPath%" /f "%A_ScriptFullPath%" %s%
}

; 一个进程叠加超过100个线程就切换另一个进程,原进程重启
Go(LabelOrFuncName="", index=0) {
  static arr:=[]
  DetectHiddenWindows, On
  SetFormat, IntegerFast, d
  index:=Floor(index), (!arr[index] && arr[index]:=[0,0])
  , ii:=Floor(arr[index][1]), jj:=Floor(arr[index][2])
  , tt:="Ahk_Sub[" index "_" jj "]"
  if (++ii>100)
  {
    IfWinExist, % tt
    {
      ControlSetText,, Reload
      WinClose
    }
    else
      this.RunAhk(index "_" jj)
    arr[index][2]:=jj:=!jj, ii:=1
    , tt:="Ahk_Sub[" index "_" jj "]"
  }
  arr[index][1]:=ii
  IfWinNotExist, % tt
  {
    this.RunAhk(index "_" jj)
    WinWait, % tt,, 3
  }
  IfWinExist, % tt
  {
    ControlSetText,, % LabelOrFuncName
    WinClose
  }
  DetectHiddenWindows, Off
}

}  ;// 类结束



;======== 下面是使用的例子 =========



;-- 按住松开型循环

$F1::
Go.Go("aaa")
KeyWait, F1
Go.Go()
return

aaa:
i:=1
Loop
  ToolTip, % "按住松开型循环-" i++
return


;-- 两次开关型循环

F2:: (ok:=!ok) ? Go.Go("bbb") : Go.Go("ccc")

bbb:
k:=1
Loop
  ToolTip, % "两次开关型循环-" k++
return

ccc:
ToolTip
return

给TA捐赠
共{{data.count}}人
人已捐赠
应用

AHK, 一个热键组合后按一个键怎么写?

2022-4-26 23:59:24

应用

纳律单人刷证

2022-5-2 9:23:28

9 条回复 A文章作者 M管理员
  1. ahker
    ahker给您打赏了¥10
  2. 蜜獾哥
    蜜獾哥给您打赏了¥2
  3. 蜜獾哥

    不顶顶,对不起大佬!

  4. Zoey

    大佬 我想利用您这个多线程来编写实现按住一个键连发此键的功能,但是出了好多问题

  5. LazzMan

    大佬,用了你的《多进程热键——快速响应随时中止 v2.1 By FeiYue》脚本后,发现一个bug,如果运行了多线程代码后,执行 ^!Numpad3::Suspend 热键会失效,请问该怎么解决啊?

  6. qingyuan0o0

    大佬,请教关于验证码部分的一个问题,是否有calldll可以通过句柄获取验证码图片,gui中的验证码是可以读取到句柄的

  7. aahk

    https://www.autoahk.com/?p=44514

    ;– 两次开关型循环
    `:: (ok:=!ok) ? Go.Go(“bbb”) : Go.Go(“ccc”)
    bbb:
    ; ToolTip,bbb
    ; Process,Exist,TotalCMD.exe
    ; if (%ErrorLevel%=0)
    DetectHiddenWindows,On
    SetTitleMatchMode,2
    ; IfWinNotExist,Total Commander or IfWinNotExist,ahk_class TTOTAL_CMD
    IfWinNotActive,Total Commander or IfWinNotActive,ahk_class TTOTAL_CMD
    {
    ;———————————–
    ; Maye Lite 和 此脚本中的快捷键都一致相同的设置为 ` ( 即波浪键~,位于Esc键正下方,位于Tab键正上方 )
    ; 搜索根目录中含有文件夹filter-file-with-totalcmd的磁盘分区
    ; 并用 Total Commander 10.52 简体中文增强版打开找到的文件夹
    ; 一旦找到文件夹后不在寻找其他磁盘分区
    ; Total Commander的右半边窗口的当前路径保持不变,只改变左半边的窗口的当前路径
    ; 此时只需要在 Total Commander 窗口中输入 “拼音首字母” 字符串序列就可以筛选过滤当前的文件列表
    ;———————————–
    DriveGet,DriveList,List
    ; loop,Parse,CDEFGHIJKLMNOPQRSTUVWXYZ
    loop, Parse, DriveList
    {
    IfExist,%A_LoopField%:filter-file-with-totalcmd
    {
    IfExist,D:ProgTotalCMD/TotalCMD64.exe
    {
    Run,D:ProgTotalCMD/TotalCMD64.exe %A_LoopField%:filter-file-with-totalcmd
    }
    else
    {
    MsgBox,找不到文件 C:ProgTotalCMD/TotalCMD64.exe
    ExitApp
    ; return
    }
    }
    }
    }
    loop,3
    {
    WinGet, WinID, ID,Total Commander ahk_class TTOTAL_CMD
    DllCall(“SwitchToThisWindow”, “UInt”, WinID, “UInt”, 1)
    WinShow,Total Commander ahk_class TTOTAL_CMD
    WinActivate,Total Commander ahk_class TTOTAL_CMD
    WinMove,Total Commander ahk_class TTOTAL_CMD,,0,0,A_ScreenWidth,A_ScreenHeight
    WinMaximize,Total Commander ahk_class TTOTAL_CMD
    }
    return
    ccc:
    ; ToolTip,ccc
    WinMinimize,Total Commander ahk_class TTOTAL_CMD
    return

  8. gdzrh917

    感谢大佬分享!学习学习

  9. JonathanWu

    THANK YOU!

  10. Doit

    哪位大佬能写个V2版本的

  11. 这个问题已经解决了,可以重新提交一下

个人中心
购物车
优惠劵
有新私信 私信列表
搜索