I've implemented a low-level keyboard hook using SetWindowsHookEx() function. It works fine and returns a virtual key code for each keystroke. I can convert this virtual key code to a System.Windows.Input.Key using KeyInterop.KeyFromVirtualKey(). But the target is to get a symbol that corresponds to this virtual key code in current keyboard layout.
I.e. for German layout I want to get "Y" for Key.Z, "Z" for Key.Y.
Does anyone can help?
Thank you.
call the GetKeyboardLayout to retrieve the active layout value, then, do some conditional loop to get the result you want.
You should take a look at this methods GetKeyboardState, GetKeyboardLayout, MapVirtualKeyEx, ToUnicodeEx.
Solution should look something like
byte[] keyboardState = new byte[256];
GetKeyboardState(keyboardState);
IntPtr handle = GetKeyboardLayout(0);
uint scanCode = MapVirtualKeyEx(VirtualKeyCode, 0, handle);
StringBuilder stringBuilder = new StringBuilder(2);
int nResultLower = ToUnicodeEx(VirtualKeyCode, scanCode, keyboardState, stringBuilder,
stringBuilder.Capacity, 0, handle);
string output= string.Empty;
if (nResultLower != 0)
{
output = stringBuilder.ToString();
}
Not quite sure we're talking about same scenario, but I recently encountered similar problem where ToUnicodeEx interrupted users' key strokes (when using modifiers like 'alt+numpad' or on German keyboard the '+' key modifier), causing unexpected letters to be printed into screen instead if the desired ones.
Solved my problem by combining @Nejchy's code with ClearKeyboardBuffer method right before running ToUnicodeEx:
private static bool ClearKeyboardBuffer(uint vk, uint sc, IntPtr hkl)
{
StringBuilder sb = new StringBuilder(10);
int rc = -1;
bool isDeadKey = false;
while (rc < 0)
{
rc = user32.ToUnicodeEx(vk, sc, new byte[256], sb, sb.Capacity, 0, hkl);
if (!isDeadKey && rc == -1) isDeadKey = true;
Console.Write(rc);
}
return isDeadKey;
}
In your code that does 'ToUnicodeEx':
var isDeadKey = ClearKeyboardBuffer((uint)aKey, 0, hKd);
if (isDeadKey) return;
user32.ToUnicodeEx((uint)aKey, vkCode, keyboardState, characters, 10, (uint)0, hKd);
Reference:
http://www.siao2.com/2006/03/23/558658.aspx
http://www.siao2.com/2006/04/06/569632.aspx
Also look at his code:
https://stackoverflow.com/a/8705696/802848