Search code examples
c#winformskeypresssingle-quotes

Detect single quote key on KeyDown event


I want a TextBox to only accept some specific characters by using the KeyDown event. I've already got it working, except for one character, the single quote. To get the character that will be written I use (char)e.KeyValue which works for all the characters except the quote (it gives Û). I know I could just use e.KeyCode but it's value is Keys.Oem4, which AFAIK might be different across systems.

Is there any way of consistently detecting a single quote key press?

Code snippet:

char c = (char)e.KeyValue;
char[] moves = { 'r', 'u', ..., '\'' };

if (!(moves.Contains(c) || e.KeyCode == Keys.Back || e.KeyCode == Keys.Space))
{
    e.SuppressKeyPress = true;
}

Solution

  • As @EdPlunkett suggested, this answer works for me:

    [DllImport("user32.dll")]
    static extern bool GetKeyboardState(byte[] lpKeyState);
    
    [DllImport("user32.dll")]
    static extern uint MapVirtualKey(uint uCode, uint uMapType);
    
    [DllImport("user32.dll")]
    static extern IntPtr GetKeyboardLayout(uint idThread);
    
    [DllImport("user32.dll")]
    static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl);
    
    
    public static string KeyCodeToUnicode(System.Windows.Forms.Keys key)
    {
        byte[] keyboardState = new byte[255];
        bool keyboardStateStatus = GetKeyboardState(keyboardState);
    
        if (!keyboardStateStatus)
        {
            return "";
        }
    
        uint virtualKeyCode = (uint)key;
        uint scanCode = MapVirtualKey(virtualKeyCode, 0);
        IntPtr inputLocaleIdentifier = GetKeyboardLayout(0);
    
        StringBuilder result = new StringBuilder();
        ToUnicodeEx(virtualKeyCode, scanCode, keyboardState, result, (int)5, (uint)0, inputLocaleIdentifier);
    
        return result.ToString();
    }