【问题标题】:Ctrl-S input event in Windows console with ReadConsoleInputW带有 ReadConsoleInputW 的 Windows 控制台中的 Ctrl-S 输入事件
【发布时间】:2017-02-03 08:38:26
【问题描述】:

我正在使用 ReadConsoleInputW 读取 Windows 10 控制台输入。我希望能够检测到何时按下 Ctrl+S。使用我拥有的代码,我可以检测到 Ctrl+Q 没有问题,但我没有看到任何 Ctrl+S Ctrl+S 甚至可以检测到吗?

下面是我按Ctrl+S几次后看到的INPUT_RECORD的序列,接着是Ctrl+

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 }

如果重要的话,这是在 Rust 中使用 wio

【问题讨论】:

  • 您使用的是哪个终端模拟器?你在用cmd.exe吗?电源外壳?像bash这样的东西?终端模拟器程序会拦截该组合键吗?
  • 您可以尝试使用SetConsoleMode 禁用ENABLE_PROCESSED_INPUT 吗?
  • 我正在使用cmd.exe。今晚我会尝试禁用ENABLE_PROCESSED_INPUT。谢谢。
  • 看来ENABLE_LINE_INPUT是罪魁祸首!请看我的回答。

标签: winapi rust console-application


【解决方案1】:

使用ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS 作为第二个参数调用SetConsoleMode(从而禁用ENABLE_PROCESSED_INPUT)就可以了。

【讨论】:

  • +1,因为您帮助我找到了解决方案。但是,我发现 ENABLE_PROCESSED_INPUT 不是罪魁祸首,请看我的回答。
【解决方案2】:

oconnor0 的回答帮助我找到了解决方案。

但是,我无法通过禁用 ENABLE_PROCESSED_INPUT 来获得 ctrl-s 事件,因此我尝试按照 oconnor0 的建议仅使用 ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS。这行得通,但这意味着ENABLE_PROCESSED_INPUT 不是罪魁祸首!

所以我尝试了:

//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();

禁用 ENABLE_ECHO_INPUT 会强制您禁用 ENABLE_ECHO_INPUT(请参阅 msdn),但这不是罪魁祸首,因为:

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

所以这意味着ENABLE_LINE_INPUT是罪魁祸首!

目前还不清楚为什么:

ENABLE_LINE_INPUT 0x0002 ReadFile 或 ReadConsole 函数返回 仅当读取回车符时。如果这种模式是 禁用,当出现一个或多个字符时,函数返回 可用。

【讨论】:

  • 显然 ENABLE_LINE_INPUT 做了 MS 没有记录的事情。
  • 通常我们不希望行编辑和历史记录用于低级读取。但是对于任何想要在行输入模式下正常阅读 Ctrl+S 的人,请在控制台默认值/属性中禁用扩展文本选择。这对应于“HKCU\Console”(或窗口标题子项)中的“ExtendedEditKey”DWORD 值。不幸的是,这也会禁用立即访问 Windows 10 中新的文本选择功能,例如 Shift+箭头键。相反,我们必须先通过 Ctrl+M 进入标记模式。
  • 应该选择这个作为答案。虽然我更喜欢它只是切入正题而不是审查所有不起作用的东西。通过 Ctrl+S 暂停控制台是禁用扩展编辑键的行输入模式的一项功能。以编程方式,控制台 API 只有粗粒度的控制来禁用行输入模式,但这对于我们需要它进行低级读取的大多数情况来说已经足够了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-10
  • 1970-01-01
  • 2011-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多