user14766639
user14766639

Reputation:

How to send WM_COPYDATA from C++ to AutoHotKey?

Trying to SendMessage with WM_COPYDATA from a C++ application to an AutoHotkey script. I tried to follow the example found in the docs:

https://learn.microsoft.com/en-us/windows/win32/dataxchg/using-data-copy

Then I did:

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);

And in the Autohotkey script:

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%
    
}

The message is being received, but this is the output:

image

When it should be: Hello World.

I have also checked for GetLastError() after the SendMessage and it output 0.

I must be doing something wrong inside of the COPYDATASTRUCT. AutoHotkey x64.

Upvotes: 3

Views: 411

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596287

Your use of StrGet() is wrong:

  • You are not including the std::string's null terminator in the sent data, but you are not passing the value of the COPYDATASTRUCT::cbData field to StrGet(), so it is going to be looking for a null terminator that does not exist. So you need to specify the length that is in the COPYDATASTRUCT::cbData field, eg:

    StringLen := NumGet(lParam + A_PtrSize, "int");
    StringAddress := NumGet(lParam + 2*A_PtrSize);
    Data := StrGet(StringAddress, StringLen, Encoding);
    
  • More importantly, you are not specifying an Encoding for StrGet(), so it is going to interpret the raw data in whatever the native encoding of the script is (see A_IsUnicode). Don't do that. Be explicit about the encoding used by the C++ code. If the std::string holds a UTF-8 string, specify "UTF-8". If the std::string holds a string in the user's default ANSI locale, specify "CP0". And so on. What you are seeing happen is commonly known as Mojibake, which happens when single-byte character data is mis-interpreted in the wrong encoding.

Upvotes: 2

Related Questions