使用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
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。