如何在java中获取键盘扫描代码?

时间:2013-06-22 21:35:34

标签: java input keyboard

我想编写一个应用程序,其中键绑定特定于键盘上键的位置,而不是它们映射到的字符。例如,美国键盘上t和u之间的键应该执行特定的功能,无论它是美国的Y还是Z,就像它在德国一样。

我认为这样做的方法是将键盘给出的实际扫描码提供给操作系统,以表示按下的键。我怎么能在java中做到这一点?

或者是否有其他方法可以实现相同的功能?

2 个答案:

答案 0 :(得分:3)

摘自Oracle的KeyEvent源代码:

//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;

首先,我考虑解析KeyEvent的 toString()返回值,因为它包含扫描码。但后来我写了一个实用工具方法(在Windows 8上成功试用),使用反射

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;
}

显然,之后重置字段的可访问性是没有必要的,因为当setAccessible()行被注释掉时使用此方法时出现异常。 (我在运行时仍在运行时来回更改它并在IntelliJ中重新编译。在Eclipse中应该是相同的。)但是,很容易,首先使用isAccessible()方法。

我需要扫描码才能在键盘上播放音乐,因为更改QWERTZ和QWERTY之间的键盘语言会按照笔记交换音符。很遗憾,我们无法合法访问类似扫描码的值。上述解决方案成功忽略了当前的键盘布局配置。

顺便说一下,toString返回" z"的值和" y"美国键盘布局:

[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]

使用DE键盘布局:

[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]

注意扫描码。

作为奖励,偏离主题:

[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]

答案 1 :(得分:2)

正如 MadProgrammer 所说:你必须使用JNA或JNI。您还可以查看这些项目:

  

JIntellitype是一个用于与Microsoft Intellitype交互的Java API   命令以及在Java中注册Global Hotkeys   应用。 API是一个Java JNI库,它使用C ++ DLL来完成   所有与Windows的沟通。

有类似的项目LinuxMac OS X


  

JNativeHook是一个提供全局键盘和鼠标的库   Java的听众。这将允许您倾听全局快捷方式   或使用纯Java无法实现的鼠标运动。至   完成这项任务,JNativeHook利用平台相关的原生   代码通过Java的本机接口创建低级系统   挂钩并将这些事件传递给您的应用程序。


仅限Windows,能够获得Win 7/8(32位和64位)