以前有过需求,两个不同程序之间发送信息,这两个程序可能是不同语言的,回想起曾一度被API支配的恐惧。
CopyDataStruct的构造是
typedef struct tagCOPYDATASTRUCT { ULONG_PTR dwData;//自定义的数据 DWORD cbData;//数据长度 PVOID lpData;//存放通信数据的内存的地址 } COPYDATASTRUCT, *PCOPYDATASTRUCT;
转成AHK能用的内存区域,以U32版本为例,A_PtrSize=32,简单的说,就是三个部分
- 随便是啥 (占32位)
- 字符串的byte数 (占32位)
- 字符串的地址,也叫指针 (占32位)
来看官方例子
Send_WM_COPYDATA(ByRef StringToSend, ByRef TargetScriptTitle) ; 在这种情况中使用 ByRef 能节约一些内存. ; 此函数发送指定的字符串到指定的窗口然后返回收到的回复. ; 如果目标窗口处理了消息则回复为 1, 而消息被忽略了则为 0. { VarSetCapacity(CopyDataStruct, 3*A_PtrSize, 0); 分配结构的内存区域. ; 首先设置结构的 cbData 成员为字符串的大小, 包括它的零终止符: SizeInBytes := (StrLen(StringToSend) + 1) * (A_IsUnicode ? 2 : 1) NumPut(SizeInBytes, CopyDataStruct, A_PtrSize) ; 操作系统要求这个需要完成. NumPut(&StringToSend, CopyDataStruct, 2*A_PtrSize) ; 设置 lpData 为到字符串自身的指针. SendMessage, 0x4a, 0, &CopyDataStruct,, %TargetScriptTitle% ; 0x4a 为 WM_COPYDATA. return ErrorLevel ; 返回 SendMessage 的回复给我们的调用者. }
先分配1.2.3.三个部分的空间
再求出 2.字符串的byte数,需要注意的是
NumPut(SizeInBytes, CopyDataStruct, A_PtrSize) ; 操作系统要求这个需要完成.
这个注释有点问题,其实就是写入 2.字符串的byte数
然后写入3.字符串的地址
CopyDataStruct整体构造完成
最后发送
WM_COPYDATA=0x4a, W=0, L=CopyDataStruct的地址, , 接受窗口
然后再看接受函数
Receive_WM_COPYDATA(wParam, lParam) { StringAddress := NumGet(lParam + 2*A_PtrSize) ; 获取 CopyDataStruct 的 lpData 成员. CopyOfData := StrGet(StringAddress) ; 从结构中复制字符串. ; 比起 MsgBox, 应该用 ToolTip 显示, 这样我们可以及时返回: ToolTip %A_ScriptName%`nReceived the following string:`n%CopyOfData% return true ; 返回 1 (true) 是回复此消息的传统方式. }
先获取3.字符串的地址
再取字符串。
至于1.随便是啥,从头到尾都没用到,没用到,没用到!
&取字符串的地址,StrGet从地址取字符串,这算是一对操作!然而AHK的帮助文件根本没有细讲!
对于没有C语言基础的新手学习API的个人建议:
打印两张纸放在手边,一张是C语言的变量类型,一张是帮助文件DllCall()部分的“参数和返回值类型”,关键是位数
陌生的复杂的函数,可以复制到word里上色,减少疲劳。
也许需要一个变量类型提示or转换插件?
相关拓展:ReadProcessMemory
学习了
这种细致的解答,必须登录点赞!! 😛
厉害了!