Skip to content

Instantly share code, notes, and snippets.

@asmichi
Created June 18, 2022 10:12
Show Gist options
  • Save asmichi/1b32730870384ae2712dbdc551b9f392 to your computer and use it in GitHub Desktop.
Save asmichi/1b32730870384ae2712dbdc551b9f392 to your computer and use it in GitHub Desktop.
ReadConsoleInput example
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <cassert>
#include <cstdio>
namespace
{
void PrintLastError(const char* name)
{
std::fprintf(stderr, "%s failed (%d)\n", name, GetLastError());
}
} // namespace
int main()
{
auto hStdInput = GetStdHandle(STD_INPUT_HANDLE);
if (hStdInput == INVALID_HANDLE_VALUE)
{
PrintLastError("GetStdHandle");
return 1;
}
// TODO: In production, the previous mode should be restored.
constexpr DWORD consoleMode =
ENABLE_PROCESSED_INPUT | // enable Ctrl+C
// ENABLE_LINE_INPUT |
// ENABLE_ECHO_INPUT |
ENABLE_WINDOW_INPUT |
ENABLE_MOUSE_INPUT |
// ENABLE_INSERT_MODE |
// // ENABLE_QUICK_EDIT_MODE |
// ENABLE_EXTENDED_FLAGS |
// ENABLE_VIRTUAL_TERMINAL_INPUT
0;
if (!SetConsoleMode(hStdInput, consoleMode))
{
PrintLastError("SetConsoleMode");
return 1;
}
while (true)
{
INPUT_RECORD r;
DWORD n;
if (!ReadConsoleInputW(hStdInput, &r, 1, &n))
{
PrintLastError("ReadConsoleInputW");
return 1;
}
assert(n == 1);
switch (r.EventType)
{
case KEY_EVENT:
{
// In a pseudo console, a key down event is immediately followed by a key up event, which is very natural since a PTY does not have the concept of "key up".
const auto& e = r.Event.KeyEvent;
std::printf(
"KeyEvent %d %d %d %d %d %d\n",
e.bKeyDown,
e.dwControlKeyState,
e.wVirtualKeyCode,
e.wVirtualScanCode,
e.wRepeatCount,
e.uChar.UnicodeChar);
break;
}
case MENU_EVENT:
// > These events are used internally and should be ignored.
break;
case MOUSE_EVENT:
{
// NOTE: need to disable the quick edit mode to receive mouse events
const auto& e = r.Event.MouseEvent;
std::printf(
"MouseEvent %d %d %d (%d, %d)\n",
e.dwButtonState,
e.dwControlKeyState,
e.dwEventFlags,
e.dwMousePosition.X,
e.dwMousePosition.Y);
break;
}
case FOCUS_EVENT:
// > These events are used internally and should be ignored.
break;
case WINDOW_BUFFER_SIZE_EVENT:
{
const auto& e = r.Event.WindowBufferSizeEvent;
std::printf(
"WindowBufferSizeEvent (%d, %d)\n",
e.dwSize.X,
e.dwSize.Y);
break;
}
default:
std::printf("Unknown Event %d\n", r.EventType);
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment