Getting a keystroke without Pressing Enter

I have made a simple Hangman like Game.
I wanted to know how to make the console know when an alphabet key is pressed and for it to continue without the user having to press enter.

I am using Windows 7 OS and MS VC++ Express compiler.

Any Help?
You can use Windows API the function SetWindowsHookEx and hook the keyboard so you can detect every key when it's pressed.
Could you elaborate?
I don't know about Win API
There is no standard C/C++ function for this. But for Windows, you can use the CRT's _getch() function. See MSDN for information - http://msdn.microsoft.com

There is no need to go near Windows hooking for a simple console game!

If you search this siite for "getch" you find a number of forum articles discussing its use.

Andy

P.S. In older version of VC the function was just getch(). But they tidied up the name of all non-standard function by adding a _ prefix when the compiler was made fully standard compliant.
Thanks. _getch() did it.
None-the-less, could you tell me what is Windows Hooking?

EDIT:
I was using the Windows specific way described in(I didn't understand it though, just copied the code) :
http://www.cplusplus.com/forum/articles/7312/#msg33734

If I am using _getch() it is for some reason not pausing at the call to PressAnyKey("")

Any other way to do the get the character?
Last edited on
PressAnyKey() is not relevant here. I meant you should just use _getch() (and probably _kbhit())

A modified version of the example in the MSDN entry for _getch(). You need to work with all letters (plus return key, etc) rather than Y and N.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <conio.h>
#include <ctype.h>

int main( void )
{
   int ch;

   _cputs( "Do you want to use _getch()?\n" );
   _cputs( "Y for Yes or N for No : " );

   do
   {
      ch = _getch();
      ch = toupper( ch );
   } while( ch != 'Y' && ch != 'N' );

   _putch( ch );
   _putch( '\r' );    // Carriage return
   _putch( '\n' );    // Line feed  
}
PressAnyKey() is not relevant here.

I had been using PressAnyKey() for a long time. I have defined it in a header file along with a number of other functions. I was hoping to make _getch() work without disturbing those functions.

But why should it disturb PressAnyKey() any way?
From: http://msdn.microsoft.com/en-us/library/ms644959(v=VS.85).aspx

Hooks Overview

A hook is a mechanism by which an application can intercept events, such as messages, mouse actions, and keystrokes. A function that intercepts a particular type of event is known as a hook procedure. A hook procedure can act on each event it receives, and then modify or discard the event.


I have only ever used hooking for debug purposes. For example, installing a mouse hook to record the mouse messages for an application, so they can be replayed later. There are test tools which can do this, but some situations a simple text, which tests a specific GUI, can be simpler to use.
The reference to Windows Hooks really was not warranted here... a hook is a way of monitoring the keyboard outside the current thread, and is not designed for normal keyboard input.

The PressAnyKey() function does the same thing that the _getch() function does, but I imagine that it does it in a way incompatible with my function. You could easily use one or the other to do the same job.

However, what you really want is what is called unbuffered input. My function shows you how to do that in Windows. You may want to just turn off buffering in order to get input for your game. Here's how it is done using the Windows API:

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
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <ciso646>
#include <ctime>
#include <iostream>
#include <windows.h>
using namespace std;

int readkey()
  {
  HANDLE hstdin = GetStdHandle( STD_INPUT_HANDLE );
  DWORD  mode;
  GetConsoleMode( hstdin, &mode );
  SetConsoleMode( hstdin, 0 );

  INPUT_RECORD inrec;
  DWORD        count;

  do ReadConsoleInput( hstdin, &inrec, 1, &count );
  while ((inrec.EventType != KEY_EVENT) || inrec.Event.KeyEvent.bKeyDown);

  SetConsoleMode( hstdin, mode );

  return inrec.Event.KeyEvent.wVirtualKeyCode;
  }

inline int abs( int a )
  {
  return (a < 0) ? -a : a;
  }

int main()
  {
  srand( time( NULL ) );
  char letter = 'A' + (rand() % 26);

  cout << "I'm thinking of a letter in the alphabet.\n"
          "I'll give you three chances to guess what it is.\n";
  for (unsigned n = 1; n <= 3; n++)
    {
    cout << "Guess " << n << "> ";
    int c = readkey();

    if ((c < 'A') or (c > 'Z'))
      {
      cout << "That was not a letter!\n";
      continue;
      }

    cout << (char)c;

    if (c == letter) 
      {
      cout << "\nVery good! You guessed the letter " << letter << "!\n";
      return 0;
      }

    cout << "  You are off by " << abs( c - letter ) << ".\n";
    }

  cout << "Alas, you did not guess the letter " << letter << ".\n";
  return 0;
  }

You may also find the function iskeypressed() to be useful.
http://www.cplusplus.com/forum/beginner/5619/#msg25047

Hope this helps.
I always use getch()

but _getch()?

Whats the difference?
I only posted the reference to Windows hooking in response to a specific question. Unfortunately it was suggested by an earlier poster; it is definitely overkill here!

But then I think that anything other than a simple _getch loop is overkill for a simple hangman game.
This is Duoas code with the readkey() replaced by _getch() followed by toupper(). It just carried on working.

I also removed the unnecessary headers and also <ciso646>, which was needed for one logcial test (so far I have never seen this header used in commercial code)

I also removed the custom abs() -- the standard version is now being used (note that the compiler treats abs, fabs, strlen, ... specially -- for the release build -- inserting intrisic code for these operations. See MSDN documentation on /Oi compiler switch).

The hash defines are to shut up warnings, etc.

The advantage of the _getch() version is that it should compile with just VC Express alone (without the platform SDK). Unless the latest Express versions are bundled with the SDK?

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
#define _USE_32BIT_TIME_T
#define _CRT_SECURE_NO_WARNINGS
#include <ctime>
#include <iostream>
#include <conio.h>
using namespace std;

int main()
  {
  srand( time( NULL ) );
  char letter = 'A' + (rand() % 26);

  cout << "I'm thinking of a letter in the alphabet.\n"
          "I'll give you three chances to guess what it is.\n";
  for (unsigned n = 1; n <= 3; n++)
  {
    cout << "Guess " << n << "> ";
    char c = _getch();
    c = toupper(c);

    if ((c < 'A') || (c > 'Z'))
    {
      cout << "That was not a letter!\n";
      continue;
    }

    cout << (char)c;

    if (c == letter) 
    {
      cout << "\nVery good! You guessed the letter " << letter << "!\n";
      return 0;
    }

    cout << "  You are off by " << abs( c - letter ) << ".\n";
    }

  cout << "Alas, you did not guess the letter " << letter << ".\n";
  return 0;
  }
I also removed the unnecessary headers and also <ciso646>, which was needed for one logcial test (so far I have never seen this header used in commercial code)
Exactly which headers did I 'unnecessarily' include?

According to the Standard, the <ciso646> header is supposed to be empty, but in actual practice some compilers require you to #include it to use operator synonyms, which I have a habit of using. (Whether or not you consider that a good thing is another issue, which you did not address. I don't frankly care what your experience is with commercial code -- particularly considering the poor quality of a large portion of commercial code.)

I also removed the custom abs() -- the standard version is now being used
For which you'll need to #include one of <cmath> or <cstdlib>...

(note that the compiler treats abs, fabs, strlen, ... specially -- for the release build -- inserting intrisic code for these operations. See MSDN documentation on /Oi compiler switch).
The custom abs() works fine, and it only exists to make code more readable. Any conforming compiler can get you your "intrinsic" crap for a non-issue optimization. (I suspect you don't really know what MS means by the word intrinsic.)

The hash defines are to shut up warnings, etc.
...which only exist with MS compilers, as MS has deprecated so many standard functions. Nevertheless, it is good to remind us, particularly as it doesn't hurt anything to put them there.

Unless the latest Express versions are bundled with the SDK?
Since 2008.

Though, honestly, I always forget that the older VC Express versions don't come bundled with the Windows SDK, but it has always been possible to add it easily enough. The nice thing about that is that it is much more portable across Windows compilers than <conio.h>.


I had issue because your commentary borders on abusive. If I have actually made an error somewhere, then post it. But it shows poor taste to assert your position superior with snide commentary about my code. So, having said my fill, I'm off to just carry on working.
you can use GetAsyncKeyState function but i think this is not good but return any key push down ID !!!! this is a api function
@Douas: Thanks a lot! This did the work without effecting PressAnyKey()
By the way, what is the point of having <ciso646> header, if it is empty?

@andywestken:
Thanks for the help!
closed account (zwA4jE8b)
actually with GetAsyncKeyState() you must use a parameter. The parameter is the key you want to check for. It does not read any key pressed.

portion of my code
1
2
3
4
5
6
7
8
9
10
const DWORD _up = 0x57, _down = 0x53, _left = 0x41, _right = 0x44, _pause = 0x50,
			_yes = 0x59, _no = 0x4E, _esc = 0x1B;
......
if(GetAsyncKeyState(_yes))
			{
				_level = 1;
				_score = 0;
				_state = 'r';
				break;
			}
no not necessary you can put this function in the loop and check any key is pressed ! almost all of keylogger use this function
Duoas - I apologise for the tone of my mail. My aim was to make further my case for _getch() -- that with Visual Studio you could avoid the dependency on windows.h for the OP's task -- which I still believe is the right choice. The comments were in no way intended to be snide; they were just a (overly blunt?) statement of what I did.

It was only because the OP stated he was using a Microsoft compiler that included the #defines.

I didn't actually criticise the quality of your code. I just said I changed the readkey() replaced by _getch() followed by toupper() (and it just carried on working)

I used "unnecessary" in the sense "no longer necessary", after I had altered the code to use _getch (the headers I was referring to were windows.h and ciso646; I retrospectively added the comment about the latter header.) I mistakenly thought this would be clear in context.

And yes, I must get into the habit of explicitly including <ctsdlib>. It's a bad habit I've picked from too much VC++ (I assume the VC++ <iostream> is including it?)

But as far as I know, "intrinsic" is nothing to do with Microsoft. It is a synonym for "built in" or "fundamental" and is common enough in C++ literature; Did I assume wrongly that I could use the term without clarification?

Andy
I am also sorry for being so angry...

"Intrinsic" is a term to mean that <something> is built-into the compiler, meaning that the compiler will automatically inline functions like abs(), etc without actually needing the source code. Most <your favorite compiled language> compilers use intrinsics optimizations. So you are correct and my attack (sorry for that!) was based on the thought that you were abusing my code. For the given function, and barring something extra-special/weird in the CPU instruction set, any good optimizer will produce the same code...

Thank you for clarifying your intent. Sorry I was so grouchy..

:-(
Topic archived. No new replies allowed.