使用SendMessage来实现两个AHK脚本进程之间的通信,基于 Windows 的 WM_COPYDATA 消息机制,用来在进程间传递字符串信息。
因为AHK没有多进程模型和管理功能,缺少对进程之间的 数据交换、资源共享、同步机制(如锁、事件、条件变量等)等功能,所以AHK更加适合开多进程做不同的任务。AHK的SendMessage通信是性价比最高的方法,底部有个最精简的通信函数模板供大家自定义通信和调用逻辑。
另一个精简但不能通信的多进程实现:多进程代替多线程函数 – 精简版
另一个可以共享变量和库调用的多进程,但执行效率不如SendMessage:共享对象的多进程库
先运行接收端.ahk,再运行发送端.ahk测试【需要互相通信就两端都创建唯一隐藏窗口】
接收端.ahk
; 先运行接收端.ahk,再运行发送端.ahk测试【需要互相通信就两端都创建唯一隐藏窗口】
Gui Gui_Label_Gui: Show, Hide, <<接收端的唯一隐藏窗口名>>
OnMessage(0x4a, "ExecReceive_WM_COPYDATA")
return
; 更多详见帮助文档:https://wyagd001.github.io/zh-cn/docs/lib/OnMessage.htm
; 接收字符串后保存在变量名为"收到的字符串",以供调用
ExecReceive_WM_COPYDATA(wParam, lParam) {
Global 收到的字符串 := StrGet(NumGet(lParam + 2*A_PtrSize))
Try Gosub ExecReturn%wParam%
Return true
}
; ExecSend的参3不带标签,就默认向主进程发送信息,接收信息后跳转到ExecReturn0【默认为"0"】
ExecReturn0:
ToolTip %收到的字符串%
Return
; ExecSend的参数3设置为2时,进入这个ExecReturn2标签
ExecReturn2:
ExitApp
Return
发送端.ahk
; 先运行接收端.ahk,再运行发送端.ahk测试【需要互相通信就两端都创建唯一隐藏窗口】
ExecSend("发送端发送的字符串 - 并延时2秒", "<<接收端的唯一隐藏窗口名>>", 0)
Sleep 2000
ExecSend("关闭接收进程的示例", "<<接收端的唯一隐藏窗口名>>", 2)
return
; 更多详见帮助文档:https://wyagd001.github.io/zh-cn/docs/lib/OnMessage.htm
ExecSend(StringToSend, Label="WinTitle", flag=0) {
VarSetCapacity(CopyDataStruct, 3*A_PtrSize, 0)
, NumPut((StrLen(StringToSend) + 1) * (A_IsUnicode ? 2 : 1), CopyDataStruct, A_PtrSize)
, NumPut(&StringToSend, CopyDataStruct, 2*A_PtrSize)
DetectHiddenWindows % ("On", DHW:=A_DetectHiddenWindows)
WinGet, NewPID, PID, %Label% ahk_class AutoHotkeyGUI
SendMessage, 0x4a, flag, &CopyDataStruct,, ahk_pid %NewPID% ahk_class AutoHotkey
DetectHiddenWindows %DHW%
Return ErrorLevel
}
精简的SendMessage兼容汉字通信函数模板.ahk
; 最精简的SendMessage汉字通信函数,方便制作自己的进程通信
Gui Show, Hide, 通信隐藏识别标题
OnMessage(0x4a, "ExecReceive_WM_COPYDATA")
Return
F1::ExecSend("发送内容可以是中文", "通信隐藏识别标题")
ExecSend(StringToSend, Title="ScriptTitle", wParam=0) {
VarSetCapacity(CopyDataStruct, 3*A_PtrSize, 0)
, NumPut((StrLen(StringToSend) + 1) * (A_IsUnicode ? 2 : 1), CopyDataStruct, A_PtrSize)
, NumPut(&StringToSend, CopyDataStruct, 2*A_PtrSize)
Return DllCall("SendMessageW", "Ptr", DllCall("FindWindowW", "Str", "AutoHotkeyGUI", "Str", Title, "Ptr"), "UInt", 0x4A, "Ptr", wParam, "Ptr", &CopyDataStruct, "Ptr")
}
; 接收字符串后保存在变量名为"收到的字符串",以供调用
ExecReceive_WM_COPYDATA(wParam, lParam) {
Global 收到的字符串 := StrGet(NumGet(lParam + 2*A_PtrSize))
MsgBox % 收到的字符串 "`n`nwParam只能接收数字:" wParam
; Gosub ExecReturn%wParam% ; 也可以做一个外部标签跳转执行你的流程
Return true
}
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。

评论(0)