I am trying to send a String to a message-only window that I have created in java using JNA.
I am using SendMessage
to send a message. (I know that it is not recommended to use FindWindow every time I send a message, but this is just for this example here)
SendMessage(FindWindow(NULL,"jnaWnd"), WM_USER + 10, 0, (LPARAM)L"Test");
On the Java (JNA) side, I had to use this interface for a proper WindowProc implementation
Besides that, I also made my way through creating a message-only hwnd on the java side. But this is not relevant for this problem.
Anyway, this is the implementation of the interface.
@Override
public LRESULT callback(HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case 1034: { //1034 is WM_USER + 10
//These lines doesn't work.... :(
//java.lang.UnsupportedOperationException: This pointer is opaque
String s = lParam.toPointer().getString(0);
// java.lang.Error: Invalid memory access
String s = lParam.toPointer().getWideString(0);
return new LRESULT(0);
}
default:
return JNA.USER32.INSTANCE.DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
Everything works fine, and I do receive the messages. Working with Integers works fine, and conversion is also easy.
But I have no clue how to parse the String out of the LPARAM value.
JNA is very well known for converting types on the fly by using the java equivalent type in the methods.
The first problem is that I use this interface, and therefore I need to stick to the params defined in the interface.
The second problem is that I also want to work with Integer values as well, which means that I cannot just replace LPARAM lParam
with String lParam
Even tho I could try to dig deeper on the JNA side to create my own interface and such... I just wanted to ask here before I move forward on this topic.
Maybe there is a simple way to get the String value out of the LPARAM
Any tips are appreciated.
EDIT_1:
I tried to use the WM_COPYDATA method, but this still leads to an invalid memory access
exception...
This is what I have tried so far:
I defined a new struct named STRMSG
struct on both sides;
Java:
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++:
typedef struct STRMSG {
LPCSTR message;
};
And here is the new SendMessage procedure:
STRMSG msg;
msg.message = "Some message";
COPYDATASTRUCT cds;
cds.dwData = 10;
cds.cbData = sizeof(STRMSG);
cds.lpData = &msg;
SendMessage(FindWindow(NULL, L"jnaWnd"), WM_COPYDATA, 0, (LPARAM)&cds);
I also added the following case in my callback method on the java side:
case WinUser.WM_COPYDATA: {
COPYDATASTRUCT cds = new COPYDATASTRUCT(new Pointer(lParam.longValue()));
ULONG_PTR uMsg1 = cds.dwData;
Pointer lParam1 = cds.lpData;
int wParam1 = cds.cbData;
switch(uMsg1.intValue()){
case 10: {
STRMSG msg = new STRMSG(lParam1); // Error: Invalid memory access here
Logger.debug(msg.message);
}
}
return new LRESULT(0);
}
The invalid memory error happens anyway :(...