使用JNA(JAVA)的GetAsyncKeyState和VirtualKeys /特殊字符

Dav*_*vid 11 java api java-native-interface winapi jna

我正在进行双向私聊,这将在全屏游戏中运行.

这需要让用户在屏幕顶部键入半透明文本框,即使它没有焦点也是如此.

使用以下代码,我可以检测所有物理键,但使用虚拟键时却很困难.

SHIFT 被检测到.

2 被检测到.

然而,Shift + 2它们都被检测为单独的键(即使在我的键盘上[SHIFT+2]给出@).IE:程序输出SHIFT和2,但不输出它们产生的内容:@.

问题是,我将如何根据键盘转换为角色?例如:

  • 在英国键盘上,SHIFT + 2会给我"(引号).
  • 在美国键盘上,SHIFT +2会给我@.

如何根据键盘转换为特定字符?

这是迄今为止的代码:

static interface User32 extends Library {
    public static User32 INSTANCE = (User32) Native.loadLibrary("User32", User32.class);

    short GetAsyncKeyState(int key);
    short GetKeyState(int key);

    IntByReference GetKeyboardLayout(int dwLayout);
    int MapVirtualKeyExW (int uCode, int nMapType, IntByReference dwhkl);

    boolean GetKeyboardState(byte[] lpKeyState);

    int ToUnicodeEx(int wVirtKey, int wScanCode, byte[] lpKeyState, char[] pwszBuff, int cchBuff, int wFlags, IntByReference dwhkl);

}



public static void main(String[] args)  {   
    long currTime = System.currentTimeMillis();

    while (System.currentTimeMillis() < currTime + 20000)
    {
        for (int key = 1; key < 256; key++)
            {
                if (isKeyPressed(key)) 
                    getKeyType(key);
            }
    }
}



private static boolean isKeyPressed(int key)
{
    return User32.INSTANCE.GetAsyncKeyState(key) == -32767;
}



private static void getKeyType(int key)
{

    boolean isDownShift = (User32.INSTANCE.GetKeyState(VK_SHIFT) & 0x80) == 0x80;
    boolean isDownCapsLock = (User32.INSTANCE.GetKeyState(VK_CAPS)) != 0;


    byte[] keystate = new byte[256];
    User32.INSTANCE.GetKeyboardState(keystate); 


    IntByReference keyblayoutID = User32.INSTANCE.GetKeyboardLayout(0);
    int ScanCode  = User32.INSTANCE.MapVirtualKeyExW(key, MAPVK_VK_TO_VSC, keyblayoutID);






    char[] buff = new char[10];

    int bufflen = buff.length;
    int ret = User32.INSTANCE.ToUnicodeEx(key, ScanCode, keystate, buff, bufflen, 0, keyblayoutID);


    switch (ret)
    {
        case -1: 
            System.out.println("Error");
        break;

        case 0:  // no translation

        break;

        default: 
        System.out.println("output=" + String.valueOf(buff).substring(0, ret));
    }




}
Run Code Online (Sandbox Code Playgroud)

它工作正常并输出按下的键,但不适用于Shift +组合.我意识到我可以做一个"Switch"并将Shift + 3更改为"£",但这不适用于不同的键盘.

Dav*_*vid 0

我得到了它。经过很多很多个小时的搜索,我设法创建了一种方法,可以将组合转换为当前键盘布局上的组合。它不处理死键(例如重音),但它捕获了[SHIFT+Combinations]我需要它捕获的所有内容。

\n\n

要使用它,请按如下方式调用它:

\n\n
getCharacter(int vkCode, boolean shiftKeyPressed);\n
Run Code Online (Sandbox Code Playgroud)\n\n

那么,观看这个魔术吧。如果我想获得SHIFT+3键盘上的内容(\xc2\xa3),我使用:

\n\n
getCharacter(KeyEvent.VK_3, true);\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是代码:

\n\n
public static char getCharacter(int vkCode, boolean shiftKeyPressed)\n{\n\n    byte[] keyStates = new byte[256]; //Create a keyboard map of 256 keys\n\n    if (shiftKeyPressed)\n    {\n        keyStates[16]=-127; //Emulate the shift key being held down\n        keyStates[160]=-128; //This needs to be set as well\n    }\n\n    IntByReference keyblayoutID = User32.INSTANCE.GetKeyboardLayout(0); //Load local keyboard layout\n\n    int ScanCode  = User32.INSTANCE.MapVirtualKeyExW(vkCode, MAPVK_VK_TO_VSC, keyblayoutID); //Get the scancode\n\n    char[] buff = new char[1];\n\n    int ret = User32.INSTANCE.ToUnicodeEx(vkCode, ScanCode, keyStates, buff, 1, 0, _currentInputLocaleIdentifier);\n\n    switch (ret)\n    {\n    case -1: //Error\n        return (char) -1;\n\n    case 0:  //No Translation\n        return (char) 0;\n\n    default: //Returning key...\n        return buff[0];\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

以下是声明:

\n\n
final static int MAPVK_VK_TO_VSC = 0;\nstatic IntByReference _currentInputLocaleIdentifier; \n\nstatic interface User32 extends Library {\n\n    public static User32 INSTANCE = (User32) Native.loadLibrary("User32", User32.class);\n\n\n    IntByReference GetKeyboardLayout(int dwLayout);\n    int MapVirtualKeyExW (int uCode, int nMapType, IntByReference dwhkl);\n\n    boolean GetKeyboardState(byte[] lpKeyState);\n\n    int ToUnicodeEx(int wVirtKey, int wScanCode, byte[] lpKeyState, char[] pwszBuff, int cchBuff, int wFlags, IntByReference dwhkl);\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

非常感谢 BrendanMcK,他帮助我找到了这个解决方案。

\n