进程间交互操作:传递数据及相互操作。
刚重写一遍,明明以前觉得写的很好,现在再看简直渣透了。
特点:
1,模仿AHKDLL的交互方式,某些程度上可以与AHKDLL混用。补充DLL单进程的不足。
这是H版帮助里的示例:
Code: Select all
AhkThread := AhkDllThread("AutoHotkey.dll")
AhkThread.ahktextdll()
AhkThread.addScript("Sub:`nMsgbox Sub`nReturn",0) ; 追加但不执行.
AhkThread.ahkLabel("Sub")
AhkThread.ahkassign("a","test") ;写入数据到变量
使用 ahkBridge() 就可以直接当作DLL操作:
Code: Select all
AhkThread := ahkBridge()
AhkThread.ahktextdll()
AhkThread.addScript("Sub:`nMsgbox Sub`nReturn",0) ; 追加但不执行.
AhkThread.ahkLabel("Sub")
AhkThread.ahkassign("a","test") ;写入数据到变量
===============================
示例,两个不同进程的脚本:
A脚本 :
Code: Select all
ahkBridge("A",1) ;将自己写入交互标志,这样其他脚本就可以对它操作
B:=ahkBridge("B") ;读取B,前提是B已经加载并写入标志
B.ahkAssign(n,f) ;写入变量,1,目标,2,写入的数据。
B.ahkGetvar(n) ;读取变量。结果传递的是对象,如:B.ahkGetvar(["n","a","b"}) 将返回包含所有变量的对象。
B.ahkFunction(n,f*) ;调用函数返回结果,1,函数名,2,可变参数。默认等待最长5秒。如果想自定义等待时间:B.ahkFunction(n,{Time:100000,Params:[a,b,c,d]})
B.ahkPostFunction(n,f*) ;调用函数不返回结果
;子标签的调用方法就多了些
B.ahkLabel("测试") ;不等待
B.ahkLabel("测试",1) ;等待最多5秒
B.ahkLabel("测试",1110000) ;片定义等待时间
B.ahkLabel("测试",,100) ;定时器运行
B.ahkReload() ; 重启
B.Edit() ; 编辑脚本
B.ahkPause() ; 暂停
B.suspend() ; 挂起
B.ahkTerminate() ; 退出
B.ListLines() ; 显示最近运行的行
B.ListVars() ; 显示变量
B.Hotkey() ; 显示热键
B.Window() ; 显示脚本信息
B.Script() ; 显示脚本信息
B.ahkReady() ;检查是否运行
; 以及其他一些与DLL相同的函数就不写了。
Code: Select all
ahkBridge("B",1)
;.....
Code: Select all
class Bridge {
__New(s){
if s
if (s+1)
this.id:=s
else
{
u := A_TitleMatchMode, h:=A_DetectHiddenWindows
DetectHiddenWindows,On
SetTitleMatchMode 2
loop 5
{
if this.id:=WinExist("ahkBridge_" s)
break
Sleep, 30
}
DetectHiddenWindows % h
SetTitleMatchMode % u
if !this.id
Return
this.Name:=s
}
}
;========================== ===============================
;========================== ===============================
ahkAssign(n,f){
Return Bridge_send(this.id, {Name:n,Command:"Assign",Params:f})
}
ahkGetvar(n){
Return Bridge_send(this.id, {Results:1,Name:n,Command:"Getvar"})
}
ahkFunction(n,f*){
h:={Results:1,Name:n,Command:"Function"}
,f.Time ? (h.Time :=f.Time,h.Params:=f.Params):h.Params :=f
Return Bridge_send(this.id, h)
}
ahkPostFunction(n,f*){
Return Bridge_send(this.id, {Time:0,Name:n,Command:"Function",Params:f})
}
ahkLabel(n,s:=0,f:=""){ ;调用子标签。s 调用方式。省略,立即返回;1,等待最长5秒。0或其他的非空值,无限等待。 f 定时器
Return Bridge_send(this.id, {Time:f?0:s=1?5000:s,Name:n,Command:"Label",Params:f})
}
;========================== ===============================
;========================== ===============================
ahkReload(){ ; 重启
Return Bridge_Post(0x111 ,this.id,65400)
}
Edit(){ ; 编辑脚本
Bridge_Post(0x111 ,this.id,65401)
}
ahkPause(){ ; 暂停
Return Bridge_Post(0x111 ,this.id,65403)
}
suspend(){ ; 挂起
Return Bridge_Post(0x111,this.id,65404)
}
ahkTerminate(){ ; 退出
Return Bridge_Post(0x111,this.id,65405)
}
ListLines(){ ; 显示最近运行的行
Bridge_Post(0x111,this.id,65406)
}
ListVars(){ ; 显示变量
Bridge_Post(0x111,this.id,65407)
}
Hotkey(){ ; 显示热键
Bridge_Post(0x111,this.id,65408)
}
Window(){ ; 显示脚本信息
Bridge_Post(0x111,this.id,65409)
}
Script(){ ; 显示脚本信息
Bridge_Post(0x111,this.id,65410)
}
ahkReady(){ ;检查是否运行
Return (Bridge_Post(0x111,this.id) = 0)
}
;========================== ===============================
;========================== ===============================
ahkdll(n, b:="", r:=""){ ; 加载脚本
FileRead, n, % n
If (ErrorLevel = 0) and n
Return this.ahktextdll(n,b,r)
}
ahktextdll(n:="#Persistent", b:="", r:=""){ ;加载代码
if this.id
this.ahkTerminate()
h:=A_DetectHiddenWindows
DetectHiddenWindows,On
WinWait % PID:= "ahk_pid " Bridge_BinRun("`n#NoTrayIcon`nSetBatchLines -1`n" (r ? "A_ahkneme:=""" r """`nahkBridge(""" r """,1)`n" : "") n , b, r), ,4
this.id:=WinExist("ahk_class AutoHotkey ahk_pid " PID)
DetectHiddenWindows % h
Return this.id
}
; 以下函数需要H版
ahkFile(n, f:=1){
Return Bridge_send(this.id, {Results:1,Name:n,Command:"File",Params:f})
}
ahkScript(n, f:=1){
Return Bridge_send(this.id, {Results:1,Name:n,Command:"Script",Params:f})
}
ahkExec(n){
Return Bridge_send(this.id, {Results:1,Name:n,Command:"Exec"})
}
ahkExecuteLine(n, f:=0, b:=0){
Return Bridge_send(this.id, {Results:1,Name:n,Command:"ExecuteLine",mode:f,wait:b})
}
}
;========================== ===============================
;========================== ===============================
class BridgeHandle {
Function(f){
if IsFunc(n:=f.Name)
Return %n%(f.Params*)
}
Label(f){
Gosub(f.Name,f.Params?f.Params:(f.Time=0)?-1:"")
}
var(f){
Bridge_Drawer["_" f.id]:=f.Return
}
Assign(f){
global
n:=f.Name
Try
%n%:=f.Params
}
Getvar(f){
global
Try
if IsObject(b:=f.Name)
{
s:=[]
for i,n in b
s[n]:=%n%
}
else
{
s:=%b%
}
Return s
}
File(f){
Return Return h_Self.addFile(f.Name,f.Params)
}
Script(f){
Return h_Self.addScript(f.Name,f.Params)
}
ahkExec(f){
Return h_Self.ahkExec(f.Name)
}
ExecuteLine(f){
Return h_Self.ahkExecuteLine(f.Name,f.mode,f.wait)
}
}
;========================== ===============================
Bridge_Post(s, a ,e:=0 ,c:=0){
h := A_DetectHiddenWindows
DetectHiddenWindows on
PostMessage, %s%, %e%, %c% ,,ahk_id %a%
DetectHiddenWindows %h%
Return ErrorLevel
}
Bridge_BinRun(n,c:="",m:=""){
static p:=(h_scriptdir ? h_scriptdir : A_ScriptDira), a:=A_IsCompiled ? (FileExist(p "\AutoHotkey.exe") ? p "\AutoHotkey.exe" : A_ScriptFullPath) : A_AhkPath, e := A_IsCompiled ? "/E " :
Return BinRun(a,e "`n" n,c,m)
}
ahkBridge(s:="",r:=""){
if r
{
Critical
static h:=Gosub("Bridge_Ready")
h:=A_DetectHiddenWindows
DetectHiddenWindows,On
WinGetTitle, T, ahk_id %A_ScriptHwnd%
WinSetTitle, ahk_id %A_ScriptHwnd%,,% s:=(instr(T, "ahkBridge_") ? T "|" : "") "ahkBridge_" (s?s:A_ScriptName)
DetectHiddenWindows % h
}
else
{
Return new Bridge(s)
}
}
Return
Bridge_Ready:
global Bridge_mark, Bridge_Drawer ,Bridge_Parked,h_Self
if !Bridge_Drawer
h_Self ? "" : h_Self:=A_IsDll ? AhkSelf() : AhkExported(),Bridge_mark:=0, Bridge_Drawer:=[], Bridge_Parked:=[]
,onmessage(0x4a, "Bridge_Receive",50), onmessage(0x80e, "Bridge_Receive",50)
Return
ahkBridge_List(){
u := A_TitleMatchMode, h:=A_DetectHiddenWindows
DetectHiddenWindows,On
SetTitleMatchMode 2
WinGet s,List,ahkBridge_
SetTitleMatchMode % u
f:=[]
loop % s
{
WinGetTitle, r, % "ahk_id " b:=s%A_Index%
f[b]:=StrReplace(r,"ahkBridge_")
}
DetectHiddenWindows % h
Return f
}
;========================== ===============================
;========================== ===============================
Bridge_send(i, f){
static n:=1
w:=A_DetectHiddenWindows,f.Tick:=t:=A_TickCount,f.Hwnd:=A_ScriptHwnd
,VarSetCapacity(s, 3*A_PtrSize, 0),f.id:=n++,cb:= ObjDump(f,dw)
,NumPut(&dw, &s, 2*A_PtrSize,"PTR"),NumPut(cb, &s, 1*A_PtrSize,"PTR")
DetectHiddenWindows on
if (f.Time=0)
PostMessage, 0x80e,0, &s,,ahk_id %i%
else
SendMessage, 0x4a,0, &s,,ahk_id %i%,,,,% f.Time?f.Time:5000
DetectHiddenWindows %w%
if f.Results and (ErrorLevel!="FAIL")
Return Bridge_Drawer.remove("_" f.id)
}
Bridge_receive(w,l){
f := ObjLoad(NumGet(l+A_PtrSize*2,"PTR"),NumGet(l + A_PtrSize,"PTR"))
if IsFunc(BridgeHandle[f.Command])
{
r:=BridgeHandle[f.Command](f)
if f.Results and ((A_TickCount - f.Tick) < ((f.Time?f.Time:5000)-15))
Bridge_send(f.Hwnd,{Return:r, id:f.id, Command:"var"})
}
}
= = 话说调用了相当多的外部函数呢,我想都贴上来,但又觉得很麻烦。。。反正用的人应该没有。。。