如何将 WM_COPYDATA 从 C++ 发送到 AutoHotKey?

How to send WM_COPYDATA from C++ to AutoHotKey?

尝试使用 WM_COPYDATA 从 C++ 应用程序 SendMessage 到 AutoHotkey 脚本。 我尝试按照文档中的示例进行操作:

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 里面做错了什么。 AutoHotkey x64.

你对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,当单字节字符数据在错误的编码中被错误解释时会发生这种情况。