问题
I'm developing a console application in which I need to detect several hotkeys such as Ctrl+N, Ctrl+O and Ctrl+S. Here's a part of the code that I use to recognize these hotkeys:
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)
{
//...
}
}
The code above works without any issues for Ctrl+N and Ctrl+O. But, I can't get it to work for Ctrl+S. After doing some quick testing, I found out that pressing Ctrl+S doesn't even do anything (meaning that the program is still waiting for the user to type something).
This issue only occurs with Ctrl+S. Using some simple if
statements for any other modifier (Shift for example) and key (N, O, etc) works fine.
Why does this happen? Is there a special meaning to the Ctrl+S combination? Is it possible to make this work? If yes, how?
回答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);
}
回答2:
With help from ThreeStarProgrammer57, I came up with this solution for my own console application.
You need to configure the console by using SetConsoleMode and passing "ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS
as suggested by oconnor0".
Import the needed kernel functions:
[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;
And use them in your program as following:
// 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)
{
//...
}
}
This solution will not only allow you to capture Ctrl+S keystrokes, but also Ctrl+C!
来源:https://stackoverflow.com/questions/39476157/detect-ctrl-s-in-console