Here's an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
#include <windows.h>
char pressanykey( const char *prompt )
{
DWORD mode;
HANDLE hstdin;
INPUT_RECORD inrec;
DWORD count;
char default_prompt[] = "Press the 'any' key...";
char result = '\0';
/* Set the console mode to no-echo, raw input, */
/* and no window or mouse events. */
hstdin = GetStdHandle( STD_INPUT_HANDLE );
if (hstdin == INVALID_HANDLE_VALUE
|| !GetConsoleMode( hstdin, &mode )
|| !SetConsoleMode( hstdin, 0 ))
return result;
if (!prompt) prompt = default_prompt;
/* Instruct the user */
WriteConsole(
GetStdHandle( STD_OUTPUT_HANDLE ),
prompt,
lstrlen( prompt ),
&count,
NULL
);
FlushConsoleInputBuffer( hstdin );
/* Wait for and get a single key PRESS */
do ReadConsoleInput( hstdin, &inrec, 1, &count );
while ((inrec.EventType != KEY_EVENT) || !inrec.Event.KeyEvent.bKeyDown);
/* Remember which key the user pressed */
result = inrec.Event.KeyEvent.uChar.AsciiChar;
/* Wait for and get a single key RELEASE */
do ReadConsoleInput( hstdin, &inrec, 1, &count );
while ((inrec.EventType != KEY_EVENT) || inrec.Event.KeyEvent.bKeyDown);
/* Restore the original console mode */
SetConsoleMode( hstdin, mode );
return result;
}
|
The DOS PAUSE command doesn't wait for the key release, but as a separate process that isn't a problem. For use in your own code, it is often best to wait for the key release too...
Also, while C and C++ streams don't define flush on input streams, the Win32 console
does. Hence line 30 to get rid of extraneous leftovers before beginning to wait for a key press.
I also added a return value to indicate which key was pressed...
Here's an example of how to use it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
/* ouch.c */
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
/* ...same stuff as above goes here... */
const char* messages[ 3 ] =
{
"Press the 'any' key...",
"\n\rAck! Not that one! Try again.",
"\n\rWoah! Watch it! Press the ANY key!"
};
int main()
{
int i;
char keys[ 4 ];
for (i = 0; i < 3; i++)
keys[ i ] = toupper( pressanykey( messages[ i ] ) );
keys[ 3 ] = '\0';
if (strcmp( keys, "ANY" ) == 0)
printf( "\nFinally! Thank you.\n" );
else
printf( "\nOh forget it!\n" );
printf( "\n\n\n\n\n" );
pressanykey( "Press any key to quit. (Seriously this time.)" );
return 0;
}
|
A DWORD is a "double-word", or 32-bit integer. The name "dword" usually implies unsigned. So in C it would be 'unsigned int'. The Windows API makes extensive use of typedefs like this to make sure that the correct size items are used when interfacing with system DLLs.
A HANDLE is just an integer that represents some resource controlled by Windows, such as an edit box, or a button, or a file, or a process, or memory, etc. It is essentially a magic number.
The link I gave you lists the kinds of flags you want to use with
SetConsoleMode(). Notice how in the example above I first saved the current console mode and last restored the console mode to its original state. In between I set the console mode to zero, or 'all flags off': unbuffered, no-echo, non-processed, keyboard-only input. Since the standard streams are (unless redirected) connected to the Windows console, modifying the console mode also appears to modify the function of
cin. (It doesn't, but since the console is affected the behavior of
cin reflects that.)
To test whether or not your standard stream is actually connected to a console, use
GetConsoleMode() and check the return value. If zero (or false) then the standard input is not connected to a console.
Hope this helps.