Как двигать (или делать что-либо с) мышью - PullRequest
10 голосов
/ 07 декабря 2011

Я пытаюсь узнать, как взаимодействовать с Windows API, используя Java и JNA (Java Native Access), но я в затруднительном положении. Я пытаюсь заставить мышь сделать что-то, поставив в очередь событие мыши в потоке ввода мыши, и код работает, так как метод SendInput(...) возвращает 1, предполагая, что он успешно поставил в очередь событие, но все же сама мышь делает ничего такого.

Мой 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, где массив - это просто указатель на область непрерывной памяти. Больше впереди (я надеюсь!).

Ответы [ 3 ]

10 голосов
/ 11 декабря 2011

Документ JNA Использование структур и союзов читает:

Объединения, как правило, взаимозаменяемы со структурами, но требуют, чтобы вы указали, какое поле объединения активно с методом 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));
    ...
}
3 голосов
/ 11 декабря 2011

Вызовите метод toArray () для вашей структуры, чтобы получить непрерывный блок памяти.

INPUT input = new INPUT();
INPUT[] arg = (INPUT[])input.toArray(1);

В качестве альтернативы, вы можете просто объявить альтернативное отображение метода для SendInput:

DWORD SendInput(int nInputs, INPUT pInputs, int cbSize);

Однако может происходить что-то еще (возможно, разрешения? См. Примечания MS по UIPI), поскольку ваш пример должен работать (по крайней мере, с одним элементом массива).

РЕДАКТИРОВАТЬ: ответ Union.setType () действительно правильный.

2 голосов
/ 07 декабря 2011
input.input.mi.dwFlags = new DWORD(0);

Вы не указали ни один из флагов ввода мыши, поэтому не было ввода мыши.

...