我如何获得仅知道ConsoleKey枚举和修饰符的按键的字符?

Ant*_*ean 4 c# console powershell keypress

我想创建一个ConsoleKeyInfo在PowerShell会话中键入的任何开括号的匹配括号的实例(我使用PSReadline进行键处理).为方便起见,以下是所涉及的所有密钥的属性

PS> while($true){ [System.Console]::ReadKey($true) }

    KeyChar     Key    Modifiers
    -------     ---    ---------
          [    Oem4            0
          ]    Oem6            0  
          {    Oem4        Shift
          }    Oem6        Shift
Run Code Online (Sandbox Code Playgroud)

在键处理程序中,我被赋予了ConsoleKeyInfo被按下的"和弦"(并且PSReadline进行了过滤,所以我已经知道我只接收了一个Oem4或者Shift+Oem4).我想生成匹配,ConsoleKeyInfo所以我可以将对打印发送到控制台.

ConsoleKeyInfo构造需要

  • 一个 char
  • 一个 System.ConsoleKey
  • 一个bool分别用于移位,Alt和控制

我可以把ConsoleKey它变成一个int并向上移动两个......

PS> [System.ConsoleKey]([int]$key.Key + 2)
Oem6
Run Code Online (Sandbox Code Playgroud)

我可以按下按键Modifiers测试按键映射...

PS> ($key.Modifiers -band [System.ConsoleModifiers]::Shift) -ne 0
False
Run Code Online (Sandbox Code Playgroud)

但是,我不知道如何获得char此控制台密钥的文字.控制台如何从键盘键获取字符?这只能通过现场控制台/键盘来完成吗?

我宁愿不维护密钥对的映射,也不分割处理程序,每个"和弦"一个,并硬编码匹配的密钥char.:(

Jas*_*irk 5

您可能不需要仅为PSReadline创建ConsoleKeyInfo.

有时您可能需要将ConsoleKeyInfo传递给PSConsoleReadLine中的方法,但PSConsoleReadLine中接受ConsoleKeyInfo的大多数方法甚至都不会查看参数.这就是参数为Nullable的原因.

这实际上并没有回答你的问题.JaredPar绝对正确,一般来说,无法将ConsoleKey/ConsoleModifiers对转换为char.如果我们不关心完全的通用性(当前PSReadline没有),您可以使用类似于PSReadline使用的代码:

internal static char GetCharFromConsoleKey(ConsoleKey key, ConsoleModifiers modifiers)
{
    // default for unprintables and unhandled
    char keyChar = '\u0000';

    // emulate GetKeyboardState bitmap - set high order bit for relevant modifier virtual keys
    var state = new byte[256];
    state[NativeMethods.VK_SHIFT] = (byte)(((modifiers & ConsoleModifiers.Shift) != 0) ? 0x80 : 0);
    state[NativeMethods.VK_CONTROL] = (byte)(((modifiers & ConsoleModifiers.Control) != 0) ? 0x80 : 0);
    state[NativeMethods.VK_ALT] = (byte)(((modifiers & ConsoleModifiers.Alt) != 0) ? 0x80 : 0);

    // a ConsoleKey enum's value is a virtual key code
    uint virtualKey = (uint)key;

    // get corresponding scan code
    uint scanCode = NativeMethods.MapVirtualKey(virtualKey, NativeMethods.MAPVK_VK_TO_VSC);

    // get corresponding character  - maybe be 0, 1 or 2 in length (diacriticals)
    var chars = new char[2];
    int charCount = NativeMethods.ToUnicode(
        virtualKey, scanCode, state, chars, chars.Length, NativeMethods.MENU_IS_INACTIVE);

    // TODO: support diacriticals (charCount == 2)
    if (charCount == 1)
    {
        keyChar = chars[0];
    }

    return keyChar;
}
Run Code Online (Sandbox Code Playgroud)