【问题标题】:Get KeyCode from a char?从字符中获取 KeyCode?
【发布时间】:2014-01-01 08:00:12
【问题描述】:

我需要能够读取一个字符并获得与其语言和键盘布局相关的键。

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

【问题讨论】:

  • @Liam,如果有请求,那么应该是有原因的......
  • 但是,@serhio,如果我们知道其中的原因,可能会有一个更合乎逻辑的解决方案。
  • 有很多符号对应的不是一个Key,而是多个Key。通过 ex 可以使用组合 Alt 0134 获得 Dagger (†) 符号(请参阅 forlang.wsu.edu/help/keyboards.asp),因此这个问题似乎确实没有合乎逻辑的解决方案。
  • 不清楚他们在问什么。他们有一个语言环境、键盘布局和一个字符,并且想知道它是否有一个键,以及它是什么。还有什么更清楚的?
  • @serhio 知道说“按 ש 键”是否有意义,这本身就是一个原因。

标签: c# char key converter


【解决方案1】:

用一个示例程序可能比其他任何东西都更容易解释这个:

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
    }
  }
}

输出:

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

(尽管您自己的控制台可能会根据设置和字体弄乱 ש 和/或 é)。

请注意,在键盘没有 AltGr 键的情况下,Windows 使用 Ctrl+Alt 作为替代品正是它的报告方式,只是在较低级别再次将两者视为单独的,这是其中之一使 Windows 键盘不那么灵活的因素(Alt + AltGr 在 Windows 中毫无意义)。

编辑:KeyboardPointer 的构造函数采用 CultureInfo 具有明显的易用性,但采用数字的构造函数对于给定文化的辅助键盘很有用。例如。 en-US 最常使用 0x0149,但对于 Dvorak 等变体布局,也有具有不同更高单词(0x00010149、0x00020149、0x00030149 等)的变体,对字符的扩展支持(所谓的“国际美国”需要编写英语诸如“naïve”、“façade”或“ressumé”之类的词)等等。

【讨论】:

  • 非常好的答案。谢谢。
【解决方案2】:

您可以解析KeyCode 以确定它是否包含您要搜索的字母。对于非英语输入,我想您必须将这些映射到英文字母才能知道键盘上的哪个键。

【讨论】:

  • 除非您知道键盘,否则您无法从 KeyCode 中推断出字母,这正是问题所在。
猜你喜欢
  • 2013-07-09
  • 1970-01-01
  • 2010-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多