设为首页收藏本站

 找回密码
 立即注册

只需一步,快速开始

搜索
查看: 81|回复: 11

多线程独立按键后台发送工具 (五按键版) v5.0 附带源码!

 火.. [复制链接]
累计签到:16 天
连续签到:4 天
灌水成绩
13
25
3553
主题
帖子
积分

等级头衔

ID : 604

初级技术员

积分成就 测量币 : 3553
在线时间 : 0 小时
注册时间 : 2026-4-18
最后登录 : 2026-5-20

勋章
UID勋章测量学徒测量员
发表于 2026-4-14 19:15:19 | 显示全部楼层 |阅读模式 IP:广东东莞
### 多线程独立按键后台发送工具 (五按键版) 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边写的工具,源码带详细注释  

> 郑重承诺:

  • 100%原创无抄袭
  • 无后门无病毒永久开源免费
> 特别感谢:

  • 吾爱论坛提供的学习平台!
    >

  • 热心坛友们的技术分享!
    >
    管理员大大们的辛苦付出!
    >


遇到问题欢迎回帖交流!
觉得好用请给个免费评分鼓励~ 😘


---

完整开源代码
[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
累计签到:15 天
连续签到:1 天
灌水成绩
0
146
10244
主题
帖子
积分

等级头衔

ID : 568

高级技术员

积分成就 测量币 : 10244
在线时间 : 0 小时
注册时间 : 2025-9-24
最后登录 : 2026-5-9

勋章
UID勋章测量学徒测量员
发表于 2026-4-15 07:00:02 | 显示全部楼层 IP:美国
内容简洁高效,不浪费时间。
回复

使用道具 举报

累计签到:19 天
连续签到:13 天
灌水成绩
1
152
11781
主题
帖子
积分

等级头衔

ID : 522

高级技术员

积分成就 测量币 : 11781
在线时间 : 0 小时
注册时间 : 2026-1-16
最后登录 : 2026-5-20

勋章
UID勋章测量学徒测量员
发表于 2026-4-18 17:40:01 | 显示全部楼层 IP:美国
示例代码规范,值得学习。
回复

使用道具 举报

累计签到:19 天
连续签到:5 天
灌水成绩
1
176
14471
主题
帖子
积分

等级头衔

ID : 593

高级技术员

积分成就 测量币 : 14471
在线时间 : 0 小时
注册时间 : 2026-4-16
最后登录 : 2026-5-19

勋章
UID勋章测量学徒测量员
发表于 2026-4-30 02:09:19 | 显示全部楼层 IP:广东东莞
学到了新思路,感谢。
回复

使用道具 举报

累计签到:22 天
连续签到:6 天
灌水成绩
0
161
12887
主题
帖子
积分

等级头衔

ID : 561

高级技术员

积分成就 测量币 : 12887
在线时间 : 0 小时
注册时间 : 2026-4-10
最后登录 : 2026-5-14

勋章
UID勋章测量学徒测量员
发表于 2026-4-30 02:09:19 | 显示全部楼层 IP:广东东莞
帮助我理解了复杂概念。
回复

使用道具 举报

累计签到:15 天
连续签到:4 天
灌水成绩
0
167
14367
主题
帖子
积分

等级头衔

ID : 567

高级技术员

积分成就 测量币 : 14367
在线时间 : 0 小时
注册时间 : 2026-1-16
最后登录 : 2026-5-13

勋章
UID勋章测量学徒测量员
发表于 2026-4-30 02:09:19 | 显示全部楼层 IP:广东东莞
解决了我一直困惑的问题。
回复

使用道具 举报

累计签到:17 天
连续签到:11 天
灌水成绩
0
139
9624
主题
帖子
积分

等级头衔

ID : 551

中级技术员

积分成就 测量币 : 9624
在线时间 : 0 小时
注册时间 : 2025-12-17
最后登录 : 2026-4-3

勋章
UID勋章测量学徒测量员
发表于 2026-5-1 01:10:33 | 显示全部楼层 IP:广东东莞
很适合做笔记和复习。
回复

使用道具 举报

累计签到:11 天
连续签到:4 天
灌水成绩
2
151
11667
主题
帖子
积分

等级头衔

ID : 555

高级技术员

积分成就 测量币 : 11667
在线时间 : 0 小时
注册时间 : 2025-12-30
最后登录 : 2026-5-19

勋章
UID勋章测量学徒测量员
发表于 2026-5-1 01:19:47 | 显示全部楼层 IP:广东东莞
解决了我一直困惑的问题。
回复

使用道具 举报

累计签到:19 天
连续签到:6 天
灌水成绩
1
189
15289
主题
帖子
积分

等级头衔

ID : 547

高级技术员

积分成就 测量币 : 15289
在线时间 : 0 小时
注册时间 : 2026-2-9
最后登录 : 2026-5-15

勋章
UID勋章测量学徒测量员
发表于 2026-5-1 01:43:51 | 显示全部楼层 IP:广东东莞
适合不同水平的开发者阅读。
回复

使用道具 举报

累计签到:17 天
连续签到:11 天
灌水成绩
0
142
11630
主题
帖子
积分

等级头衔

ID : 585

高级技术员

积分成就 测量币 : 11630
在线时间 : 0 小时
注册时间 : 2026-1-19
最后登录 : 2026-5-17

勋章
UID勋章测量学徒测量员
发表于 2026-5-6 22:20:01 | 显示全部楼层 IP:香港
风格简洁明了,很喜欢。
回复

使用道具 举报

快速回复换一批
感谢楼主,好人一生平安
遇见神贴岂能不顶
顶顶顶
好贴帮顶
马克一下
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|精密测量技术论坛 ( 桂ICP备2026007449号-1 )

GMT+8, 2026-5-21 12:48 , Processed in 1.003664 second(s), 31 queries .

快速回复 返回顶部 返回列表