Question

could someone please tell me the identifier for the @ key?

for example keys.Escape is for the ESC key. i would like to know what it is for @

thank you.

Was it helpful?

Solution

The KeyCode is what you get in KeyDown and KeyUp events. Since this is a shifted character, it depends on the keyboard layout. As far as I know, most keyboards have it above the digit 2, and that means checcking for e.Shift && e.KeyCode == Keys.D2 (WinForms). But on some most international keyboards, this will not work.

But note that handling the KeyPress event is much more reliable: e.KeyChar == '@'

Edit: I took a quick look at this page, and most international keyboards have the " over the 2 key and use Alt-something to get a @.

OTHER TIPS

On my keyboard it is Keys.D2 because @ is the same key as digit 2.

However, if you handle KeyPress event you get KeyPressEventArgs in the argument that has KeyPressEventArgs.KeyChar property. And this property contains a character rather than keycode.

You should not use the KeyDown event to recognize typing keys like @. The translation from virtual key code (KeyEventArgs.KeyData) to a typing key is dependent on the keyboard layout. Which is probably different in the UK from the one in the USA, you've got a pound to squeeze in somewhere. And surely different on a keyboard in a far East location.

Use the KeyPressed event instead.

First you need a class to wrap the OS calls necessary for examining the keyboard layout:

public class KeyboardPointer : IDisposable
{
  [DllImport("user32.dll", CharSet = CharSet.Unicode)]
  static extern short VkKeyScanEx(char ch, IntPtr dwhkl);
  [DllImport("user32.dll")]
  static extern bool UnloadKeyboardLayout(IntPtr hkl);
  [DllImport("user32.dll")]
  static extern IntPtr LoadKeyboardLayout(string pwszKLID, uint Flags);
  private readonly IntPtr pointer;
  public KeyboardPointer(int klid)
  {
    pointer = LoadKeyboardLayout(klid.ToString("X8"), 1);
  }
  public KeyboardPointer(CultureInfo culture)
    :this(culture.KeyboardLayoutId){}
  public void Dispose()
  {
    UnloadKeyboardLayout(pointer);
    GC.SuppressFinalize(this);
  }
  ~KeyboardPointer()
  {
    UnloadKeyboardLayout(pointer);
  }
  public bool GetKey(char character, out Keys key)
  {
    short keyNumber = VkKeyScanEx(character, pointer);
    if(keyNumber == -1)
    {
      key = Keys.None;
      return false;
    }
    key = (System.Windows.Forms.Keys)(((keyNumber & 0xFF00) << 8) | (keyNumber & 0xFF));
    return true;
  }
}

Then if you run:

Keys atKey;
bool hasAtKey;
using(var keyboard = new KeyboardPointer(CultureInfo.CurrentCulture))
  hasAtKey = keyboard.GetKey('@', out atKey);

hasAtKey will be true if the keyboard has a key combination for @, in which case atKey will hold the corresponding value, while otherwise it will hold Keys.None.

For example, when I run it then atKey contains the value Keys.Oemtilde | Keys.Shift, but if I change the code to pass in CultureInfo.GetCultureInfo("en-US") it contains Keys.D2 | Keys.Shift.

As you can see, KeyboardPointer is written to accept both a culture and a numeric ID so you aren't restricted to the primary keyboard for a culture but also other layouts used with it, such as Dvorak layouts etc.

The above is all using calls into Windows' User32 functions, so another approach will be necessary on other platforms.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top