Here is how to make a non blocking call to stdin in windows by using the right API :
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
void ErrorExit(LPSTR);
void KeyEventProc(KEY_EVENT_RECORD ker);
// Global variables are here for example, avoid that.
DWORD fdwSaveOldMode;
HANDLE hStdin;
void printToCoordinates(int x, int y, char* text)
{
printf("\033[%d;%dH%s", y, x, text);
}
int main()
{
printf("\033[H\033[J");
int i = 0;
char* s = "*";
DWORD fdwMode, cNumRead;
INPUT_RECORD irInBuf[128];
DWORD bufferSize = 0;
hStdin = GetStdHandle(STD_INPUT_HANDLE);
// Just a check to ensure everything is fine at this state
if (hStdin==INVALID_HANDLE_VALUE){
printf("Invalid handle value.\n");
exit(EXIT_FAILURE);
}
// Just a check to ensure everything is fine at this state
if (! GetConsoleMode(hStdin, &fdwSaveOldMode) )
ErrorExit("GetConsoleMode");
// Those constants are documented on Microsoft doc
// ENABLE_PROCESSED_INPUT allows you to use CTRL+C
// (so it's not catched by ReadConsoleInput here)
fdwMode = ENABLE_WINDOW_INPUT | ENABLE_PROCESSED_INPUT;
if (! SetConsoleMode(hStdin, fdwMode) )
ErrorExit("SetConsoleMode");
while (i < 60) {
// The goal of this program is to print a line of stars
printToCoordinates(i, 5, s);
i++;
GetNumberOfConsoleInputEvents(hStdin, &bufferSize);
// ReadConsoleInput block if the buffer is empty
if (bufferSize > 0) {
if (! ReadConsoleInput(
hStdin, // input buffer handle
irInBuf, // buffer to read into
128, // size of read buffer
&cNumRead) ) // number of records read
ErrorExit("ReadConsoleInput");
// This code is not rock solid, you should iterate over
// irInBuf to get what you want, the last event may not contain what you expect
// Once again you'll find an event constant list on Microsoft documentation
if (irInBuf[cNumRead-1].EventType == KEY_EVENT) {
KeyEventProc(irInBuf[cNumRead-1].Event.KeyEvent);
Sleep(2000);
}
}
Sleep(100);
}
// Setting the console back to normal
SetConsoleMode(hStdin, fdwSaveOldMode);
CloseHandle(hStdin);
printf("\nFIN\n");
return 0;
}
void ErrorExit (LPSTR lpszMessage)
{
fprintf(stderr, "%s\n", lpszMessage);
// Restore input mode on exit.
SetConsoleMode(hStdin, fdwSaveOldMode);
ExitProcess(0);
}
void KeyEventProc(KEY_EVENT_RECORD ker)
{
printf("Key event: \"%c\" ", ker.uChar.AsciiChar);
if(ker.bKeyDown)
printf("key pressed\n");
else printf("key released\n");
}
Please notice this work in brand new Terminal application but not in CMD (due to termcaps used in the code) but it will compile and you can run it anyway.