从char中获取KeyCode?

use*_*645 2 c# key converter char

我需要能够读取一个字符并使其与其语言和键盘布局相关.

我知道如何看待文化背景和语言.但是我怎么能用英文写一个像'S'的字母,知道它在键盘上的键是什么?或者对于一个更难的问题,我怎么能拿到字母"ש"并知道它在键盘上的键是什么?

Jon*_*nna 11

使用示例程序可能比使用其他任何内容更容易解释这个:

namespace KeyFinder
{
  class Program
  {
    [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);
    public class KeyboardPointer : IDisposable
    {
      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);
      }
      // Converting to System.Windows.Forms.Key here, but
      // some other enumerations for similar tasks have the same
      // one-to-one mapping to the underlying Windows API values
      public bool GetKey(char character, out Keys key)
      {
        short keyNumber = VkKeyScanEx(character, pointer);
        if(keyNumber == -1)
        {
          key = System.Windows.Forms.Keys.None;
          return false;
        }
        key = (System.Windows.Forms.Keys)(((keyNumber & 0xFF00) << 8) | (keyNumber & 0xFF));
        return true;
      }
    }
    private static string DescribeKey(Keys key)
    {
      StringBuilder desc = new StringBuilder();
      if((key & Keys.Shift) != Keys.None)
        desc.Append("Shift: ");
      if((key & Keys.Control) != Keys.None)
        desc.Append("Control: ");
      if((key & Keys.Alt) != Keys.None)
        desc.Append("Alt: ");
      return desc.Append(key & Keys.KeyCode).ToString();
    }
    public static void Main(string[] args)
    {
      string testChars = "Aé?";
      Keys key;
      foreach(var culture in (new string[]{"he-IL", "en-US", "en-IE"}).Select(code => CultureInfo.GetCultureInfo(code)))
      {
        Console.WriteLine(culture.Name);
        using(var keyboard = new KeyboardPointer(culture))
          foreach(char test in testChars)
          {
            Console.Write(test);
            Console.Write('\t');
            if(keyboard.GetKey(test, out key))
              Console.WriteLine(DescribeKey(key));
            else
              Console.WriteLine("No Key");
          }
      }
      Console.Read();//Stop window closing
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

输出:

he-IL
A  Shift: A
é  No Key
?  A
en-US
A  Shift: A
é  No Key
?  No Key
en-IE
A  Shift: A
é  Control: Alt: E
?  No Key
Run Code Online (Sandbox Code Playgroud)

(虽然根据设置和字体,你自己的控制台可能会搞乱和/或é).

请注意,在键盘没有AltGr键的情况下,使用Ctrl + Alt作为替代的Windows kludge正是它的报告方式,它只是在较低的级别再将两者视为单独的,这是其中一个使Windows键盘的灵活性降低(Alt + AltGr在Windows中毫无意义).

编辑:对于构造函数KeyboardPointer,需要一个CultureInfo具有明显的易用性,但是这需要一个数字是针对给定的文化附属键盘非常有用.例如,en-US最常使用0x0149,但是对于像Dvorak这样的变体布局,存在具有不同更高字(0x00010149,0x00020149,0x00030149等)的变体,对字符的扩展支持(所谓的"国际美国"需要写入英语单词"naïve","façade"或"résumé")等.