GetAsyncKeyState and VirtualKeys/special characters using JNA (JAVA)(使用 JNA (JAVA) 的 GetAsyncKeyState 和 VirtualKeys/特殊字符)
问题描述
我正在开发一个可以在全屏游戏中使用的双向私人聊天.
I am working on a two-way private chat that will work in a full screen game.
这是让用户在屏幕顶部的半透明文本框中输入内容所必需的,即使它没有焦点.
This is required to let the user to type into a semi-transparent textbox at the top of the screen even when it doesn't have focus.
使用以下代码,我可以检测到所有物理键,但使用虚拟键很难.
Using the following code, I can detect ALL physical keys, but have a tough time with virtual keys.
SHIFT 被检测到.
2 被检测到.
但是 Shift + 2 被检测为两个单独的键(即使 [SHIFT+2] 在我的键盘上给出了 @ ).IE:程序输出 SHIFT 和 2,但不输出它们产生的内容:@.
However Shift + 2 are detected both as separate keys (Even though [SHIFT+2] gives @ on my keyboard). IE: The program outputs both SHIFT, and 2, but not what they produce: @.
问题是,我将如何根据键盘转换为字符?例如:
The problem is, how will I convert to a character depending on the keyboard? For example:
- 在英国键盘上,SHIFT+2 会给我 
"(引号). - 在美式键盘上,SHIFT +2 将为我提供 
@. 
- On a UK Keyboard, SHIFT+2 will give me 
"(quotes). - On a US keyboard, SHIFT +2 will give me 
@. 
如何根据键盘转换为特定字符?
How can I convert to a specific character depending on the keyboard?
这是目前为止的代码:
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));
    }
}
它工作正常并输出按下的键,但不适用于 Shift + 组合.我意识到我可以做一个切换"并将 Shift+3 更改为£",但这不适用于不同的键盘.
It works fine and outputs the keys pressed, but doesn't work with Shift + combinations. I realize that I could do a "Switch" and change Shift+3 to "£", but this will not work with different keyboards.
推荐答案
我明白了.经过很多很多小时的搜索,我设法创建了一种方法,可以将组合转换为当前键盘布局上的组合.它不处理死键(例如重音符号),但它捕获了我需要它捕获的所有 [SHIFT+Combinations].
I got it. After many, many, many hours of searching, I managed to create a method that converts the combination to what it should be on the current keyboard layout. It doesn't deal with dead-keys (such as accents), but it catches all the [SHIFT+Combinations] that I need it to catch.
要使用它,调用它如下:
To use it, call it as follows:
getCharacter(int vkCode, boolean shiftKeyPressed);
所以,请注意这个魔术.如果我想获得 SHIFT+3 将在我的键盘 (£) 上给我的内容,我使用:
So, watch this magic. If I want to get what SHIFT+3 will give me on my keyboard (£), I use:
getCharacter(KeyEvent.VK_3, true);
代码如下:
public static char getCharacter(int vkCode, boolean shiftKeyPressed)
{
    byte[] keyStates = new byte[256]; //Create a keyboard map of 256 keys
    if (shiftKeyPressed)
    {
        keyStates[16]=-127; //Emulate the shift key being held down
        keyStates[160]=-128; //This needs to be set as well
    }
    IntByReference keyblayoutID = User32.INSTANCE.GetKeyboardLayout(0); //Load local keyboard layout
    int ScanCode  = User32.INSTANCE.MapVirtualKeyExW(vkCode, MAPVK_VK_TO_VSC, keyblayoutID); //Get the scancode
    char[] buff = new char[1];
    int ret = User32.INSTANCE.ToUnicodeEx(vkCode, ScanCode, keyStates, buff, 1, 0, _currentInputLocaleIdentifier);
    switch (ret)
    {
    case -1: //Error
        return (char) -1;
    case 0:  //No Translation
        return (char) 0;
    default: //Returning key...
        return buff[0];
    }
}
以下是声明:
final static int MAPVK_VK_TO_VSC = 0;
static IntByReference _currentInputLocaleIdentifier; 
static interface User32 extends Library {
    public static User32 INSTANCE = (User32) Native.loadLibrary("User32", User32.class);
    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);
}
非常感谢 BrendanMcK,他帮助我找到了这个解决方案.
A big thank you to BrendanMcK, who helped me to get to this solution.
这篇关于使用 JNA (JAVA) 的 GetAsyncKeyState 和 VirtualKeys/特殊字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用 JNA (JAVA) 的 GetAsyncKeyState 和 VirtualKeys/特殊字符
				
        
 
            
        - GC_FOR_ALLOC 是否更“严重"?在调查内存使用情况时? 2022-01-01
 - 在 Java 中,如何将 String 转换为 char 或将 char 转换 2022-01-01
 - 将 Java Swing 桌面应用程序国际化的最佳实践是什么? 2022-01-01
 - 转换 ldap 日期 2022-01-01
 - 未找到/usr/local/lib 中的库 2022-01-01
 - Eclipse 的最佳 XML 编辑器 2022-01-01
 - java.lang.IllegalStateException:Bean 名称“类别"的 BindingResult 和普通目标对象都不能用作请求属性 2022-01-01
 - 如何使 JFrame 背景和 JPanel 透明且仅显示图像 2022-01-01
 - 获取数字的最后一位 2022-01-01
 - 如何指定 CORS 的响应标头? 2022-01-01
 
						
						
						
						
						
				
				
				
				