Как перемещать (или делать что-либо) с помощью мыши
Я пытаюсь научиться взаимодействовать с Windows API с помощью Java и JNA (Java Native Access), но я на дорожном блоке. Я пытаюсь заставить мышь что-то сделать, поставив событие мыши на поток ввода мыши, а код работает, поскольку метод SendInput(...)
возвращает 1, предположив, что он успешно поставил в очередь событие, но при этом сама мышь ничего.
My SSCCE:
Изменить:, чтобы заполнить поле dwFlags. Я пробовал несколько комбинаций констант либо самостоятельно, либо бит - или комбинировался без успеха. Опять же, метод SendInput возвращает 1, поскольку он должен предлагать метод работы, но мышь не сдвигается:
import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinDef.*;
import com.sun.jna.platform.win32.WinUser.*;
import com.sun.jna.win32.StdCallLibrary;
public class MouseUtils {
public interface User32 extends StdCallLibrary {
public static final long MOUSEEVENTF_MOVE = 0x0001L;
public static final long MOUSEEVENTF_VIRTUALDESK = 0x4000L;
public static final long MOUSEEVENTF_ABSOLUTE = 0x8000L;
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
DWORD SendInput(DWORD dWord, INPUT[] input, int cbSize);
}
public static void main(String[] args) {
INPUT input = new INPUT();
input.type = new DWORD(INPUT.INPUT_MOUSE);
input.input.mi.dx = new LONG(500);
input.input.mi.dy = new LONG(500);
input.input.mi.mouseData = new DWORD(0);
input.input.mi.dwFlags = new DWORD(User32.MOUSEEVENTF_MOVE
| User32.MOUSEEVENTF_VIRTUALDESK | User32.MOUSEEVENTF_ABSOLUTE);
// input.input.mi.dwFlags = new DWORD(0x8000L);
input.input.mi.time = new DWORD(0);
INPUT[] inArray = {input};
int cbSize = input.size(); // mouse input struct size
DWORD nInputs = new DWORD(1); // number of inputs
DWORD result = User32.INSTANCE.SendInput(nInputs , inArray, cbSize);
System.out.println("result: " + result); // return 1 if the 1 event successfully inserted
}
}
Изменить 2:
Делаем больше чтения, и кажется, что мое понимание массивов с JNA является недостаточным, что я должен думать в терминах C-массивов, где массив просто является указателем на область смежной памяти. Еще впереди (надеюсь!).
Ответы
Ответ 1
JNA document Использование структур и союзов гласит:
Союзы, как правило, взаимозаменяемы с Structures, но требуют, чтобы вы указывали, какое из полей union активно с помощью метода setType
, прежде чем его можно правильно передать вызову функции.
Я думаю, вы пропустили часть setType
. Кроме того, при использовании MOUSEEVENTF_ABSOLUTE
, dx
и dy
указываются как координаты мыши, а не пикселей.
Следующие работы:
public interface User32 extends StdCallLibrary {
...
public static final int SM_CXSCREEN = 0x0;
public static final int SM_CYSCREEN = 0x1;
int GetSystemMetrics(int index);
}
public static void main(String[] args) {
...
input.input.setType("mi");
input.input.mi.dx = new LONG(500 * 65536 / User32.INSTANCE.GetSystemMetrics(User32.SM_CXSCREEN));
input.input.mi.dy = new LONG(500 * 65536 / User32.INSTANCE.GetSystemMetrics(User32.SM_CYSCREEN));
...
}
Ответ 2
Вызов метода toArray() в вашей структуре для получения непрерывного блока памяти.
INPUT input = new INPUT();
INPUT[] arg = (INPUT[])input.toArray(1);
В качестве альтернативы вы можете просто объявить альтернативное сопоставление методов для SendInput:
DWORD SendInput(int nInputs, INPUT pInputs, int cbSize);
Однако может быть что-то еще (разрешения, возможно? см. заметки MS в UIPI), так как ваш пример должен работать (по крайней мере, с одним элементом массива).
EDIT: ответ Union.setType() действительно правильный.
Ответ 3
input.input.mi.dwFlags = new DWORD(0);
Вы не указали ни один из входных флагов мыши, поэтому не было ввода мыши.