2011-04-28 10 views
24

Mi aplicación WPF maneja prensas de teclado y específicamente el carácter # y * ya que es un teléfono VoIP.cómo capturar el carácter '#' en diferentes teclados de configuración regional en WPF/C#?

Tengo un error con los teclados internacionales, y en particular con el teclado inglés británico. Normalmente escucho la tecla 3 y si el modificador de la tecla shift está abajo, disparamos un evento para hacer cosas. Sin embargo, en el teclado británico este es el personaje '£'. Descubrí que el teclado inglés del Reino Unido tiene una clave dedicada para '#'. Obviamente, podríamos simplemente escuchar esa clave en particular, pero eso no resuelve el caso del inglés de EE. UU. Que es shift-3 y todos los innumerables otros teclados que lo ubican en otro lado.

En pocas palabras, ¿cómo puedo escuchar a un personaje en particular al presionar una tecla, ya sea un combo de tecla o una sola tecla y reaccionar a él?

Respuesta

52

La siguiente función, GetCharFromKey (tecla clave) hará el truco.

Se utiliza una serie de llamadas de Win32 para decodificar la tecla pulsada:

  1. obtener el virtual key from WPF key

  2. obtener el scan code from the virtual key

  3. obtener your unicode character

Este old post lo describe con un poco más de detalle.

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

He estado usando esto desde hace un tiempo y noté un error. Dos claves que devuelven el mismo resultado de GetCharFromKey. Para verificarlo, simplemente subclase un TextBox, anule PreiewKeyDown, pulse la barra espaciadora, (que es 32 caracteres), luego pulse la tecla Supr, también devuelve 32 caracteres. ¿Alguien más está viendo esto? – gcadmes

+0

Bueno, eso fue humillante ... La primera declaración en el GetCharFromKey es el char ch = '';. Entonces, para los casos que caen en '0' o '1', el char de retorno siempre es un espacio (char) 32. (bofetada de frente) – gcadmes

+3

Realmente debería devolver ''\ 0'' para las claves que no producen un carácter de texto, o' (char?) null'. – jnm2

Cuestiones relacionadas