Как захватить символ "#" на разных языковых клавиатурах в WPF/С#?

В моем приложении WPF обрабатываются нажатия клавиш и, в частности, символ # и *, так как это VoIP-телефон.

У меня есть ошибка, хотя с международными клавиатурами и, в частности, английской английской клавиатурой. Обычно я слушаю ключ 3, и если модификатор смены ключа выключен, мы запускаем событие, чтобы сделать что-то. Однако на британской клавиатуре это символ "Е". Я обнаружил, что английская английская клавиатура имеет выделенный ключ для "#". Очевидно, мы могли бы просто прослушать этот конкретный ключ, но это не решает проблему для английского английского, который является shift-3 и всех бесчисленных других клавиатур, которые помещают его где-то в другом месте.

Короче говоря, как я могу прослушивать определенный символ от нажатия клавиши, будь то ключевой комбо или один ключ и реагировать на него?

Ответ 1

Функция ниже, GetCharFromKey (клавиша Key), добьется цели.

Для декодирования нажатой клавиши используется серия вызовов win32:

  1. получить виртуальный ключ из ключа WPF

  2. получить код сканирования из виртуального ключа

  3. получить свой юникодный символ

Этот старый пост описывает его более подробно.

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