3

I am using ReadConsoleInputW to read Windows 10 console input. I want to be able to detect when Ctrl+S is pressed. Using the code I have, I can detect Ctrl+Q without issue, but I'm not seeing anything for Ctrl+S. Is Ctrl+S even detectable?

The below is the sequence of INPUT_RECORD I read when pressing Ctrl+S a few times, followed by Ctrl+Q.

Key { key_down: true, repeat_count: 1, key_code: 17, scan_code: 29, wide_char: 0, control_key_state: 40 }
Key { key_down: true, repeat_count: 1, key_code: 17, scan_code: 29, wide_char: 0, control_key_state: 40 }
Key { key_down: true, repeat_count: 1, key_code: 17, scan_code: 29, wide_char: 0, control_key_state: 40 }
Key { key_down: true, repeat_count: 1, key_code: 17, scan_code: 29, wide_char: 0, control_key_state: 40 }
Key { key_down: true, repeat_count: 1, key_code: 17, scan_code: 29, wide_char: 0, control_key_state: 40 }
Key { key_down: true, repeat_count: 1, key_code: 17, scan_code: 29, wide_char: 0, control_key_state: 40 }
Key { key_down: true, repeat_count: 1, key_code: 17, scan_code: 29, wide_char: 0, control_key_state: 40 }
Key { key_down: true, repeat_count: 1, key_code: 17, scan_code: 29, wide_char: 0, control_key_state: 40 }
Key { key_down: true, repeat_count: 1, key_code: 81, scan_code: 16, wide_char: 17, control_key_state: 40 }

If it matters, this is in Rust using wio.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
oconnor0
  • 3,154
  • 6
  • 34
  • 52
  • 1
    Which terminal emulator are you using? Are you using `cmd.exe`? Powershell? Something like bash? Could the terminal emulator program be intercepting that key combo? – Shepmaster Sep 26 '16 at 12:39
  • 2
    Can you try to disable `ENABLE_PROCESSED_INPUT` using [`SetConsoleMode`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx)? – wimh Sep 26 '16 at 13:21
  • I'm using `cmd.exe`. I'll try disabling `ENABLE_PROCESSED_INPUT` tonight. Thanks. – oconnor0 Sep 26 '16 at 14:18
  • It seems that `ENABLE_LINE_INPUT` is the culprit! Please see my answer. – ThreeStarProgrammer57 Feb 14 '18 at 00:51

2 Answers2

3

Calling SetConsoleMode with ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS as the second argument (thus disabling ENABLE_PROCESSED_INPUT) did the trick.

oconnor0
  • 3,154
  • 6
  • 34
  • 52
2

oconnor0's answer helped me find the solution.

However, I could not get ctrl-s event by disabling ENABLE_PROCESSED_INPUT, so I tried using only ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS as suggested by oconnor0. This worked, but this means ENABLE_PROCESSED_INPUT is not the culrpit!

So I tried:

//This didn't work
if (!GetConsoleMode(hConsoleInput, &lpMode)) Error();
lpMode &= ~(ENABLE_PROCESSED_INPUT);
if (!SetConsoleMode(hConsoleInput, lpMode)) Error();

//This worked
if (!GetConsoleMode(hConsoleInput, &lpMode)) Error();
lpMode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
if (!SetConsoleMode(hConsoleInput, lpMode)) Error();

Disabling ENABLE_ECHO_INPUT forces you to disable ENABLE_ECHO_INPUT (see msdn), but it isn't the culprit because:

//This didn't work either
if (!GetConsoleMode(hConsoleInput, &lpMode)) Error();
lpMode &= ~(ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT);
if (!SetConsoleMode(hConsoleInput, lpMode)) Error();

So this means that ENABLE_LINE_INPUT is the culprit!

It's not clear why though:

ENABLE_LINE_INPUT 0x0002 The ReadFile or ReadConsole function returns only when a carriage return character is read. If this mode is disabled, the functions return when one or more characters are available.

ThreeStarProgrammer57
  • 2,906
  • 2
  • 16
  • 24
  • Clearly the ENABLE_LINE_INPUT does things that are not documented by MS. – Peter Camilleri Nov 02 '18 at 17:52
  • 1
    Normally we wouldn't want line editing and history for a low-level read anyway. But for anyone who wants to read Ctrl+S normally with line-input mode, disable extended text selection in the console defaults / properties. This corresponds to the "ExtendedEditKey" DWORD value in "HKCU\Console" (or a window-title subkey). Unfortunately this also disables immediate access to the new text selection features in Windows 10, such as Shift+ArrowKeys. Instead we have to first enter mark mode via Ctrl+M. – Eryk Sun Mar 19 '19 at 07:36
  • This should be selected as the answer. Though I'd prefer if it simply cut to the chase instead of reviewing everything that doesn't work. Pausing the console via Ctrl+S is a feature of line-input mode with extended editing keys disabled. Programmatically the console API only has the course-grained control to disable line-input mode, but that's good enough for most cases where we need this for a low-level read. – Eryk Sun Mar 19 '19 at 07:42