Samples‎ > ‎WinPack Samples‎ > ‎

Raw Keyboard Input Sample

import com.jniwrapper.*;
import com.jniwrapper.win32.Handle;
import com.jniwrapper.win32.IntPtr;
import com.jniwrapper.win32.LastErrorException;
import com.jniwrapper.win32.ui.*;

import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

/**
* This example demonstrates how to implement key logging
* using <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms645536%28v=vs.85%29.aspx">Raw Input</a> Windows API.
*/
public class RawKeyboardInputSample
{
/**
* Wrapper for <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms645575%28v=vs.85%29.aspx">RAWKEYBOARD</a> structure.
*/
static class RAWKEYBOARD extends Structure {
UShortInt MakeCode = new UShortInt();
UShortInt Flags = new UShortInt();
UShortInt Reserved = new UShortInt();
UShortInt VKey = new UShortInt();
UInt Message = new UInt();
ULongInt ExtraInformation = new ULongInt();
public RAWKEYBOARD() {
init(new Parameter[] {MakeCode, Flags, Reserved, VKey, Message, ExtraInformation}, (short) 8);
}
}

/**
* Wrapper for <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms645565%28v=vs.85%29.aspx">RAWINPUTDEVICE</a> structure.
*/
static class RAWINPUTDEVICE extends Structure {
UShortInt usUsagePage = new UShortInt();
UShortInt usUsage = new UShortInt();
UInt32 dwFlags = new UInt32();
Wnd hwndTarget = new Wnd();

public RAWINPUTDEVICE() {
init(new Parameter[] {usUsagePage, usUsage, dwFlags, hwndTarget}, (short) 8);
}
}

/**
* Wrapper for <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms645571%28v=vs.85%29.aspx">RAWINPUTHEADER</a> structure.
*/
static class RAWINPUTHEADER extends Structure {
UInt32 dwType = new UInt32();
UInt32 dwSize = new UInt32();
Handle hDevice = new Handle();
IntPtr wParam = new IntPtr();

public RAWINPUTHEADER() {
init(new Parameter[] {dwType, dwSize, hDevice, wParam}, (short) 8);
}
}

/**
* Wrapper for <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms645562%28v=vs.85%29.aspx">RAWINPUT</a> structure.
*/
static class RAWINPUT extends Structure {
RAWINPUTHEADER rawinputheader = new RAWINPUTHEADER();
RAWKEYBOARD keyboard = new RAWKEYBOARD();

public RAWINPUT() {
init(new Parameter[] {rawinputheader, keyboard}, (short) 8);
}
}

/**
* <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms645590%28v=vs.85%29.aspx">WM_INPUT</a> event.
*/
public static final int WM_INPUT = 0x00FF;

public static void main(String[] args) {

// a sample frame to redirect raw messages to
JFrame mainFrame = new JFrame("Main Frame");
mainFrame.setSize(800, 600);
mainFrame.setLocationRelativeTo(null);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setVisible(true);

User32 user32 = User32.getInstance();
final Function getRawInputData = user32.getFunction("GetRawInputData");
final Function registerRawInputDevices = User32.getInstance().getFunction("RegisterRawInputDevices");

Wnd wnd = new Wnd(mainFrame);

// Substitute frame's window procedure to receive WM_INPUT events
final WindowProc windowProc = new WindowProc(wnd);
windowProc.addMessageListener(new WindowMessageListener() {
public boolean canHandle(WindowMessage message, boolean beforeWindowProc) {
return message.getMsg() == WM_INPUT;
}

public int handle(WindowMessage message) {
final int RID_INPUT = 0x10000003;

RAWINPUTHEADER rih = new RAWINPUTHEADER();
UInt32 size = new UInt32();
UInt result = new UInt();
getRawInputData.invoke(result, new Parameter[]{
new Pointer.Void(message.getLParam()),
new UInt(RID_INPUT),
new Pointer.Void(),
new Pointer(size),
new Int(rih.getLength())
});
if (result.getValue() == -1) {
return 0;
}

PrimitiveArray buffer = new PrimitiveArray(UInt8.class, (int) size.getValue());
Pointer bufferPtr = new Pointer(buffer);
getRawInputData.invoke(result, new Parameter[]{
new Pointer.Void(message.getLParam()),
new UInt(RID_INPUT),
bufferPtr,
new Pointer(size),
new Int(rih.getLength())
});

if (result.getValue() != size.getValue()) {
return 0;
}

RAWINPUT rawinput = new RAWINPUT();
Pointer rawinputPtr = new Pointer(rawinput);
bufferPtr.castTo(rawinputPtr);

RAWKEYBOARD keyboard = rawinput.keyboard;
System.out.println("Keyboard: make = " + keyboard.MakeCode + "; flags = " + keyboard.Flags + "; Reserved = " + keyboard.Reserved +
"; ExtraInformation = " + keyboard.ExtraInformation + "; Message = " + keyboard.Message + "; VKey = " + keyboard.VKey);

return 0;
}
});
windowProc.substitute();

mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
windowProc.restoreNative();
}
});


RAWINPUTDEVICE rid = new RAWINPUTDEVICE();
rid.usUsagePage.setValue(1); // generic desktop controls
rid.usUsage.setValue(6); // keyboard
rid.dwFlags.setValue(0x00000030 | 0x00000100);
rid.hwndTarget.setValue(wnd.getValue()); // use Frame's wnd (message queue) to receive events

Bool result = new Bool();
long lastErrorCode = registerRawInputDevices.invoke(result, new Pointer(rid), new UInt(1), new UInt(rid.getLength()));
if (!result.getValue()) {
throw new LastErrorException(lastErrorCode);
}
}
}