在 JNA 中使用 WM_COPYDATA 发送字符串值时为空字符串

Empty String when sending a String value using WM_COPYDATA in JNA

我正在尝试将字符串从 Java(第一个应用程序)发送到 C++(第二个应用程序,仅包含消息 window)。

所以首先,我尝试的是: 我将 this example 改编成我的代码,并在 java 端得到了这个

    STRMSG msg = new STRMSG();
    msg.message = "test";
    //msg.write(); // Idk exactly why because i thought JNA does this before every call. Works the same without

    cds = new COPYDATASTRUCT();
    cds.dwData = new ULONG_PTR(UniqueWindowMessageID);
    cds.cbData = msg.size();
    cds.lpData = msg.getPointer();
    cds.write(); // But here it is somehow needed because otherwise the message will not arrive.

    JNA.USER32.INSTANCE.SendMessage(
        msgOnlyWnd, WinUser.WM_COPYDATA,
        null,
        new LPARAM(Pointer.nativeValue(cds.getPointer()))
    );

哦,STRMSG 看起来像这样(也改编自示例):

public class STRMSG extends Structure {

    public STRMSG() {
        super();
    }

    public STRMSG(Pointer p) {
        super(p);
        read();
    }

    public String message;

    protected List<String> getFieldOrder() {
        return Arrays.asList("message");
    }
}

在 c++ 端,我只收到消息 window,我可以成功捕获 WM_COPYDATA 消息。

但不知何故,我的字符串值在这里为空:

    case WM_COPYDATA: {
        PCOPYDATASTRUCT cds = (PCOPYDATASTRUCT)lParam;
        if (cds->dwData == UniqueWindowMessageID) { // <- works 
            STRMSG* msgStruct = (STRMSG*)cds->lpData; // <- The message struct is corrupt i guess

            cout << msgStruct->message << endl; // Will just endl in the console
        }
        break;
    }

这是 C++ 端的结构:

const struct STRMSG {
    string message;
};

除了这次尝试之外,我还尝试调整我的结构,使其包含 BYTE* (byte[]) 和大小,这样我就可以使用以下字节和大小创建一个字符串:(source)

std::string s(reinterpret_cast<char const*>(inputParam), lengthParam);

但我的结构无论如何都不是它应该的样子。所以数据有点错误,我知道我在这里做错了什么。

感谢任何帮助。

编辑:我在调试时也查看了数据。我没有得到任何东西:

编辑 2:

评论 Remy 后,我的 COPYDATASTRUCT 看起来像这样:

    byte[] msg = "test".getBytes();
    cds = new COPYDATASTRUCT();
    cds.dwData = new ULONG_PTR(UniqueWindowMessageID);
    cds.cbData = msg.length;
    cds.lpData = msg // how??
    cds.write();

但是我应该如何将 cds.lpData 映射到 byte[]

好吧,基本上,在 Remy Lebeau 的帮助下(一如既往),我设法将 NativeString Class 包含在我的项目中,这使我能够获得 [= NativeString 的 15=] 并直接在我的 COPYDATASTRUCT.

中使用它

我不得不 inline 我自己的一些方法内容 NativeString Class 因为其中一些也不可见。

无论如何,这是我用来构建我的 COPYDATASTRUCT 发送部分没有改变的片段。

NativeString ns = new NativeString("Hello String", true); //true so its a wide string
cds = new COPYDATASTRUCT();
cds.dwData = new ULONG_PTR(UniqueWindowMessageID);
cds.cbData = ns.length()*2; //Without *2 the text will be only the half
cds.lpData = ns.getPointer();
cds.write();

这就是我在 C++ 端处理收到的 WM_COPYDATA 消息的方式:

case WM_COPYDATA: {
    PCOPYDATASTRUCT cds = (PCOPYDATASTRUCT)lParam;
    if (cds->dwData == UniqueWindowMessageID) {
        wchar_t* msg = (wchar_t*)cds->lpData;
        wcout << msg << endl;
    }
    break;
}

再次感谢@Remy Lebeau