now I use the panama interface to call the MessageBoxW function and the code is garbled. The performance is as follows:
enter image description here normal
enter image description here err1
enter image description here err2
enter image description here err3
My code:
import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SymbolLookup;
import java.lang.foreign.ValueLayout;
import java.nio.charset.StandardCharsets;
public class MessageBoxWMain {
public static void main(String[] args) throws Throwable {
var linker = Linker.nativeLinker();
try (var arean = Arena.ofConfined()) {
var user32 = SymbolLookup.libraryLookup("User32", arean);
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw
var messageBoxW_MH = linker.downcallHandle(user32.find("MessageBoxW").get(), FunctionDescriptor.of(
ValueLayout.JAVA_INT, // return int
ValueLayout.ADDRESS, // HWND hWnd
ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE)), // LPCWSTR lpText
ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE)), // LPCWSTR lpCaption
ValueLayout.JAVA_INT // UINT uType
));
var NULL = MemorySegment.NULL; // HWND hWnd = NULL
// https://stackoverflow.com/questions/66072117/why-does-windows-use-utf-16le
var cs = StandardCharsets.UTF_16LE;
// LPCWSTR lpText = "Hello from Panama! 你好, the world"
var lpText = arean.allocateArray(ValueLayout.JAVA_BYTE,
"Hello from Panama! 你好, the world".getBytes(cs));
// LPCWSTR lpCaption = "Demo123 你好,世界"
var lpCaption = arean.allocateArray(ValueLayout.JAVA_BYTE, "Demo123 你好,世界".getBytes(cs));
// var lpCaption = allocateArray(arean, "Demo123 你好,世界");
var MB_OK = 0x0; // UINT uType = MB_OK
var result = (int) messageBoxW_MH.invokeExact(NULL, lpText, lpCaption, MB_OK);
System.out.println(STR."MessageBox result: \{result}");
}
}
private static MemorySegment allocateArray(Arena arena, String str) {
var bs = str.getBytes(StandardCharsets.UTF_16LE);
var ms = arena.allocate(bs.length + 1);
var i = 0;
for (; i < bs.length; i++) {
ms.set(ValueLayout.JAVA_BYTE, i, bs[i]);
}
ms.set(ValueLayout.JAVA_BYTE, i, (byte) '\0');
return ms;
}
}
I don't know why it is like this, is there something wrong with my code?
How can I make the window display only the normal one?
Thanks in advance for everyone's replies, thank you.
I tried C string terminating \0
but it still didn't work correctly.
Finally, I solved the garbled problem through @Holger's method, thank you again.
private static MemorySegment allocateArray(Arena arena, String str) {
var bs = str.getBytes(StandardCharsets.UTF_16LE);
var ms = arena.allocate(bs.length + 2);
var i = 0;
for (; i < bs.length; i++) {
ms.set(ValueLayout.JAVA_BYTE, i, bs[i]);
}
// fix: UTF_16LE double byte
ms.set(ValueLayout.JAVA_BYTE, i++, (byte) '\0');
ms.set(ValueLayout.JAVA_BYTE, i, (byte) '\0');
return ms;
}