Обнаружить Ctrl + S в консоли

Я разрабатываю консольное приложение, в котором мне нужно обнаружить несколько горячих клавиш, таких как Ctrl + N, Ctrl + O и Ctrl + S. Вот часть кода, который я использую для распознавания этих горячих клавиш:

ConsoleKeyInfo input = Console.ReadKey(true);

if (input.Modifiers == ConsoleModifiers.Control)
{
    if (input.Key == ConsoleKey.N)
    {
        // ...
    }
    else if (input.Key == ConsoleKey.O)
    {
        // ...
    }
    else if (input.Key == ConsoleKey.S)
    {
        //...
    }
}

Приведенный выше код работает без проблем для Ctrl + N и Ctrl + O. Но я не могу заставить его работать для Ctrl + S. Проведя небольшое тестирование, я обнаружил, что нажатие Ctrl + S даже ничего не делает (это означает, что программа все еще ждет, пока пользователь что-то напечатает).

Эта проблема возникает только при использовании Ctrl + S. Использование простых операторов if для любого другого модификатора (например, Shift) и ключа (N, O и т. Д.) Работает нормально.

Почему это происходит? Есть ли особое значение в комбинации Ctrl + S? Можно ли заставить это работать? Если да, то как?


person OC_    schedule 13.09.2016    source источник
comment
CTRL-S перехватывается консольной программой для приостановки вывода. Вот почему он не передается в ваше приложение. Не знаю как отключить.   -  person Some programmer dude    schedule 13.09.2016
comment
Я тоже нашел это: stackoverflow.com/a/9951471/2524589   -  person KSib    schedule 13.09.2016


Ответы (2)


С помощью ThreeStarProgrammer57 я придумал это решение для своего собственного консольного приложения.

Вам необходимо настроить консоль, используя SetConsoleMode и передав "ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS как было предложено oconnor0 ".

Импортируйте необходимые функции ядра:

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
[Flags]
private enum ConsoleInputModes : uint
{
    ENABLE_PROCESSED_INPUT = 0x0001,
    ENABLE_LINE_INPUT = 0x0002,
    ENABLE_ECHO_INPUT = 0x0004,
    ENABLE_WINDOW_INPUT = 0x0008,
    ENABLE_MOUSE_INPUT = 0x0010,
    ENABLE_INSERT_MODE = 0x0020,
    ENABLE_QUICK_EDIT_MODE = 0x0040,
    ENABLE_EXTENDED_FLAGS = 0x0080,
    ENABLE_AUTO_POSITION = 0x0100
}

[Flags]
private enum ConsoleOutputModes : uint
{
    ENABLE_PROCESSED_OUTPUT = 0x0001,
    ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002,
    ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004,
    DISABLE_NEWLINE_AUTO_RETURN = 0x0008,
    ENABLE_LVB_GRID_WORLDWIDE = 0x0010
}

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
static int STD_INPUT_HANDLE = -10;

И используйте их в своей программе следующим образом:

// Add this section to your code:
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), (uint)(
    ConsoleInputModes.ENABLE_WINDOW_INPUT |
    ConsoleInputModes.ENABLE_MOUSE_INPUT  |
    ConsoleInputModes.ENABLE_EXTENDED_FLAGS
));
// ------------------------------

ConsoleKeyInfo input = Console.ReadKey(true);

if (input.Modifiers == ConsoleModifiers.Control)
{
    if (input.Key == ConsoleKey.N)
    {
        // ...
    }
    else if (input.Key == ConsoleKey.O)
    {
        // ...
    }
    else if (input.Key == ConsoleKey.S)
    {
        //...
    }
}

Это решение не только позволит вам захватывать нажатия клавиш Ctrl + S, но также Ctrl + C!

person William R.    schedule 05.11.2019

person    schedule
comment
Как это должно называться? Откуда взялись msg и keyData? - person William R.; 26.10.2019