Как я могу отобразить KeyCode и KeyData для строчных букв в c # winforms - PullRequest
0 голосов
/ 10 ноября 2018

Я пытаюсь показать информацию о нажатых клавишах клавиатуры.
Этот код правильно отображает заглавные буквы, но информация о заглавных буквах отображается также при нажатии строчной буквы.

Как я могу решить эту проблему? Вот что я пытаюсь сделать:

public partial class keyDemo : Form
{
    private void keyDemo_KeyPress(object sender, KeyPressEventArgs e)
    {
        charLabel.Text = $"Key pressed: {e.KeyChar}";
    }

    private void keyDemo_KeyDown(object sender, KeyEventArgs e)
    {
        keyInfoLabel.Text =
            $"Alt: {(e.Alt ? "Yes" : "No")}\n" +
            $"Shift: {(e.Shift ? "Yes" : "No")}\n" +
            $"Ctrl: {(e.Control ? "Yes" : "No")}\n" +
            $"KeyCode: {e.KeyCode}\n" +
            $"KeyData: {e.KeyData}\n" +
            $"KeyValue: {e.KeyValue}";
    }

    private void keyDemo_KeyUp(object sender, KeyEventArgs e)
    {
        charLabel.Text = "";
        keyInfoLabel.Text = "";
    }
}

it shows uppercase info but the pressed key is lowercase

1 Ответ

0 голосов
/ 10 ноября 2018

Причина этого в том, что KeyEventArgs возвращает детали ключа, а не символа. (Заглавные и строчные буквы используют один и тот же ключ.) Некоторые клавиши не производят символы (например, Shift, F-клавиши), другие - непечатаемые символы (например, Tab, Escape), а символ, создаваемый определенным нажатием клавиши, зависит от вашей раскладки клавиатуры.

Если вам нужен персонаж, вам, вероятно, следует использовать событие KeyPress, а не KeyDown.

Но если вы хотите сделать это:

Как говорит @PrinceOfRavens, вам нужно проверить состояние клавиши Caps Lock.

Вы можете сделать это следующим образом, но это все равно не обрабатывает ключи, кроме букв, и не обрабатывает Alt Gr (для акцентированных букв). Чтобы полностью преобразовать нажатие клавиши в символ, вам потребуется преобразовать Keys.Add (цифровая клавиатура '+') и Shift '=' на большинстве клавиатур в "+", а Shift "1" обычно в "!" (в зависимости от вашей раскладки клавиатуры).

Вы можете расширить его, заменив return null в KeyToLetter, , но это НЕ рекомендуемый способ получения символа, набранного .

(я добавил два элемента к выводу.)

    using System.Runtime.InteropServices;   // for GetKeyState

    ...


    private void keyDemo_KeyDown(object sender, KeyEventArgs e)
    {
        keyInfoLabel.Text =
            $"Alt: {(e.Alt ? "Yes" : "No")}\n" +
            $"Shift: {(e.Shift ? "Yes" : "No")}\n" +
            $"Ctrl: {(e.Control ? "Yes" : "No")}\n" +
            $"KeyCode: {e.KeyCode}\n" +
            $"KeyData: {e.KeyData}\n" +
            $"KeyValue: {e.KeyValue}\n" +
            $"CapsLock: {(CapsLockState ? "Yes" : "No")}\n" +
            $"Letter: {KeyToLetter(e.KeyData, CapsLockState)}";
    }

    // Import the DLL to use a Win32 API call.
    // See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getkeystate
    // If using WPF, you could use Keyboard.IsKeyDown :
    //  https://docs.microsoft.com/en-us/dotnet/api/system.windows.input.keyboard.iskeydown?view=netframework-4.7.2
    [DllImport("user32.dll")]
    public static extern short GetKeyState(Keys nVirtKey);

    /// <summary>
    /// true if Caps Lock is on, otherwise false.
    /// </summary>
    public bool CapsLockState 
        => (GetKeyState(Keys.CapsLock) & 1) == 1;

    /// <summary/>
    /// <param name="key">A base key (no modifiers).</param>
    /// <returns>true if and only if the given key represents a letter.</returns>
    public static bool IsLetterKey(Keys key)
        => key >= Keys.A && key <= Keys.Z;

    /// <summary>
    /// Given a keystroke that produces a letter, this returns the letter.
    /// </summary>
    /// <param name="key"></param>
    /// <param name="capsLockState"></param>
    /// <returns>the letter, or null if the given keystroke does not produce a letter.</returns>
    public static char? KeyToLetter(Keys key, bool capsLockState)
    {
        Keys baseKey = key & ~Keys.Modifiers;  // remove modifier keys
        if (IsLetterKey(baseKey) && !key.HasFlag(Keys.Control))    // if a letter
        {
            bool shiftPressed = key.HasFlag(Keys.Shift);   // check whether Shift was pressed
            bool capital = capsLockState ^ shiftPressed;   // if it should be capital
            if (capital)
                return (char)baseKey;
            else
                return Char.ToLower((char)baseKey);
        }
        else
        {
            return null;  // not a letter
        }
    }
...