2015-05-29 2 views
4

Я хочу позвонить GetRawInputDeviceInfo с моего приложения Java, используя JNA.Как я могу вызвать GetRawInputDeviceInfo с помощью JNA?

Это то, что мой Library интерфейс ЮНА выглядит следующим образом:

public static final UINT RIDI_DEVICEINFO = new UINT(0x2000000b); 

public static DWORD RIM_TYPE_KEYBOARD = new DWORD(1); 

public static class RID_DEVICE_INFO extends Structure { 
    public DWORD cbSize; 
    public DWORD dwType; 
    public RID_DEVICE_INFO_ ridDeviceInfo_; 

    @Override 
    protected List<String> getFieldOrder() { 
    return asList("cbSize", "dwType", "ridDeviceInfo_"); 
    } 
} 

public static class RID_DEVICE_INFO_ extends Structure { 
    public RID_DEVICE_INFO_MOUSE mouse; 
    public RID_DEVICE_INFO_KEYBOARD keyboard; 
    public RID_DEVICE_INFO_HID hid; 

    @Override 
    protected List<String> getFieldOrder() { 
    return asList("mouse", "keyboard", "hid"); 
    } 
} 

public static class RID_DEVICE_INFO_MOUSE extends Structure { 
    public DWORD dwId; 
    public DWORD dwNumberOfButtons; 
    public DWORD dwSampleRate; 
    public BOOL fHasHorizontalWheel; 

    @Override 
    protected List<String> getFieldOrder() { 
    return asList("dwId", "dwNumberOfButtons", "dwSampleRate", "fHasHorizontalWheel"); 
    } 
} 

public static class RID_DEVICE_INFO_KEYBOARD extends Structure { 
    public DWORD dwType; 
    public DWORD dwSubType; 
    public DWORD dwKeyboardMode; 
    public DWORD dwNumberOfFunctionKeys; 
    public DWORD dwNumberOfIndicators; 
    public DWORD dwNumberOfKeysTotal; 

    @Override 
    protected List<String> getFieldOrder() { 
    return asList("dwType", "dwSubType", "dwKeyboardMode", "dwNumberOfFunctionKeys", "dwNumberOfIndicators", "dwNumberOfKeysTotal"); 
    } 
} 

public static class RID_DEVICE_INFO_HID extends Structure { 
    public DWORD dwVendorId; 
    public DWORD dwProductId; 
    public DWORD dwVersionNumber; 
    public USHORT usUsagePage; 
    public USHORT usUsage; 

    @Override 
    protected List<String> getFieldOrder() { 
    return asList("dwVendorId", "dwProductId", "dwVersionNumber", "usUsagePage", "usUsage"); 
    } 
} 

public UINT GetRawInputDeviceInfo(HANDLE hDevice, UINT uiCommand, PointerByReference pData, IntByReference pcbSize); 

Затем я использую GetRawInputDeviceInfo вроде этого: (. Пусть hDevice является действительным HANDLE, полученный откуда-то)

UINT uiCommand = RIDI_DEVICEINFO; 
RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO(); 
deviceInfo.cbSize.setValue(deviceInfo.size()); 
PointerByReference pData = new PointerByReference(deviceInfo.getPointer()); 
IntByReference pcbSize = new IntByReference(deviceInfo.size()); 
UINT lResult = INSTANCE.GetRawInputDeviceInfo(hDevice, uiCommand, pData, pcbSize); 

Моя проблема заключается в том, что lResult равен -1, о чем сообщает документация GetRawInputDeviceInfo, указывает, что pData не был достаточно большим для информации об устройстве. Я задал pData или cbSize. Если да, то каков правильный способ определить их в этом случае?

Моя версия JNA - 4.1.0. Мое приложение работает на Java 8 на 64-разрядной версии Windows 7.

+0

Я думаю, что ваш внутренний 'RID_DEVICE_INFO_' должен быть' Union'. Также немного проще использовать 'int', а не' DWORD', особенно для 'cbSize'. – technomage

+0

Сравните размер, возвращаемый вашим вызовом, с возвратом 'Structure.size()' и значением 'sizeof (RID_DEVICE_INFO)'. – technomage

ответ

1

По крайней мере, вам необходимо изменить структуру, чтобы иметь правильное представление. В настоящее время у вас есть три отдельных поля, вместо которых вы должны иметь Union. Это сделает размер вашей структуры более крупным, чем предполагалось.

Кроме того, вы должны передать структуру непосредственно в качестве третьего аргумента (использование PointerByReference не только неверно, но и нативный код получит адрес указателя, а не адрес вашей структуры). При прямой передаче структуры JNA знает, когда нужно синхронизировать поля Java с собственной памятью.

public interface DeviceAccess extends StdCallLibrary { 
    public static class RID_DEVICE_INFO extends Structure { 
     public int cbSize; 
     public int dwType; 
     public RID_DEVICE_INFO_ ridDeviceInfo_; 

     // Ensure the active field corresponds to what is read back from native memory 
     protected void read() { 
      super.read(); 
      type = RID_DEVICE_INFO_HID.class; 
      switch(dwType) { 
      case RID_DEVICE_INFO_MOUSE: 
       type = RID_DEVICE_INFO_MOUSE.class; break; 
      case RID_DEVICE_INFO_KEYBOARD: 
       type = RID_DEVICE_INFO_KEYBOARD.class; break; 
      default: 
       break; 
      } 
      ridDeviceInfo_.setType(type); 
     } 

     @Override 
     protected List<String> getFieldOrder() { 
      return asList("cbSize", "dwType", "ridDeviceInfo_"); 
     } 
    } 

    public static class RID_DEVICE_INFO_ extends Union { 
     public RID_DEVICE_INFO_MOUSE mouse; 
     public RID_DEVICE_INFO_KEYBOARD keyboard; 
     public RID_DEVICE_INFO_HID hid; 
    } 

    public UINT GetRawInputDeviceInfo(HANDLE hDevice, UINT uiCommand, RID_DEVICE_INFO pData, IntByReference pcbSize); 
} 

Затем использовать его как это:

UINT uiCommand = RIDI_DEVICEINFO; 
RID_DEVICE_INFO deviceInfo = new RID_DEVICE_INFO(); 
// Could also just put this in the constructor 
deviceInfo.cbSize = deviceInfo.size(); 

IntByReference pcbSize = new IntByReference(deviceInfo.size()); 
UINT lResult = INSTANCE.GetRawInputDeviceInfo(hDevice, uiCommand, deviceInfo, pcbSize);