在控制台中检测 Ctrl + S

Posted

技术标签:

【中文标题】在控制台中检测 Ctrl + S【英文标题】:Detect Ctrl + S in Console 【发布时间】:2016-09-13 17:50:04 【问题描述】:

我正在开发一个控制台应用程序,我需要在其中检测几个热键,例如 Ctrl+NCtrl+ OCtrl+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+NCtrl+O 没有任何问题。但是,我无法让它为 Ctrl+S 工作。在做了一些快速测试之后,我发现按下 Ctrl+S 甚至没有做任何事情(意味着程序仍在等待用户输入内容)。

只有 Ctrl+S 才会出现此问题。对任何其他修饰符(例如 Shift)和键(NO 等)使用一些简单的 if 语句都可以正常工作。

为什么会这样? Ctrl+S组合有什么特殊含义吗?有可能完成这项工作吗?如果是,怎么做?

【问题讨论】:

CTRL-S 被控制台程序捕获以暂停输出。这就是为什么它不会传递给您的应用程序的原因。我不知道如何禁用它。 我也发现了这个:***.com/a/9951471/2524589 【参考方案1】:
protected override  bool  ProcessCmdKey(ref Message msg, Keys keyData)

    if (msg.Msg == 256)
    
        //if the user pressed control + s
        if (keyData == (Keys.Control | Keys.S))
        

        
        //if the user pressed control + o 
        else if (keyData == (Keys.Control | Keys.O))
        

        
        //if the user pressed control + n 
        else if (keyData == (Keys.Control | Keys.N))
        

        
    
    return base.ProcessCmdKey(ref msg, keyData);

【讨论】:

这应该怎么称呼? msgkeyData 来自哪里?【参考方案2】:

在ThreeStarProgrammer57 的帮助下,我为自己的控制台应用程序提出了这个解决方案。

您需要使用SetConsoleMode 并按照oconnor0 的建议传递ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS”来配置控制台

导入需要的内核函数:

[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

【讨论】:

以上是关于在控制台中检测 Ctrl + S的主要内容,如果未能解决你的问题,请参考以下文章

在 MouseDown 事件处理程序中检测 Ctrl+Left(鼠标按钮)

14图像边缘检测的sobel_ctrl控制模块

14图像边缘检测的sobel_ctrl控制模块

在 CEdit::OnChar 中检测 CTRL 并测试 nChar 值?

解决远程登陆Linux误按ctrl+s锁屏

R语言客户端RStudio快捷键大全