How to get keyboard scan code in java?

I would like to write an application in which key bindings are specific to the location of the key on the keyboard, not the character they are mapped to. For example, the key that is between t and u on an American keyboard must perform a specific function regardless of whether it is Y, as it is in the US, or Z, as in Germany.

I think the way to do this is to get the actual scan code given by the keyboard for the OS to represent the key pressed. How can i do this in java?

Or is there another way to achieve the same functionality?

+2


source to share


2 answers


As MadProgrammer said: you have to use JNA or JNI. You can also check out these projects:

JIntellitype is a Java API for interacting with Microsoft Intellitype commands as well as registering global hotkeys in your Java expression. The API is a Java JNI library that uses a C ++ DLL to do all the communication with Windows.

There are similar projects Linux and the Mac OS the X .




JNativeHook is a library for providing global keyboard and mouse listeners for Java. This will allow you to listen to global shortcuts or mouse movement that would otherwise not be possible using pure Java. To accomplish this task, JNativeHook uses platform-specific platform-dependent code through its native Java interface to create a low-level system intercepts and passes these events to your application.


Windows only capable of Win 7/8 (32 & 64 bit)


+2


source


Excerpt from Oracle KeyEvent source code:

//set from native code.
private transient long rawCode = 0;
private transient long primaryLevelUnicode = 0;
private transient long scancode = 0; // for MS Windows only
private transient long extendedKeyCode = 0;

      

I first thought about parsing the return value of KeyEvent toString () because it contains scancode. But then I wrote a utility method (tried it successfully on Windows 8.) that uses reflection :

final public static Integer getScancodeFromKeyEvent(final KeyEvent keyEvent) {

    Integer ret;
    Field field;

    try {
        field = KeyEvent.class.getDeclaredField("scancode");
    } catch (NoSuchFieldException nsfe) {
        System.err.println("ATTENTION! The KeyEvent object does not have a field named \"scancode\"! (Which is kinda weird.)");
        nsfe.printStackTrace();
        return null;
    }

    try {
        field.setAccessible(true);
    } catch (SecurityException se) {
        System.err.println("ATTENTION! Changing the accessibility of the KeyEvent class' field \"scancode\" caused a security exception!");
        se.printStackTrace();
        return null;
    }

    try {
        ret = (int) field.getLong(keyEvent);
    } catch (IllegalAccessException iae) {
        System.err.println("ATTENTION! It is not allowed to read the field \"scancode\" of the KeyEvent instance!");
        iae.printStackTrace();
        return null;
    }

    return ret;
}

      

Apparently resetting the field accessibility afterwards is not required as I got an exception when using this method when the setAccessible () line was commented out. (I changed it on the fly back and forth and recompiled in IntelliJ while the runtime was not yet. Should be the same in Eclipse.) It would be easy, however, to use the isAccessible () method first.

I needed scancode to play music on my keyboard because changing the keyboard language between QWERTZ and QWERTY was swapping notes. It's very sad that we don't have legal access to the value like a scancode. The above solution was successfully ignoring the current keyboard layout configuration.

BTW, toString returns a value for "z" and "y" with US keyboard layout:



[KEY_PRESSED,keyCode=90,keyText=Z,keyChar='z',keyLocation=KEY_LOCATION_STANDARD,rawCode=90,primaryLevelUnicode=122,scancode=44,extendedKeyCode=0x5a] on frame0]
[KEY_PRESSED,keyCode=89,keyText=Y,keyChar='y',keyLocation=KEY_LOCATION_STANDARD,rawCode=89,primaryLevelUnicode=121,scancode=21,extendedKeyCode=0x59] on frame0]

      

With DE keyboard layout:

[KEY_PRESSED,keyCode=89,keyText=Y,keyChar='y',keyLocation=KEY_LOCATION_STANDARD,rawCode=89,primaryLevelUnicode=121,scancode=44,extendedKeyCode=0x59] on frame0]
[KEY_PRESSED,keyCode=90,keyText=Z,keyChar='z',keyLocation=KEY_LOCATION_STANDARD,rawCode=90,primaryLevelUnicode=122,scancode=21,extendedKeyCode=0x5a] on frame0]

      

Pay attention to scancode.

As a bonus off topic:

[KEY_PRESSED,keyCode=10,keyText=Enter,keyChar=Enter,keyLocation=KEY_LOCATION_STANDARD,rawCode=13,primaryLevelUnicode=13,scancode=28,extendedKeyCode=0xa] on frame0]
[KEY_PRESSED,keyCode=10,keyText=Enter,keyChar=Enter,keyLocation=KEY_LOCATION_NUMPAD,rawCode=13,primaryLevelUnicode=13,scancode=28,extendedKeyCode=0xa] on frame0]
[KEY_PRESSED,keyCode=49,keyText=1,keyChar='1',keyLocation=KEY_LOCATION_STANDARD,rawCode=49,primaryLevelUnicode=49,scancode=2,extendedKeyCode=0x31] on frame0]
[KEY_PRESSED,keyCode=97,keyText=NumPad-1,keyChar='1',keyLocation=KEY_LOCATION_NUMPAD,rawCode=97,primaryLevelUnicode=49,scancode=79,extendedKeyCode=0x61] on frame0]

      

+2


source







All Articles