很长的帖子......
我有以下已映射到JNA的C结构。 这些结构在Windows上用于从鼠标,键盘和其他HID设备获取原始输入。 问题是我在RAWINPUT.data.keyboard(RAWKEYBAORD)结构中没有得到任何东西。我还没有用鼠标测试过。
关于RAWMOUSE结构,它在technomage之前的评论之后被修改。
但我在预期的字段中没有得到任何数据,在调试时我可以看到有数据。 我想我可能错误地映射了结构,或者在使用它们时做错了什么。 有人可以告诉我,我的映射是否正确或可以使用一些更正?
我之前用C代码编写了一个DLL,我在Java中使用JNI。 但我宁愿松开DLL并使用Java。
下面的两种方法映射如下: C代码:
UINT WINAPI GetRawInputData(
_In_ HRAWINPUT hRawInput,
_In_ UINT uiCommand,
_Out_opt_ LPVOID pData,
_Inout_ PUINT pcbSize,
_In_ UINT cbSizeHeader
);
Java代码:
int GetRawInputData(RawInputLibrary.HRAWINPUT hRawInput, int uiCommand, Memory pData, IntByReference pcbSize, int cbSizeHeader);
C代码:
BOOL WINAPI RegisterRawInputDevices(
_In_ PCRAWINPUTDEVICE pRawInputDevices,
_In_ UINT uiNumDevices,
_In_ UINT cbSize
);
Java代码
boolean RegisterRawInputDevices(RawInputLibrary.RAWINPUTDEVICE pRawInputDevices, int uiNumDevices, int cbSize);
当我转储缓冲区时,我可以看到以下按下的键的值。在内存块6中的42是键盘上按下的字母b,该值根据我按下的键而改变。这是RAWINPUT结构的转储:
RawInputLibrary$RAWINPUT(allocated@0x525ecb8 (44 bytes) (shared from allocated@0x525ecb8 (44 bytes))) {
RawInputLibrary$RAWINPUTHEADER header@0=RawInputLibrary$RAWINPUTHEADER(allocated@0x525ecb8 (16 bytes) (shared from allocated@0x525ecb8 (44 bytes) (shared from allocated@0x525ecb8 (44 bytes)))) {
int dwType@0=1
int dwSize@4=20
WinNT$HANDLE hDevice@8=native@0x3da0cb3 (com.sun.jna.platform.win32.WinNT$HANDLE@3da0cb3)
WinDef$WPARAM wParam@c=1
}
RawInputLibrary$RAWINPUT$DataUnion data@10=RawInputLibrary$RAWINPUT$DataUnion(allocated@0x525ecc8 (28 bytes) (shared from allocated@0x525ecb8 (44 bytes) (shared from allocated@0x525ecb8 (44 bytes)))) {
RawInputLibrary$RAWMOUSE mouse@0=RawInputLibrary$RAWMOUSE(auto-allocated@0x525ed48 (28 bytes)) {
short usFlags@0=0
NativeLong ulButtons@4=0
short usButtonFlags@8=0
short usButtonData@a=0
NativeLong ulRawButtons@c=0
NativeLong lLastX@10=0
NativeLong lLastY@14=0
NativeLong ulExtraInformation@18=0
}
RawInputLibrary$RAWKEYBOARD keyboard@0=RawInputLibrary$RAWKEYBOARD(auto-allocated@0x525ed70 (16 bytes)) {
short MakeCode@0=0
short Flags@2=0
short Reserved@4=0
short VKey@6=0
int Message@8=0
NativeLong ExtraInformation@c=0
}
RawInputLibrary$RAWHID hid@0=RawInputLibrary$RAWHID(auto-allocated@0x525ed88 (12 bytes)) {
int dwSizeHid@0=0
int dwCount@4=0
byte bRawData[1]@8=[B@50fe39
}
}
}
memory dump
[01000000]
[20000000]
[b30cda03]
[01000000]
[30000000]
[00004200]
[00010000]
[00000000]
[00000000]
[00000000]
[00000000]
这些是我映射的结构。这里可以看到C计数器部分(不发布它们以保持帖子更小):https://msdn.microsoft.com/en-us/library/windows/desktop/ff468899(v=vs.85).aspx
public static class HRAWINPUT extends PointerType {
public HRAWINPUT(Pointer address) {
super(address);
}
public HRAWINPUT() {
super();
}
}
public class RAWINPUT extends Structure {
public static class ByReference extends RAWINPUT implements Structure.ByReference {}
public static class ByValue extends RAWINPUT implements Structure.ByValue {}
public RawInputLibrary.RAWINPUTHEADER header;
public DataUnion data;
public static class DataUnion extends Union {
public static class ByReference extends DataUnion implements Structure.ByReference {}
public static class ByValue extends DataUnion implements Structure.ByValue {}
public RawInputLibrary.RAWMOUSE mouse;
public RawInputLibrary.RAWKEYBOARD keyboard;
public RawInputLibrary.RAWHID hid;
public DataUnion() {
super();
}
public DataUnion(RawInputLibrary.RAWMOUSE mouse) {
super();
this.mouse = mouse;
setType(RawInputLibrary.RAWMOUSE.class);
}
public DataUnion(RawInputLibrary.RAWKEYBOARD keyboard) {
super();
this.keyboard = keyboard;
setType(RawInputLibrary.RAWKEYBOARD.class);
}
public DataUnion(RawInputLibrary.RAWHID hid) {
super();
this.hid = hid;
setType(RawInputLibrary.RAWHID.class);
}
protected List<? > getFieldOrder() {
return Arrays.asList("mouse", "keyboard", "hid");
}
}
public RAWINPUT() {
super();
}
public RAWINPUT(Pointer p) {
super(p);
useMemory(p); //using this doesn't make any difference, but maybe I need to do something similar to this in the data struct ?
read();
}
public RAWINPUT(RawInputLibrary.RAWINPUTHEADER header, DataUnion data) {
super();
this.header = header;
this.data = data;
}
protected List<? > getFieldOrder() {
return Arrays.asList("header", "data");
}
}
public static class RAWINPUTHEADER extends Structure {
public static class ByReference extends RAWINPUTHEADER implements Structure.ByReference {}
public static class ByValue extends RAWINPUTHEADER implements Structure.ByValue {}
public int dwType;
public int dwSize;
public WinNT.HANDLE hDevice;
public WinDef.WPARAM wParam;
public RAWINPUTHEADER() {
super();
}
public RAWINPUTHEADER(int dwType, int dwSize, WinNT.HANDLE hDevice, WinDef.WPARAM wParam) {
super();
this.dwType = dwType;
this.dwSize = dwSize;
this.hDevice = hDevice;
this.wParam = wParam;
}
protected List<?> getFieldOrder() {
return Arrays.asList("dwType", "dwSize", "hDevice", "wParam");
}
}
public static class RAWHID extends Structure {
public static class ByReference extends RAWHID implements Structure.ByReference {}
public static class ByValue extends RAWHID implements Structure.ByValue {}
public int dwSizeHid;
public int dwCount;
public byte[] bRawData = new byte[1];
public RAWHID() {
super();
}
public RAWHID(int dwSizeHid, int dwCount, byte bRawData[]) {
super();
this.dwSizeHid = dwSizeHid;
this.dwCount = dwCount;
if ((bRawData.length != this.bRawData.length)) {
throw new IllegalArgumentException("Wrong array size !");
}
this.bRawData = bRawData;
}
protected List<? > getFieldOrder() {
return Arrays.asList("dwSizeHid", "dwCount", "bRawData");
}
}
public static class RAWKEYBOARD extends Structure {
public static class ByReference extends RAWKEYBOARD implements Structure.ByReference {}
public static class ByValue extends RAWKEYBOARD implements Structure.ByValue {}
public short MakeCode;
public short Flags;
public short Reserved;
public short VKey;
public int Message;
public NativeLong ExtraInformation;
public RAWKEYBOARD() {
super();
}
public RAWKEYBOARD(short MakeCode, short Flags, short Reserved, short VKey, int Message, NativeLong ExtraInformation) {
super();
this.MakeCode = MakeCode;
this.Flags = Flags;
this.Reserved = Reserved;
this.VKey = VKey;
this.Message = Message;
this.ExtraInformation = ExtraInformation;
}
protected List<?> getFieldOrder() {
return Arrays.asList("MakeCode", "Flags", "Reserved", "VKey", "Message", "ExtraInformation");
}
}
public static class RAWMOUSE extends Structure {
public static class ByReference extends RAWMOUSE implements Structure.ByReference {}
public static class ByValue extends RAWMOUSE implements Structure.ByValue {}
public short usFlags;
public NativeLong ulButtons;
public short usButtonFlags;
public short usButtonData;
public NativeLong ulRawButtons;
public NativeLong lLastX;
public NativeLong lLastY;
public NativeLong ulExtraInformation;
public RAWMOUSE() {
super();
}
public RAWMOUSE(short usFlags, NativeLong ulButtons, short usButtonFlags, short usButtonData, NativeLong ulRawButtons, NativeLong lLastX, NativeLong lLastY, NativeLong ulExtraInformation) {
super();
this.usFlags = usFlags;
this.ulButtons = ulButtons;
this.usButtonFlags = usButtonFlags;
this.usButtonData = usButtonData;
this.ulRawButtons = ulRawButtons;
this.lLastX = lLastX;
this.lLastY = lLastY;
this.ulExtraInformation = ulExtraInformation;
}
protected List<?> getFieldOrder() {
return Arrays.asList("usFlags", "ulButtons", "usButtonFlags", "usButtonData", "ulRawButtons", "lLastX", "lLastY", "ulExtraInformation");
}
}
下面的代码是我用来测试的代码的摘录。
private class WndProc implements User32.WindowProc {
public WndProc() {
}
@Override
public LRESULT callback(HWND hwnd, int msg, WPARAM wparam, LPARAM lparam) {
switch (msg) {
case User32.WM_CREATE: {
if (hwnd != null) {
log.debug("Registering raw input device notifications...");
RawInputLibrary.RAWINPUTDEVICE.ByReference rawInputDevice = new RawInputLibrary.RAWINPUTDEVICE.ByReference();
//create an array of the struct in memory and fill it with data, and then parse the reference to the native call
RawInputLibrary.RAWINPUTDEVICE[] pRawInputDevice = (RawInputLibrary.RAWINPUTDEVICE[]) rawInputDevice.toArray(1);
pRawInputDevice[0].dwFlags = RawInputLibrary.RIDEV_INPUTSINK; // receive system wide keystrokes
pRawInputDevice[0].usUsagePage = 1; // generic desktop controls
pRawInputDevice[0].usUsage = 6; // keyboard
pRawInputDevice[0].hwndTarget = hwnd;
// register interest in raw data input
if (!rawInputLib.RegisterRawInputDevices(rawInputDevice, 1, rawInputDevice.size())) {
rawInputRegistrationSuccess = false;
log.error("Failed to register for raw input messages");
} else {
log.debug("Done registering raw input device notifications...");
}
} else {
log.debug("window handle is not defined");
}
break;
}
case RawInputLibrary.WM_INPUT: {
log.debug("Got raw input device message...");
IntByReference dwSize = new IntByReference();
int rawInputHeaderSize = new RawInputLibrary.RAWINPUTHEADER().size();
RawInputLibrary.HRAWINPUT hRawInput = new RawInputLibrary.HRAWINPUT(lparam.toPointer());
if (rawInputLib.GetRawInputData(hRawInput, RawInputLibrary.RID_INPUT, null, dwSize, rawInputHeaderSize) < 0) {
break;
}
if (dwSize.getValue() == 0) {
break;
}
IntByReference bufferSize = new IntByReference(Math.max(dwSize.getValue(), new RawInputLibrary.RAWINPUT().size()));
Memory buffer = new Memory(bufferSize.getValue());
if (rawInputLib.GetRawInputData(hRawInput, RawInputLibrary.RID_INPUT, buffer, bufferSize, rawInputHeaderSize) == -1) {
buffer.clear();
break;
}
RawInputLibrary.RAWINPUT rawinput = new RawInputLibrary.RAWINPUT(buffer);
int event = rawinput.data.keyboard.Message;
switch(event) {
case User32.WM_KEYDOWN:
case User32.WM_SYSKEYDOWN:
log.debug("Got raw input keyboard pressed");
switch(rawinput.data.keyboard.VKey){
//Shift
case 160:
case 161:
// inform listener about shift key pressed
break;
//Ignore special characters
case 144: //Numlock
break;
default:
// inform listener about key pressed
break;
}
break;
case User32.WM_KEYUP:
case User32.WM_SYSKEYUP:
if (rawinput.data.keyboard.VKey == 160 || rawinput.data.keyboard.VKey == 161) {
// inform listener about shift key released
}
break;
default:
break;
}
break;
}
default : {
return user32Lib.DefWindowProc(hwnd, msg, wparam, lparam);
}
}
return new LRESULT(0);
}
}