como capturar o caractere ‘#’ em teclados de localidade diferentes no WPF / C #?

Meu aplicativo WPF manipula pressionamentos de teclado e especificamente o caractere # e *, pois é um telefone VoIP.

Eu tenho um bug embora com teclados internacionais e, em particular, o teclado inglês britânico. Normalmente eu ouço a tecla 3 e, se o modificador da tecla Shift estiver inativo, triggersmos um evento para fazer as coisas. No entanto, no teclado britânico, esse é o caractere ‘£’. Eu achei que o teclado inglês do Reino Unido tem uma chave dedicada para ‘#’. Obviamente, poderíamos apenas ouvir essa chave em particular, mas isso não resolve o caso do inglês americano, que é o shift-3 e todos os inúmeros outros teclados que o colocam em outro lugar.

Para encurtar a história, como ouço um caractere específico de um pressionamento de tecla, seja um combo de teclas ou uma única tecla e reajo a ele?

A function abaixo, GetCharFromKey (tecla de chave) fará o truque.

Ele usa uma série de chamadas win32 para decodificar a tecla pressionada:

  1. obter a chave virtual da chave do WPF

  2. obter o código de verificação da chave virtual

  3. obtenha seu caractere unicode

Este post antigo descreve isso com um pouco mais de detalhes.

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