如何在WinRT中将VirtualKey转换为非美国键盘布局的char?

时间:2012-12-02 07:16:47

标签: c# microsoft-metro windows-runtime windows-store-apps

在标准.NET中,存在ToAscii / ToUnicode和MapVirtualKey函数来处理这个功能,虽然它似乎没有被带入Metro / WinRT的等效函数或库。如果在Metro / WinRT中实际上没有公开的等效功能或库,则会使非自定义文本输入框非常难以在非美国国家推向市场。 具体示例:在我的自定义控件中,如果法语键盘用户按下è,ù,é或à键,则无法将它们转换为正确的字符。例如,è使用VirtualKey.Number7的扫描代码,据我所知,没有办法知道键盘布局或根据当前键盘布局没有简单的方法来翻译该扫描码。 有没有人有关于此的一些信息?

3 个答案:

答案 0 :(得分:2)

我想这取决于你在寻找什么。如果您正在寻找一个简单的英文字母或数字,您可以这样做:

private static char? ToChar(VirtualKey key, bool shift)
{
    // convert virtual key to char
    if (32 == (int)key)
        return ' ';

    VirtualKey search;

    // look for simple letter
    foreach (var letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
    {
        if (Enum.TryParse<VirtualKey>(letter.ToString(), out search) && search.Equals(key))
            return (shift) ? letter : letter.ToString().ToLower()[0];
    }

    // look for simple number
    foreach (var number in "1234567890")
    {
        if (Enum.TryParse<VirtualKey>("Number" + number.ToString(), out search) && search.Equals(key))
            return number;
    }

    // not found
    return null;
}

祝你好运!

答案 1 :(得分:2)

对于WinRT(带有TextBox的示例,只选择Letters):

 CoreWindow.GetForCurrentThread().CharacterReceived += TextBox_CharacterReceived;
 void TextBox_CharacterReceived(CoreWindow sender, CharacterReceivedEventArgs args)
    {
        char c = Convert.ToChar(args.KeyCode);
        if (char.IsLetter(c))
        {
           ...
        }
    }

取消de char条目:

TextBox textBoxData;

void TextBox_KeyDown(object sender, KeyRoutedEventArgs e)
    {
        textBoxData = sender as TextBox;
        if (e.Key!=VirtualKey.Space)
        e.Handled = true;
    }

可选的:

void TextBox_Paste(object sender, TextControlPasteEventArgs e)
   {
       e.Handled = true;
   }

并修改CharacterReceived:

if (char.IsLetter(c))
   {
     textBoxData.Text += c;
     textBoxData.SelectionStart = textBoxData.Text.Length;
    }

警告!如果您的TextBox具有MaxLength,则必须修改代码:

if (char.IsLetter(c) && textBoxData.Text.Length < textBoxData.MaxLength)

答案 2 :(得分:0)

您可以使用Win32 API函数MapVirtualKey将虚拟键映射到一组值,其中一个值是字符值。 MapVirtualKey似乎使用当前设置的键盘布局(这没有记录)。要使用指定的布局,您可以使用MapVirtualKeyEx。

MapVirtualKey不会考虑是否按下Shift。如果按下Shift键轻松获取信息,可以使用GetKeyState(遗憾的是,WinRT团队无法轻松获取修改键的状态)。

以下是如何将虚拟键转换为字符的示例:

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

[DllImport("user32.dll")]
private static extern short GetKeyState(uint nVirtKey);

private const uint MAPVK_VK_TO_CHAR = 0x02;

private const uint VK_SHIFT = 0x10;

private char TranslateVirtualKeyIntoChar(VirtualKey key)
{
   char c = (char)MapVirtualKey((uint)key, MAPVK_VK_TO_CHAR);
   short shiftState = GetKeyState(VK_SHIFT);
   if (shiftState < 0)
   {
      // Shift is pressed
      c = char.ToUpper(c);
   }
   return c;
}

<强>更新

不幸的是,此解决方案不适用于必须经过认证的Windows应用商店应用。由于使用了MapVirtualKey和GetKeyState不支持的API,因此认证失败。这也意味着该解决方案很可能无法在WinRT下运行。