4

I need to get the numeric values of keyboard keys based on ASCII table .As WPF doesn't have built in solution I have tried several hacks:

1. This one gives only the upper case value.

        char res ;
        Char.TryParse(e.Key.ToString(),out res);
        Debug.WriteLine((int)res);

2 This one ,even though it is listed in many places as possible solution , gives a completely wrong number .

        Debug.WriteLine(Convert.ToInt16(e.Key).ToString());
      

So how do I get both upper and lower case letter ASCII codes from the input in WPF ?

Update

After getting several answers here I want to emphasize my question .I absolutely must get ASCII codes from the input both for lower and upper case.No hard coded char compare or anything like that.I am looking for more generic way.

Community
  • 1
  • 1
Michael IV
  • 11,016
  • 12
  • 92
  • 223
  • Where does `e` come from? – Sebastian Negraszus Feb 11 '13 at 19:00
  • Presumably, `e` is a [KeyEventArgs](http://msdn.microsoft.com/en-us/library/system.windows.input.keyeventargs.aspx) – Chris Sinclair Feb 11 '13 at 19:01
  • 1
    I think, and I may be wrong, but the `KeyEventArgs` doesn't provide a _direct_ way of grabbing the upper/lower case of the key pressed (that is, SHIFT + key, or toggled based on CapsLock). You would have to manually check if the key equals the particular physical key (via `e.Key == Keys.YOUR_KEY`), then check the "modifiers" (like `SHIFT`) and perform a final toggle based on `IsToggled(Keys.CapsLock)`. – Chris Sinclair Feb 11 '13 at 19:03
  • Based on your updated question, if you _must_ get _ASCII_ representation of the characters, I'm not sure there's a built-in mechanism to do that. _Generally_ speaking, that level of text encoding is handled on an I/O side of things whereas the `KeyEventArgs` are handled on a GUI side. I think you may have to roll your own simple class to do the conversion to ASCII; perhaps there's an existing open source helper utility library to do this, but I don't know of it. If you can convert the `Key` into a `string` type, then you might be able to leverage System.Text.Encoding.ASCII in some way. – Chris Sinclair Feb 11 '13 at 19:15
  • May be some system DLLs ? From windows API ? – Michael IV Feb 11 '13 at 19:22
  • I can't believe such a framework as WPF doesn't allow to do this.... – Michael IV Feb 11 '13 at 19:25
  • It sounds like you're trying to take text input using a control that isn't designed to take text input. Why not just use a `TextBox` and get the string? Or to put it a different way, what are you trying to accomplish that requires you to approach the problem in the way you are? – GalacticCowboy Feb 11 '13 at 19:46
  • Here's the WinAPI function that would be needed: [`ToAscii`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms646316.aspx). Note that it needs the status of every key on the keyboard in order to determine what modifiers are in effect (e.g. Caps Lock, SHIFT pressed, etc.) `GetKeyboardState` gives access to that information. – Ben Voigt Feb 11 '13 at 21:31
  • You are mistaken on your assumptions of how keyboards work or the information provided by KeyEvent. See my answer to this question: http://stackoverflow.com/questions/14720836/what-events-occur-when-i-enter-text-into-a-field-what-text-encoding-is-my-input/14727598#14727598 and then use the code @kenny provided it seems to be correctly translating virtual keys to characters, but I have not run it, and there might be a better way. – Eli Algranti Feb 11 '13 at 23:12

4 Answers4

5

Look at KeyEventUtility.GetCharFromKey( e.Key )

UPDATE: sorry that was some library code of mine

    public static class KeyEventUtility
{
    // ReSharper disable InconsistentNaming
    public enum MapType : uint
    {
        MAPVK_VK_TO_VSC = 0x0,
        MAPVK_VSC_TO_VK = 0x1,
        MAPVK_VK_TO_CHAR = 0x2,
        MAPVK_VSC_TO_VK_EX = 0x3,
    }
    // ReSharper restore InconsistentNaming

    [DllImport( "user32.dll" )]
    public static extern int ToUnicode(
        uint wVirtKey,
        uint wScanCode,
        byte[] lpKeyState,
        [Out, MarshalAs( UnmanagedType.LPWStr, SizeParamIndex = 4 )] 
       StringBuilder pwszBuff,
    int cchBuff,
    uint wFlags );

[DllImport( "user32.dll" )]
public static extern bool GetKeyboardState( byte[] lpKeyState );

[DllImport( "user32.dll" )]
public static extern uint MapVirtualKey( uint uCode, MapType uMapType );

public static char GetCharFromKey( Key key )
    {
        char ch = ' ';

        int virtualKey = KeyInterop.VirtualKeyFromKey( key );
        var keyboardState = new byte[256];
        GetKeyboardState( keyboardState );

        uint scanCode = MapVirtualKey( (uint)virtualKey, MapType.MAPVK_VK_TO_VSC );
        var stringBuilder = new StringBuilder( 2 );

        int result = ToUnicode( (uint)virtualKey, scanCode, keyboardState, stringBuilder, stringBuilder.Capacity, 0 );
        switch ( result )
        {
        case -1:
            break;
        case 0:
            break;
        case 1:
            {
                ch = stringBuilder[0];
                break;
            }
        default:
            {
                ch = stringBuilder[0];
                break;
            }
        }
        return ch;
    }
kenny
  • 21,522
  • 8
  • 49
  • 87
4

Based on one of the answers mentioned here, I would suggest You to use TextInput (or PreviewTextInput) event to get the letter pressed. It should give You correct values for both upper and lower case letters.

In order to test it, You can use code similar to this one:

private void Window_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
    Console.WriteLine(String.Format("letter: {0} (charcode: {1})", e.TextComposition.Text, (int)Convert.ToChar(e.TextComposition.Text)));
}

Let me know if this helps or if You have any problems when using this solution.

Community
  • 1
  • 1
Lukasz M
  • 5,635
  • 2
  • 22
  • 29
  • 1
    Thanks ! Switched to TextInput and now it works like a charm. :) – Michael IV Feb 16 '13 at 15:08
  • I'm glad my answer helped You :). After posting my answer I've noticed that *Hans Passant* mentioned the `TextInput` event in his answer as well. – Lukasz M Feb 17 '13 at 12:07
4

This is just not the way keyboards work. Every PC in the world has the same keyboard. Pressing a key generates a virtual key value, the same value on every keyboard in the world. The e.Key value you get in the KeyDown event.

This is where it stops for keys like the function keys, cursor keys, Shift key, etcetera. Unless the key is a typing key that produces a character. Like the letter A. Internally, the KeyDown event is processed by Windows and translated to a character. The actual character that's produced depends on the keyboard layout. Users in different countries have different keyboard layouts, favoring the glyphs that are used most often in their language. Or for that matter the personal preference of a user, a programmer often likes the Dvorak layout.

The character produced also depends on the keyboard state. Like the Shift key, hold it down to produce an A, not down to produce an a. This can get pretty convoluted on non-English keyboards, other layouts also have dead keys that, when pressed, alters the character produced by a the next keystroke. Languages that have a lot of diacritics use them.

The implication is clear, translating the virtual key you get from a KeyDown event is a very perilous undertaking. You should therefore not attempt to do this. And you don't have to, use the TextInput event.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
0
if (e.Key == Key.A )

Take a look at this page

shahkalpesh
  • 33,172
  • 3
  • 63
  • 88
  • Yeah but this way I will have to map the whole Alphabet in my code.I need the whole keyboard charcode set.That is why I need numeric values. – Michael IV Feb 11 '13 at 19:02