2013-12-13 86 views
2

我需要能够读取一个字符,并得到它的语言和键盘布局的关键。从char获取KeyCode?

我知道如何看文化设置和语言。 但是我怎样才能在英语中拿出一个像'S'这样的字母,并且知道它在键盘上的键? 或者对于一个更难的问题,我怎么能把这个字母'ש'知道键盘上的键?

+0

@李亚姆,如果有请求,所以应该有一个原因... – serhio

+2

但是,@serhio,如果我们知道推理有一个更合理的解决方案。 – Liam

+1

有很多符号不对应于单个密钥,而是多个密钥。通过使用Dagger(†)符号可以使用组合Alt 0134 \t \t(请参阅http://www.forlang.wsu.edu/help/keyboards.asp)获得,所以这个问题似乎没有合理的解决方案。 – serhio

回答

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

输出:

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 

(虽然你自己的控制台可能陷入困境ש和/或E视设置和字体)。

请注意,在键盘没有AltGr键的情况下,使用Ctrl + Alt作为替代键的Windows kludge正是如何报告的,它只是在较低级别再次被视为单独的,这是一个让Windows键盘不太灵活(Alt + AltGr在Windows中没有意义)。

编辑:KeyboardPointer的构造函数采用CultureInfo具有明显的易用性,但对于特定文化的辅助键盘而言,使用该编号对于该编号非常有用。例如。 en-US大多数情况下使用0x0149,但是对于不同的版式(如Dvorak),扩展的字符支持(所谓的“国际美国”需要编写英语)有不同的高级字(0x00010149,0x00020149,0x00030149等)像“naïve”,“façade”或“简历”等词)等等。

+0

非常好的答案。谢谢。 –

0

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

+1

除非您知道键盘,否则您无法从KeyCode中推导出一个字母,这正是问题所在。 –