如何捕捉“#” WPF/C# 中不同区域设置键盘上的字符?

发布于 2024-11-04 10:24:23 字数 270 浏览 1 评论 0原文

我的 WPF 应用程序处理键盘按键,特别是 # 和 * 字符,因为它是 VoIP 电话。

不过,我对国际键盘有一个错误,特别是英式英语键盘。通常我会监听 3 键,如果按下 Shift 键修饰符,我们会触发一个事件来执行操作。然而,在英式键盘上,这是“£”字符。我发现英国英语键盘有一个专门的“#”键。显然我们可以只听那个特定的键,但这并不能解决美国英语的情况,即shift-3以及所有无数其他键盘将其放在其他地方。

长话短说,我如何从按键中监听特定字符(无论是组合键还是单个键)并对其做出反应?

My WPF application handles keyboard presses and specifically the # and * character as it is a VoIP phone.

I have a bug though with international keyboards, and in particular the British english keyboard. Normally I listen for the 3 key and if the shift key modifier is down we fire off an event to do stuff. However on the British keyboard this is the '£' character. I found that the UK english keyboard has a dedicated key for '#'. Obviously we could just listen for that particular key, but that doesn't solve the case for US english which is shift-3 and all the countless other keyboards that put it somewhere else.

Long story short, how do I listen for a particular character from a key press, whether it's a key combo or single key and react to it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

远山浅 2024-11-11 10:24:23

下面的函数 GetCharFromKey(Key key) 就可以解决这个问题。

它使用一系列 win32 调用来解码按下的键:

  1. 获取 WPF 密钥中的虚拟密钥

  2. 获取从虚拟按键扫描代码

  3. 获取您的 unicode字符

这个< a href="http://web.archive.org/web/20111225141637/http://huddledmasses.org:80/how-to-get-the-character-and-virtualkey-from-a-wpf-keydown- event/" rel="noreferrer">旧帖子 更详细地描述了它。

      public enum MapType : uint
      {
         MAPVK_VK_TO_VSC = 0x0,
         MAPVK_VSC_TO_VK = 0x1,
         MAPVK_VK_TO_CHAR = 0x2,
         MAPVK_VSC_TO_VK_EX = 0x3,
      }

      [DllImport("user32.dll")]
      public static extern int ToUnicode(
          uint wVirtKey,
          uint wScanCode,
          byte[] lpKeyState,
          [Out, MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 4)] 
            StringBuilder pwszBuff,
          int cchBuff,
          uint wFlags);

      [DllImport("user32.dll")]
      public static extern bool GetKeyboardState(byte[] lpKeyState);

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

      public static char GetCharFromKey(Key key)
      {
         char ch = ' ';

         int virtualKey = KeyInterop.VirtualKeyFromKey(key);
         byte[] keyboardState = new byte[256];
         GetKeyboardState(keyboardState);

         uint scanCode = MapVirtualKey((uint)virtualKey, MapType.MAPVK_VK_TO_VSC);
         StringBuilder stringBuilder = new StringBuilder(2);

         int result = ToUnicode((uint)virtualKey, scanCode, keyboardState, stringBuilder, stringBuilder.Capacity, 0);
         switch (result)
         {
            case -1: 
               break;
            case 0: 
               break;
            case 1:
               {
                  ch = stringBuilder[0];
                  break;
               }
            default:
               {
                  ch = stringBuilder[0];
                  break;
               }
         }
         return ch;
      }

The function below, GetCharFromKey(Key key) will do the trick.

It uses a series of win32 calls to decode the key pressed:

  1. get the virtual key from WPF key

  2. get the scan code from the virtual key

  3. get your unicode character

This old post describes it in a bit more detail.

      public enum MapType : uint
      {
         MAPVK_VK_TO_VSC = 0x0,
         MAPVK_VSC_TO_VK = 0x1,
         MAPVK_VK_TO_CHAR = 0x2,
         MAPVK_VSC_TO_VK_EX = 0x3,
      }

      [DllImport("user32.dll")]
      public static extern int ToUnicode(
          uint wVirtKey,
          uint wScanCode,
          byte[] lpKeyState,
          [Out, MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 4)] 
            StringBuilder pwszBuff,
          int cchBuff,
          uint wFlags);

      [DllImport("user32.dll")]
      public static extern bool GetKeyboardState(byte[] lpKeyState);

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

      public static char GetCharFromKey(Key key)
      {
         char ch = ' ';

         int virtualKey = KeyInterop.VirtualKeyFromKey(key);
         byte[] keyboardState = new byte[256];
         GetKeyboardState(keyboardState);

         uint scanCode = MapVirtualKey((uint)virtualKey, MapType.MAPVK_VK_TO_VSC);
         StringBuilder stringBuilder = new StringBuilder(2);

         int result = ToUnicode((uint)virtualKey, scanCode, keyboardState, stringBuilder, stringBuilder.Capacity, 0);
         switch (result)
         {
            case -1: 
               break;
            case 0: 
               break;
            case 1:
               {
                  ch = stringBuilder[0];
                  break;
               }
            default:
               {
                  ch = stringBuilder[0];
                  break;
               }
         }
         return ch;
      }
小伙你站住 2024-11-11 10:24:23

我在这篇文章中找到了一个有用的解决方案: http://www.codewrecks.com/blog/index.php/2008/05/06/wpf-convert-systemwindowsinputkey-to-char-or-string-2/

还有另一个事件< code>TextInput 或 PreviewTextInput 将字符作为字符串而不是 Key :)。

I found a helpful solution in this post: http://www.codewrecks.com/blog/index.php/2008/05/06/wpf-convert-systemwindowsinputkey-to-char-or-string-2/

There is another event TextInput or PreviewTextInput which gives the character as string instead of the Key :).

零崎曲识 2024-11-11 10:24:23

根据 @JanDotNet 答案的输入,该链接不再指向现有网站:它使用 PreviewTextInput 事件对我有用。

Xaml:

<TextBox x:Name="NameTextBox" ... PreviewTextInput="NameTextBox_PreviewTextInput"/>

背后代码:

private void NameTextBox_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
{
    // Check for forbidden characters (as negatives of the allowed characters) in the input.
    if (Regex.IsMatch(e.Text, @"[^0-9^A-z^\+^\-^\=^\<^\>^\%^\[^\]]"))
    {
        // Prevent the character being entered into the text box.
        e.Handled = true;
    }
}

Based on the input from the answer of @JanDotNet where the link doesn't lead to an existent website anymore: it worked for me using the PreviewTextInput event.

Xaml:

<TextBox x:Name="NameTextBox" ... PreviewTextInput="NameTextBox_PreviewTextInput"/>

Code behind:

private void NameTextBox_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
{
    // Check for forbidden characters (as negatives of the allowed characters) in the input.
    if (Regex.IsMatch(e.Text, @"[^0-9^A-z^\+^\-^\=^\<^\>^\%^\[^\]]"))
    {
        // Prevent the character being entered into the text box.
        e.Handled = true;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文