累计签到:16 天 连续签到:4 天
|
### 多线程独立按键后台发送工具 (五按键版) v5.0 附带源码!
**作者**:Mr Bean(多年吾爱老坛友)
**开发工具**:AutoHotkey v2.0
**运行平台**:Windows 7/10/11
---
各位坛友大家好!
在吾爱论坛潜水多年,最近在魔兽乌龟服摸鱼时用AHK写了这个后台按键工具,压缩包大小仅2M,特点就是给指定窗口连续发送后台按键,不干扰咱们前端牛马!现开源分享给大家!
重要提示:必须用管理员权限运行!否则后台发送会失效!



---
工具特点
- 五按键独立控制:同时控制5个按键,每个按键独立设置内容和间隔
- 真后台发送:窗口最小化也能发送(ControlSend/PostMessage模式)
- 三重发送模式:
- ControlSend:后台发送(推荐)
- PostMessage:底层消息防检测
- SendInput:前台模拟
- 智能窗口绑定:一键锁定目标窗口
- 实时状态监控:显示每个线程运行状态完全开源:代码透明无后门
---
使用说明
- 第一步:右键以管理员身份运行脚本
- 第二步:点击【选择窗口】→ 切换到目标窗口 → 确定
- 第三步:设置按键内容和间隔(建议>100ms)第四步:点击【启动】开始发送
---
高级功能
- 一键发送:独立线程,最多发送5个按键
- 保存配置:下次启动自动加载紧急熔断:一键停止所有线程
---
下载与运行
- 成品版:下载附件压缩包→解压→右键管理员运行源码版:安装AutoHotkey v2.0→保存代码为.ahk文件→右键管理员运行
---
打包版本下载
见文章结尾
---
给坛友的话
> 第一次在吾爱发原创工具,心情激动又紧张 😊
> 边学AHK边写的工具,源码带详细注释
> 郑重承诺:
> 特别感谢:
- 吾爱论坛提供的学习平台!
>
- 热心坛友们的技术分享!
>管理员大大们的辛苦付出!
>
遇到问题欢迎回帖交流!
觉得好用请给个免费评分鼓励~ 😘
---
完整开源代码
[AAuto] 纯文本查看 复制代码; ===== 多线程独立按键后台发送工具 (五按键版) =====#SingleInstance Force#MaxThreadsPerHotkey 5InstallKeybdHook()Persistent(); 管理员权限检查if !A_IsAdmin { try Run('*RunAs "' A_AhkPath '" "' A_ScriptFullPath '"') ExitApp}; === 配置 ===global Config := Map( "targetHwnd", 0, ; 目标窗口句柄 "targetTitle", "", ; 目标窗口标题 "targetClass", "", ; 目标窗口类名 "keyToSend1", "1", ; 按键1 "keyToSend2", "", ; 按键2 "keyToSend3", "", ; 按键3 "keyToSend4", "", ; 按键4 "keyToSend5", "", ; 按键5 "interval1", 500, ; 按键1发送间隔 "interval2", 1000, ; 按键2发送间隔 "interval3", 1500, ; 按键3发送间隔 "interval4", 2000, ; 按键4发送间隔 "interval5", 2500, ; 按键5发送间隔 "sendMethod", "ControlSend", ; 发送方法 "debug", true ; 启用调试模式); 按键线程状态global KeyThreads := Map( "key1", Map("running", false, "timer", 0), "key2", Map("running", false, "timer", 0), "key3", Map("running", false, "timer", 0), "key4", Map("running", false, "timer", 0), "key5", Map("running", false, "timer", 0)); === GUI 界面 - 优化版 ===CreateGUI() { global ; 主窗口 MyGui := Gui("+Resize -MinimizeBox", "多线程后台按键发送工具 v5.0 by Mr Bean") MyGui.OnEvent("Close", GuiClose) MyGui.SetFont("s9", "Segoe UI") MyGui.MarginX := 10, MyGui.MarginY := 10 ; ===== 左侧区域:窗口设置 ===== leftSection := MyGui.Add("GroupBox", "x10 y10 w300 h150 Section", "目标窗口设置") ; 窗口选择行 MyGui.Add("Text", "xs+10 ys+30 w80", "窗口句柄:") hwndEdit := MyGui.Add("Edit", "vHwndEdit w100 xs+90 ys+25", Config["targetHwnd"]) selectBtn := MyGui.Add("Button", "x+5 yp-3 w90", "选择窗口") selectBtn.OnEvent("Click", SelectWindow) ; 窗口信息 (缩小输入框) MyGui.Add("Text", "xs+10 ys+65 w80", "窗口标题:") titleEdit := MyGui.Add("Edit", "vTitleEdit w200 xs+90 ys+60", Config["targetTitle"]) MyGui.Add("Text", "xs+10 ys+95 w80", "窗口类名:") classEdit := MyGui.Add("Edit", "vClassEdit w200 xs+90 ys+90", Config["targetClass"]) ; 发送方法 MyGui.Add("Text", "xs+10 ys+125 w80", "发送方法:") methodDDL := MyGui.Add("DropDownList", "vMethodDDL w120 xs+90 ys+122 Choose1", ["ControlSend", "PostMessage", "SendInput"]) methodDDL.Text := Config["sendMethod"] ; ===== 右侧区域:按键设置 ===== rightSection := MyGui.Add("GroupBox", "x320 y10 w300 h230 Section", "按键设置") ; 按键1设置 MyGui.Add("Text", "xs+10 ys+30 w40", "按键1:") keyEdit1 := MyGui.Add("Edit", "vKeyEdit1 w40 xs+50 ys+25", Config["keyToSend1"]) MyGui.Add("Text", "xs+100 ys+30 w50", "间隔(ms):") ; 宽度增加避免换行 intervalEdit1 := MyGui.Add("Edit", "vIntervalEdit1 w50 xs+150 ys+25", Config["interval1"]) key1ToggleBtn := MyGui.Add("Button", "x+10 yp-3 w80", "启动按键1") key1ToggleBtn.OnEvent("Click", (*) => ToggleKeyThread("key1")) ; 按键2设置 MyGui.Add("Text", "xs+10 ys+70 w40", "按键2:") keyEdit2 := MyGui.Add("Edit", "vKeyEdit2 w40 xs+50 ys+65", Config["keyToSend2"]) MyGui.Add("Text", "xs+100 ys+70 w50", "间隔(ms):") intervalEdit2 := MyGui.Add("Edit", "vIntervalEdit2 w50 xs+150 ys+65", Config["interval2"]) key2ToggleBtn := MyGui.Add("Button", "x+10 yp-3 w80", "启动按键2") key2ToggleBtn.OnEvent("Click", (*) => ToggleKeyThread("key2")) ; 按键3设置 MyGui.Add("Text", "xs+10 ys+110 w40", "按键3:") keyEdit3 := MyGui.Add("Edit", "vKeyEdit3 w40 xs+50 ys+105", Config["keyToSend3"]) MyGui.Add("Text", "xs+100 ys+110 w50", "间隔(ms):") intervalEdit3 := MyGui.Add("Edit", "vIntervalEdit3 w50 xs+150 ys+105", Config["interval3"]) key3ToggleBtn := MyGui.Add("Button", "x+10 yp-3 w80", "启动按键3") key3ToggleBtn.OnEvent("Click", (*) => ToggleKeyThread("key3")) ; 按键4设置 MyGui.Add("Text", "xs+10 ys+150 w40", "按键4:") keyEdit4 := MyGui.Add("Edit", "vKeyEdit4 w40 xs+50 ys+145", Config["keyToSend4"]) MyGui.Add("Text", "xs+100 ys+150 w50", "间隔(ms):") intervalEdit4 := MyGui.Add("Edit", "vIntervalEdit4 w50 xs+150 ys+145", Config["interval4"]) key4ToggleBtn := MyGui.Add("Button", "x+10 yp-3 w80", "启动按键4") key4ToggleBtn.OnEvent("Click", (*) => ToggleKeyThread("key4")) ; 按键5设置 (独立一行,位置下移) MyGui.Add("Text", "xs+10 ys+190 w40", "按键5:") keyEdit5 := MyGui.Add("Edit", "vKeyEdit5 w40 xs+50 ys+185", Config["keyToSend5"]) MyGui.Add("Text", "xs+100 ys+190 w50", "间隔(ms):") intervalEdit5 := MyGui.Add("Edit", "vIntervalEdit5 w50 xs+150 ys+185", Config["interval5"]) key5ToggleBtn := MyGui.Add("Button", "x+10 yp-3 w80", "启动按键5") key5ToggleBtn.OnEvent("Click", (*) => ToggleKeyThread("key5")) ; ===== 底部区域:控制按钮 ===== btnSection := MyGui.Add("GroupBox", "x10 y250 w610 h80 Section", "控制面板") ; 按钮行 sendBtn := MyGui.Add("Button", "xs+10 ys+25 w90 h30", "发送一次") sendBtn.SetFont("s10") sendBtn.OnEvent("Click", SendKeyOnce) saveBtn := MyGui.Add("Button", "x+20 yp w90 h30", "保存配置") saveBtn.SetFont("s10") saveBtn.OnEvent("Click", SaveConfig) stopAllBtn := MyGui.Add("Button", "x+20 yp w100 h30", "全部停止") stopAllBtn.SetFont("s10") stopAllBtn.OnEvent("Click", StopAllThreads) ; 状态指示器 (多行显示所有线程状态) statusGroup := MyGui.Add("GroupBox", "x10 y340 w610 h100", "线程状态") statusText := MyGui.Add("Text", "x20 y360 w590 h80", "就绪 - 请选择目标窗口") ; 显示GUI MyGui.Show("w630 h450") ; 保存控件引用 global GuiControls := Map( "hwndEdit", hwndEdit, "titleEdit", titleEdit, "classEdit", classEdit, "keyEdit1", keyEdit1, "keyEdit2", keyEdit2, "keyEdit3", keyEdit3, "keyEdit4", keyEdit4, "keyEdit5", keyEdit5, "intervalEdit1", intervalEdit1, "intervalEdit2", intervalEdit2, "intervalEdit3", intervalEdit3, "intervalEdit4", intervalEdit4, "intervalEdit5", intervalEdit5, "methodDDL", methodDDL, "statusText", statusText, "key1ToggleBtn", key1ToggleBtn, "key2ToggleBtn", key2ToggleBtn, "key3ToggleBtn", key3ToggleBtn, "key4ToggleBtn", key4ToggleBtn, "key5ToggleBtn", key5ToggleBtn )}; === 窗口选择功能 ===SelectWindow(*) { global Config, GuiControls MsgBox("请切换到目标窗口,然后点击确定", "选择窗口", "Iconi T5") try { Config["targetHwnd"] := WinGetID("A") Config["targetTitle"] := WinGetTitle("A") Config["targetClass"] := WinGetClass("A") GuiControls["hwndEdit"].Value := Config["targetHwnd"] GuiControls["titleEdit"].Value := Config["targetTitle"] GuiControls["classEdit"].Value := Config["targetClass"] UpdateStatus("窗口已选择: " Config["targetTitle"]) } catch { UpdateStatus("错误: 无法获取窗口信息") }}; === 发送功能 ===SendKeyOnce(*) { global Config, GuiControls ; 从GUI获取当前设置 UpdateConfigFromGUI() ; 发送按键序列 if (Config["keyToSend1"] != "") SendKeyToWindow(Config["keyToSend1"]) if (Config["keyToSend2"] != "") SendKeyToWindow(Config["keyToSend2"]) if (Config["keyToSend3"] != "") SendKeyToWindow(Config["keyToSend3"]) if (Config["keyToSend4"] != "") SendKeyToWindow(Config["keyToSend4"]) if (Config["keyToSend5"] != "") SendKeyToWindow(Config["keyToSend5"]) UpdateStatus("按键序列发送完成!")}; === 按键线程控制 ===ToggleKeyThread(keyName) { global KeyThreads, Config, GuiControls ; 更新配置 UpdateConfigFromGUI() ; 获取按钮引用 btnRef := GuiControls[keyName . "ToggleBtn"] ; 获取线程状态 threadState := KeyThreads[keyName] if (threadState["running"]) { ; 停止线程 if (threadState["timer"] != 0 && IsObject(threadState["timer"])) { SetTimer(threadState["timer"], 0) threadState["timer"] := 0 } threadState["running"] := false btnRef.Text := "启动" . SubStr(keyName, 4) UpdateStatus() } else { ; 启动线程 threadState["running"] := true btnRef.Text := "停止" . SubStr(keyName, 4) ; 获取间隔时间 keyNum := SubStr(keyName, 4) interval := Config["interval" . keyNum] ; 创建线程 threadState["timer"] := SetTimer((*) => KeyThreadFunction(keyName), interval) UpdateStatus() }}; 按键线程函数KeyThreadFunction(keyName) { global Config, KeyThreads threadState := KeyThreads[keyName] if (!threadState["running"]) return keyNum := SubStr(keyName, 4) key := Config["keyToSend" . keyNum] if (key != "") { SendKeyToWindow(key) }}; 停止所有线程StopAllThreads(*) { global KeyThreads, GuiControls for keyName, threadState in KeyThreads { if (threadState["running"]) { if (threadState["timer"] != 0 && IsObject(threadState["timer"])) { SetTimer(threadState["timer"], 0) threadState["timer"] := 0 } threadState["running"] := false ; 更新按钮文本 btnRef := GuiControls[keyName . "ToggleBtn"] btnRef.Text := "启动" . SubStr(keyName, 4) } } UpdateStatus()}; === 发送按键功能 ===SendKeyToWindow(key) { global Config if (!Config["targetHwnd"] || !WinExist("ahk_id " Config["targetHwnd"])) { UpdateStatus("错误: 目标窗口不存在!") return false } try { switch (Config["sendMethod"]) { case "ControlSend": ControlSend key, , "ahk_id " Config["targetHwnd"] LogAction("ControlSend: " key " to " Config["targetTitle"]) return true case "PostMessage": vk := GetKeyVK(key) if (vk) { PostMessage(0x100, vk, 0, , "ahk_id " Config["targetHwnd"]) ; WM_KEYDOWN PostMessage(0x101, vk, 0xC0000001, , "ahk_id " Config["targetHwnd"]) ; WM_KEYUP LogAction("PostMessage: " key " to " Config["targetTitle"]) return true } return false case "SendInput": WinActivate "ahk_id " Config["targetHwnd"] WinWaitActive("ahk_id " Config["targetHwnd"], , 0.5) Send key LogAction("SendInput: " key " to " Config["targetTitle"]) return true } } catch as e { LogAction("错误: " e.Message) return false }}; 获取按键虚拟键码GetKeyVK(key) { static map := Map( "1", 0x31, "2", 0x32, "3", 0x33, "4", 0x34, "5", 0x35, "f", 0x46, "e", 0x45, "g", 0x47, "q", 0x51, "v", 0x56, "x", 0x58, "z", 0x5A, "c", 0x43, "r", 0x52, "t", 0x54, "h", 0x48, "a", 0x41, "s", 0x53, "d", 0x44, "w", 0x57, "Space", 0x20, "Enter", 0x0D, "Tab", 0x09, "Esc", 0x1B, "Backspace", 0x08, "Up", 0x26, "Down", 0x28, "Left", 0x25, "Right", 0x27, "F1", 0x70, "F2", 0x71, "F3", 0x72, "F4", 0x73, "F5", 0x74, "F6", 0x75, "F7", 0x76, "F8", 0x77, "F9", 0x78, "F10", 0x79, "Ctrl+C", "CtrlC", "Ctrl+V", "CtrlV", "Alt+Tab", "AltTab" ) return map.Get(key, 0)}; === 配置管理 ===UpdateConfigFromGUI() { global Config, GuiControls ; 保存当前配置 Config["targetHwnd"] := GuiControls["hwndEdit"].Value Config["targetTitle"] := GuiControls["titleEdit"].Value Config["targetClass"] := GuiControls["classEdit"].Value Config["keyToSend1"] := GuiControls["keyEdit1"].Value Config["keyToSend2"] := GuiControls["keyEdit2"].Value Config["keyToSend3"] := GuiControls["keyEdit3"].Value Config["keyToSend4"] := GuiControls["keyEdit4"].Value Config["keyToSend5"] := GuiControls["keyEdit5"].Value Config["sendMethod"] := GuiControls["methodDDL"].Text ; 处理按键间隔 Config["interval1"] := ValidateInterval(GuiControls["intervalEdit1"].Value, 1) Config["interval2"] := ValidateInterval(GuiControls["intervalEdit2"].Value, 2) Config["interval3"] := ValidateInterval(GuiControls["intervalEdit3"].Value, 3) Config["interval4"] := ValidateInterval(GuiControls["intervalEdit4"].Value, 4) Config["interval5"] := ValidateInterval(GuiControls["intervalEdit5"].Value, 5)}; 验证间隔时间ValidateInterval(value, keyNum) { try { interval := Integer(value) if (interval >= 50 && interval |
精密测量技术论坛免责声明
✈️重要声明:以上内容仅代表该作者观点,不代表本站精密测量技术论坛立场。
✅如有涉及侵权请尽快告知,我们将会在第一时间处理。作者原创内容未经允许不得转载!
📱 站长联系邮箱:1339305021@qq.com
📱 站长联系微信:dddnnbbb
|