Windows console non-blocking mode

Sorry to derail the thread, but this is something I’ve been trying to figure out forever, with no success.

About the awaiting-a-single-character-mode, does anyone here have any idea how to get the Windows console into non-blocking read mode for stdin? In Posix we have file descriptors and stdin is FD 0, so we can do something like: fcntl(0, F_SETFL, O_NONBLOCK) and now stdin is non-blocking and we can poll it without hanging the program. Then just use cbreak or raw from curses so it’s sending input immediately instead of waiting for enter. This kind of setup seems perfect for roguelike games.

How the heck do you do this on Windows?

Apparently the Windows equivalent of the curses stuff is SetConsoleMode, but I’ve had no luck finding something equivalent to fcntl (there is something for sockets, but I’m not sure it’s useful).

IIRC Windows doesn’t have a mode like that. With SetConsoleMode you can clear the line mode and get individual characters with ReadConsole (I think?) but it still blocks until the user presses a key (which may be OK for you, or may not). There’s also a function ReadConsoleInput or something which doesn’t block but also returns mouse events and such, so you have to filter to get just the ones you want.

You used to be able to use _kbhit and _getch to read in a completely non-blocking way that’s more like the POSIX functions.

Damn, was afraid of that.

I vaguely remember trying kbhit and co, but not being satisfied for some reason… probably no support for modifier keys or something.

Ah well, Windows console is actually coming up to speed fast now (finally ANSI escape code support, woo). Maybe they’ll get that worked out in our lifetimes…

Maybe using PeekConsoleInput does what you want?

You should be able to do it with ReadConsoleInput and (as @borg323 says) PeekConsoleInput: it’s just a little bit more work because you have to filter out the focus and mouse events and such. The KEY_EVENT_RECORDs have modifier state and all that.

Hmm, it looks like those would work… apparently ReadConsoleInput will block if there’s nothing in the buffer, but you can check first with GetNumberOfConsoleInputEvents. Or it looks like PeekConsoleInput always returns immediately, and you can flush it afterwards with FlushConsoleInputBuffer. Also it looks like SetConsoleMode can be used to disable mouse/window input. Will try these out, thanks!