Created
June 18, 2022 10:12
-
-
Save asmichi/1b32730870384ae2712dbdc551b9f392 to your computer and use it in GitHub Desktop.
ReadConsoleInput example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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