如何将 WM_COPYDATA 从 C++ 发送到 AutoHotKey?
Posted
技术标签:
【中文标题】如何将 WM_COPYDATA 从 C++ 发送到 AutoHotKey?【英文标题】:How to send WM_COPYDATA from C++ to AutoHotKey? 【发布时间】:2021-09-04 02:32:10 【问题描述】:尝试使用 WM_COPYDATA
从 C++ 应用程序向 AutoHotkey 脚本SendMessage。
我尝试按照文档中的示例进行操作:
https://docs.microsoft.com/en-us/windows/win32/dataxchg/using-data-copy
然后我做了:
HWND htarget_window = FindWindow(NULL, L"MyGui");
std::string str = "Hello World";
COPYDATASTRUCT cds;
cds.dwData = 1;
cds.lpData = (PVOID) str.c_str();
cds.cbData = strlen((char*)cds.lpData);
auto Response = SendMessage(htarget_window, WM_COPYDATA, (WPARAM)htarget_window, (LPARAM)&cds);
在 Autohotkey 脚本中:
OnMessage(0x4a , "Receive_WM_COPYDATA")
Receive_WM_COPYDATA(wParam, lParam)
; Retrieves the CopyDataStruct's lpData member.
StringAddress := NumGet(lParam + 2*A_PtrSize)
; Copy the string out of the structure.
Data := StrGet(StringAddress)
MsgBox Received the following string: %Data%
正在接收消息,但输出如下:
什么时候应该是:Hello World
。
我还在SendMessage
之后检查了GetLastError()
,它输出0
。
我一定在COPYDATASTRUCT
内部做错了什么。
自动热键 x64。
【问题讨论】:
【参考方案1】:你对StrGet()
的使用是错误的:
您没有在发送的数据中包含std::string
的空终止符,但您没有将COPYDATASTRUCT::cbData
字段的值传递给StrGet()
,因此它将寻找一个空终止符不存在。因此,您需要指定 COPYDATASTRUCT::cbData
字段中的长度,例如:
StringLen := NumGet(lParam + A_PtrSize, "int");
StringAddress := NumGet(lParam + 2*A_PtrSize);
Data := StrGet(StringAddress, StringLen, Encoding);
更重要的是,您没有为StrGet()
指定Encoding
,因此它将以脚本的本机编码方式解释原始数据(请参阅A_IsUnicode
)。不要那样做。明确 C++ 代码使用的编码。如果 std::string
包含 UTF-8 字符串,请指定 "UTF-8"
。如果std::string
包含用户默认ANSI 语言环境中的字符串,请指定"CP0"
。等等。您所看到的情况通常称为Mojibake,当单字节字符数据被错误地解释为错误的编码时会发生这种情况。
【讨论】:
使用最新版本的x64,脚本与你的代码崩溃:AutoHotkey closed for the following exit code: 3221226525
,消息仍然是汉字,我也试过你的建议使用StringAddress := NumGet(lParam + A_PtrSize + 4)
它也崩溃了,在这种情况下甚至在 MsgBox 之前就崩溃了,当我只发送一个字符时,它确实可以正确读取它,例如 std::string str = "X";
此链接中的 4º 示例演示了在两个 AutoHotkey 脚本之间使用 WM_COPYDATA autohotkey.com/docs/commands/OnMessage.htm
@Gutth 您是否确认StringLen
正在接收正确数量的发送字符?您是否验证收到的 dwData
字段为 1?也许您正在处理与预期不同的WM_COPYDATA
消息?
现在可以使用:StringLen := NumGet(lParam + A_PtrSize, "int") StringAddress := NumGet(lParam + 2*A_PtrSize) Data := StrGet(StringAddress, StringLen, Encoding)
,您可以在答案中编辑它吗?另外,谢谢雷米的帮助! :)以上是关于如何将 WM_COPYDATA 从 C++ 发送到 AutoHotKey?的主要内容,如果未能解决你的问题,请参考以下文章
在 WPF 或控制台 C# 应用程序中接收 WM_COPYDATA 结构
使用 SendMessage WM_COPYDATA 发送双精度数组