Skip to content

Instantly share code, notes, and snippets.

@magiblot
Last active February 24, 2025 14:15
Show Gist options
  • Save magiblot/318807a2a0f52f7fe63cf111d41504f7 to your computer and use it in GitHub Desktop.
Save magiblot/318807a2a0f52f7fe63cf111d41504f7 to your computer and use it in GitHub Desktop.
Windows Console/MS-DOS keyboard input tester

Windows Console/MS-DOS keyboard input tester

  • To build for Windows, any compiler can be used.
  • To build for MS-DOS, use Borland C++.
// Program to test keyboard input in the Windows Console or MS-DOS.
// To build for MS-DOS, use Borland C++.
#include <stdlib.h>
#include <stdio.h>
const unsigned short
kbCtrlC = 0x2e03;
static void init();
static void restore();
static int readKey(unsigned short &keyCode, unsigned short &controlKeyState);
int main()
{
init();
atexit(restore);
puts("Press Ctrl+C to exit");
unsigned long counter = 0;
unsigned short keyCode, controlKeyState;
do {
if (readKey(keyCode, controlKeyState))
printf("Event #%lu:\t{0x%04hx, 0x%04hx}\n", ++counter, keyCode, controlKeyState);
} while (keyCode != kbCtrlC);
return 0;
}
#if defined(_WIN32) || (defined(__BORLANDC__) && defined(__FLAT__))
#include <windows.h>
static DWORD oldConsoleMode;
static void init()
{
puts("Using Win32 Console API");
HANDLE console = GetStdHandle(STD_INPUT_HANDLE);
DWORD consoleMode;
if (!GetConsoleMode(console, &consoleMode))
{
printf("GetConsoleMode error: %lu\n", GetLastError());
exit(1);
}
oldConsoleMode = consoleMode;
consoleMode &= ~ENABLE_PROCESSED_INPUT; // Report Ctrl+C and Shift+Arrow events.
consoleMode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT); // Report Ctrl+S.
if (!SetConsoleMode(console, consoleMode))
{
printf("SetConsoleMode error: %lu\n", GetLastError());
exit(1);
}
}
static void restore()
{
HANDLE console = GetStdHandle(STD_INPUT_HANDLE);
if (!SetConsoleMode(console, oldConsoleMode))
{
printf("SetConsoleMode error: %lu\n", GetLastError());
exit(1);
}
}
static int readKey(unsigned short &keyCode, unsigned short &controlKeyState)
{
HANDLE console = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD irBuffer;
unsigned long eventsRead;
if (!ReadConsoleInput(console, &irBuffer, 1, &eventsRead))
{
printf("ReadConsoleInput error: %lu\n", GetLastError());
exit(1);
}
if (irBuffer.EventType != KEY_EVENT || !irBuffer.Event.KeyEvent.bKeyDown)
return 0;
keyCode = (irBuffer.Event.KeyEvent.wVirtualScanCode << 8) | (irBuffer.Event.KeyEvent.uChar.AsciiChar);
controlKeyState = (unsigned short) irBuffer.Event.KeyEvent.dwControlKeyState;
return 1;
}
#elif defined(__BORLANDC__) && defined(__MSDOS__)
#include <dos.h>
const unsigned biosSel = 0x0040;
const unsigned short far * const biosKeyShiftStatus =
(const unsigned short far *) MK_FP(biosSel, 0x17);
static void init()
{
puts("Using DOS interrupts");
}
static void restore()
{
}
int readKey(unsigned short &keyCode, unsigned short &controlKeyState)
{
_AH = 0x10; // Get extended keystroke.
geninterrupt(0x16);
keyCode = _AX;
controlKeyState = *biosKeyShiftStatus;
return 1;
}
#else
#error Unknown system. MS-DOS (with Borland C++) or Win32 are supported.
#endif
@magiblot
Copy link
Author

Prebuilt executables (built with Borland C++ 4.52): https://github.com/user-attachments/files/18907005/keytest.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment