工具特点
五按键独立控制:同时控制5个按键,每个按键独立设置内容和间隔
真后台发送:窗口最小化也能发送(ControlSend/PostMessage模式)
三重发送模式:
ControlSend:后台发送(推荐)
PostMessage:底层消息防检测
SendInput:前台模拟
智能窗口绑定:一键锁定目标窗口
实时状态监控:显示每个线程运行状态
完全开源:代码透明无后门

作者:Mr Bean(多年吾爱老坛友)
开发工具:AutoHotkey v2.0
运行平台:Windows 7/10/11
各位坛友大家好!
在吾爱论坛潜水多年,最近在魔兽乌龟服摸鱼时用AHK写了这个后台按键工具,压缩包大小仅2M,
特点就是给指定窗口连续发送后台按键,不干扰咱们前端牛马!现开源分享给大家!
重要提示:必须用管理员权限运行!否则后台发送会失效!
使用说明
第一步:右键以管理员身份运行脚本
第二步:点击【选择窗口】→ 切换到目标窗口 → 确定
第三步:设置按键内容和间隔(建议>100ms)
第四步:点击【启动】开始发送
---
高级功能
一键发送:独立线程,最多发送5个按键
保存配置:下次启动自动加载
紧急熔断:一键停止所有线程
---
下载与运行
成品版:下载附件压缩包→解压→右键管理员运行
源码版:安装AutoHotkey v2.0→保存代码为.ahk文件→右键管理员运行
---
下载点击上面的快捷目录即可跳转到下载地址
---
给坛友的话
> 第一次在吾爱发原创工具,心情激动又紧张
> 边学AHK边写的工具,源码带详细注释
> 郑重承诺:
100%原创无抄袭
无后门无病毒
永久开源免费
> 特别感谢:
吾爱论坛提供的学习平台!
>
热心坛友们的技术分享!
>
管理员大大们的辛苦付出!
>
遇到问题欢迎回帖交流!
觉得好用请给个免费评分鼓励~
完整开源源码
; ===== 多线程独立按键后台发送工具 (五按键版) =====
#SingleInstance Force
#MaxThreadsPerHotkey 5
InstallKeybdHook()
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 <= 5000) {
return interval
}
} catch {
; 捕获转换错误
}
; 无效值重置为默认
defaultIntervals := [500, 1000, 1500, 2000, 2500]
defaultInterval := defaultIntervals[keyNum-1]
GuiControls["intervalEdit" . keyNum].Value := defaultInterval
UpdateStatus("警告: 按键" keyNum "间隔无效,已重置为" defaultInterval "ms")
return defaultInterval
}
SaveConfig(*) {
global Config, GuiControls
; 更新配置
UpdateConfigFromGUI()
; 保存到INI文件
IniWrite(Config["targetHwnd"], "SendKeys.ini", "Config", "targetHwnd")
IniWrite(Config["targetTitle"], "SendKeys.ini", "Config", "targetTitle")
IniWrite(Config["targetClass"], "SendKeys.ini", "Config", "targetClass")
IniWrite(Config["keyToSend1"], "SendKeys.ini", "Config", "keyToSend1")
IniWrite(Config["keyToSend2"], "SendKeys.ini", "Config", "keyToSend2")
IniWrite(Config["keyToSend3"], "SendKeys.ini", "Config", "keyToSend3")
IniWrite(Config["keyToSend4"], "SendKeys.ini", "Config", "keyToSend4")
IniWrite(Config["keyToSend5"], "SendKeys.ini", "Config", "keyToSend5")
IniWrite(Config["interval1"], "SendKeys.ini", "Config", "interval1")
IniWrite(Config["interval2"], "SendKeys.ini", "Config", "interval2")
IniWrite(Config["interval3"], "SendKeys.ini", "Config", "interval3")
IniWrite(Config["interval4"], "SendKeys.ini", "Config", "interval4")
IniWrite(Config["interval5"], "SendKeys.ini", "Config", "interval5")
IniWrite(Config["sendMethod"], "SendKeys.ini", "Config", "sendMethod")
UpdateStatus("配置已保存!")
}
LoadConfig() {
global Config
; 从INI文件加载
if (FileExist("SendKeys.ini")) {
Config["targetHwnd"] := IniRead("SendKeys.ini", "Config", "targetHwnd", 0)
Config["targetTitle"] := IniRead("SendKeys.ini", "Config", "targetTitle", "")
Config["targetClass"] := IniRead("SendKeys.ini", "Config", "targetClass", "")
Config["keyToSend1"] := IniRead("SendKeys.ini", "Config", "keyToSend1", "1")
Config["keyToSend2"] := IniRead("SendKeys.ini", "Config", "keyToSend2", "")
Config["keyToSend3"] := IniRead("SendKeys.ini", "Config", "keyToSend3", "")
Config["keyToSend4"] := IniRead("SendKeys.ini", "Config", "keyToSend4", "")
Config["keyToSend5"] := IniRead("SendKeys.ini", "Config", "keyToSend5", "")
Config["interval1"] := IniRead("SendKeys.ini", "Config", "interval1", 500)
Config["interval2"] := IniRead("SendKeys.ini", "Config", "interval2", 1000)
Config["interval3"] := IniRead("SendKeys.ini", "Config", "interval3", 1500)
Config["interval4"] := IniRead("SendKeys.ini", "Config", "interval4", 2000)
Config["interval5"] := IniRead("SendKeys.ini", "Config", "interval5", 2500)
Config["sendMethod"] := IniRead("SendKeys.ini", "Config", "sendMethod", "ControlSend")
}
}
; === 实用函数 ===
UpdateStatus(message := "") {
global GuiControls, KeyThreads, Config
if (message != "") {
GuiControls["statusText"].Value := message
return
}
; 构建多线程状态信息
status := ""
status .= "按键1: " (KeyThreads["key1"]["running"] ? "运行中 (" Config["interval1"] "ms)" : "停止") "`n"
status .= "按键2: " (KeyThreads["key2"]["running"] ? "运行中 (" Config["interval2"] "ms)" : "停止") "`n"
status .= "按键3: " (KeyThreads["key3"]["running"] ? "运行中 (" Config["interval3"] "ms)" : "停止") "`n"
status .= "按键4: " (KeyThreads["key4"]["running"] ? "运行中 (" Config["interval4"] "ms)" : "停止") "`n"
status .= "按键5: " (KeyThreads["key5"]["running"] ? "运行中 (" Config["interval5"] "ms)" : "停止")
GuiControls["statusText"].Value := status
}
LogAction(message) {
global Config
if (Config["debug"]) {
FileAppend FormatTime(, "yyyy-MM-dd HH:mm:ss") " - " message "`n", "SendKeys.log"
}
}
GuiClose(*) {
; 停止所有线程
StopAllThreads()
Sleep 100
ExitApp
}
; === 启动 ===
LoadConfig()
CreateGUI()
下载地址
https://pan.baidu.com/s/1uCLC64C7Nm1PQ18JRS-nWg?pwd=mc63 提取码: mc63
https://pan.quark.cn/s/43661ec4217d
转载自
https://www.52pojie.cn/thread-2039403-1-1.html







评论抢沙发