I would like to realize the code taken from this answer and simulate a click without simulating mouse movement inside non-java app window. I know about JNA which, in theory, should have all WinAPI functions. The latest JNA version is 5.6.0 but I didn't find something similar to MAKELPARAM.
POINT pt;
pt.x = 30; // This is your click coordinates
pt.y = 30;
HWND hWnd = WindowFromPoint(pt);
LPARAM lParam = MAKELPARAM(pt.x, pt.y);
PostMessage(hWnd, WM_RBUTTONDOWN, MK_RBUTTON, lParam);
PostMessage(hWnd, WM_RBUTTONUP, MK_RBUTTON, lParam);
Does anyone know if there is something similar in Java or JNA?
Please do not suggest Java Robot. I have tried it, but unfortunately the mouse cursor moves (disappears) by about a milliseconds from the starting position to the point where you need to click and back to the starting position.
public void performClick(int x, int y) {
Point origLoc = MouseInfo.getPointerInfo().getLocation();
robot.mouseMove(x, y);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
robot.mouseMove(origLoc.x, origLoc.y);
}
Short answer:
No, but you can easily do it yourself.
Long answer:
As you said, "JNA ... in theory, should have all WinAPI functions." What is important to recognize is that there are two components to JNA, the core functionality that allows Java to interface with native (C) code via libffi
, contained in the jna
artifact; and the user-contributed platform mappings (including many WinAPI mappings) in jna-platform
. So JNA has the ability to map anything in WinAPI but someone needs to contribute it to the project to share their work with others.
Now regarding MAKELPARAM, it is simply a macro. You can see the source code for it here:
#define MAKELPARAM(l, h) ((LPARAM)(DWORD)MAKELONG(l, h))
It calls the MAKELONG
macro with (WORD
) inputs l
and h
, casts that to a DWORD
, and further casts that to a LPARAM
.
The MAKELONG
macro is defined in Windef.h:
#define MAKELONG(a, b) ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))
JNA does have the LPARAM
type mapped, present in the WinDef
class. It takes a long
argument to the constructor.
So you must simply take two 16-bit values l
and h
, map them to the rightmost 32 bits of a long
, and send that long to the LPARAM
constructor.
So the solution you seek is:
// int args are needed for unsigned 16-bit values
public static WinDef.LPARAM makeLParam(int l, int h) {
// note the high word bitmask must include L
return new WinDef.LPARAM((l & 0xffff) | (h & 0xffffL) << 16);
}