GetAsyncKeyState和使用JNA VirtualKeys /特殊字符(JAVA) [英] GetAsyncKeyState and VirtualKeys/special characters using JNA (JAVA)
问题描述
我工作的一个双向私聊,将在全屏幕游戏的工作。
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.
使用以下code,我可以检测所有物理按键,但有一个艰难的时间与虚拟按键。
Using the following code, I can detect ALL physical keys, but have a tough time with virtual keys.
SHIFT
进行检测。
2
进行检测。
但 SHIFT + 2
同时检测作为单独的按键(即使 [SHIFT + 2]
给<$ ç我的键盘上的$ C> @ )。即:程序输出两个移位,和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?
下面是code迄今:
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));
}
}
它工作正常,并输出键pressed,但不使用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 +组合]
,我需要它来赶上。
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);
下面是code:
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.
这篇关于GetAsyncKeyState和使用JNA VirtualKeys /特殊字符(JAVA)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!