How to convert VirtualKey to char for non-US keyboard layouts in WinRT?

In the .NET standard, there were ToAscii / ToUnicode and MapVirtualKey functions to take care of this function, although it seems that an equivalent function or library was not added to Metro / WinRT. If there is virtually no equivalent function or library exposed in Metro / WinRT, then this would make the text input box VERY hard to bring to market in non-US countries. A specific example: in my user control, if a French keyboard user presses the รจ, รน, รฉ or ร  keys, they cannot be translated to the correct character. For example, รจ uses the scan code for VirtualKey.Number7, and as far as I can tell, there is no way to find out the keyboard layout or there is no easy way to translate this scancode based on the current keyboard layout. Anyone have any info on this?

+4
source share
3 answers

I suppose it depends on what you are looking for. If you are looking for a simple English letter or number, you can simply do this:

private static char? ToChar(VirtualKey key, bool shift) { // convert virtual key to char if (32 == (int)key) return ' '; VirtualKey search; // look for simple letter foreach (var letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ") { if (Enum.TryParse<VirtualKey>(letter.ToString(), out search) && search.Equals(key)) return (shift) ? letter : letter.ToString().ToLower()[0]; } // look for simple number foreach (var number in "1234567890") { if (Enum.TryParse<VirtualKey>("Number" + number.ToString(), out search) && search.Equals(key)) return number; } // not found return null; } 

Good luck

+2
source

For WinRT (example with TextBox and select only letters):

  CoreWindow.GetForCurrentThread().CharacterReceived += TextBox_CharacterReceived; void TextBox_CharacterReceived(CoreWindow sender, CharacterReceivedEventArgs args) { char c = Convert.ToChar(args.KeyCode); if (char.IsLetter(c)) { ... } } 

To cancel a de char entry:

 TextBox textBoxData; void TextBox_KeyDown(object sender, KeyRoutedEventArgs e) { textBoxData = sender as TextBox; if (e.Key!=VirtualKey.Space) e.Handled = true; } 

Additionally:

 void TextBox_Paste(object sender, TextControlPasteEventArgs e) { e.Handled = true; } 

and change CharacterReceived:

 if (char.IsLetter(c)) { textBoxData.Text += c; textBoxData.SelectionStart = textBoxData.Text.Length; } 

Attention! if your TextBox has MaxLength, you should change your code:

 if (char.IsLetter(c) && textBoxData.Text.Length < textBoxData.MaxLength) 
+2
source

You can use the Win32 MapVirtualKey API function, which maps a virtual key to a bunch of values, one of which is a character value. MapVirtualKey seems to be using the currently installed keyboard layout (this is not documented). To use the specified layout, you can use MapVirtualKeyEx.

MapVirtualKey does not take into account whether Shift is pressed or not. To easily get information, if you press Shift, you can use GetKeyState (unfortunately, the WinRT command did not make it easier to get the state of modifier keys).

Here is an example of how to translate a virtual key into a symbol:

 [DllImport("user32.dll")] private static extern uint MapVirtualKey(uint uCode, uint uMapType); [DllImport("user32.dll")] private static extern short GetKeyState(uint nVirtKey); private const uint MAPVK_VK_TO_CHAR = 0x02; private const uint VK_SHIFT = 0x10; private char TranslateVirtualKeyIntoChar(VirtualKey key) { char c = (char)MapVirtualKey((uint)key, MAPVK_VK_TO_CHAR); short shiftState = GetKeyState(VK_SHIFT); if (shiftState < 0) { // Shift is pressed c = char.ToUpper(c); } return c; } 

Update

Unfortunately, this solution does not apply to Windows Store applications that must be certified. The certificate fails because MapVirtualKey and GetKeyState APIs are used. It also means that this solution will most likely not work under WinRT.

0
source

All Articles