An alternate to using getch()

OK, I have seen enough people suggesting the use of non-standard getch() or _getch().

Please, refrain from using the conio.h library as it is unreliable and non-standard. The conio.h of MSV C++ 08 differs hugely from the one in Mingw C.
Lots of functions in there like textcolor(), cprintf, etc., are deprecated and there are other alternatives to it.

Here, I shall post one such alternative to getch() which works using Win API.
Oh, it will only work on windows....
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <windows.h>
CHAR GetCh (VOID)
{
  HANDLE hStdin = GetStdHandle (STD_INPUT_HANDLE);
  INPUT_RECORD irInputRecord;
  DWORD dwEventsRead;
  CHAR cChar;

  while(ReadConsoleInputA (hStdin, &irInputRecord, 1, &dwEventsRead)) /* Read key press */
    if (irInputRecord.EventType == KEY_EVENT
	&&irInputRecord.Event.KeyEvent.wVirtualKeyCode != VK_SHIFT
	&&irInputRecord.Event.KeyEvent.wVirtualKeyCode != VK_MENU
	&&irInputRecord.Event.KeyEvent.wVirtualKeyCode != VK_CONTROL)
    {
      cChar = irInputRecord.Event.KeyEvent.uChar.AsciiChar;
	ReadConsoleInputA (hStdin, &irInputRecord , 1, &dwEventsRead); /* Read key release */
	return cChar;
    }
  return EOF;
}

The above code should work as it worked for me.

Suggestions and improvements are accepted. I am a tyro in this field.
Last edited on
Cool. getch() takes a char without echoing it, and without line-buffering (so you don't need to press enter), right?

You can use ncurses on UNIX/Linux or PDCurses on windows.
Well, I knew that getch() took a char and does not echo it, one could use getche() for echo.

I don't have PD Curses installed and <windows.h> is a standard windows header file anyway (I think).

Thanks for the input, PD Curses is a good idea. I'll have to install it though.
windows.h is a standard "windows" header file yes, but it's not standard to C++ but then neither is ncurses or pdcurses.

it would be better to suggest cin.ignore(1000,'\n'); in replace of it. or functions to replicate the pressing of a key written in a standard way.
Curses is a fantastic library for console I/O; it has more facilities than conio.h by far.
http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/

<windows.h> is a standard windows header file anyway (I think).

Not quite. windows.h is one of the windows API extensions; only compilers for windows have them, and they only work on windows. The C and C++ standard libraries (libc and libstdc++) are completely cross-platform. Each operating system adds it's own API (Application-Programming Interface), e.g. the windows API (win*.h) and POSIX API, the latter being the more extensive and, IMO, better of the two. The reason the POSIX-C API is better (IMO) is because it's a UNIX-based specification and C was created by two of the creators of UNIX (Brian Kernighan and Dennis Ritchie, with Ritchie being the actual designer of the language AFAIK); also it was influenced by the language B which was created by Ken Thompson, another of the creators of UNIX (he wrote and designed the original system). I also find e.g. the code you've written above unreadable; no offence to you, that's just my opinion on all these stupid typedefs (and typedef'ing a pointer is retarded; apparently anything with the prefix LP is a pointer (long pointer is my guess); what is wrong with having an asterisk? Every C/C++ programmer should recognise an asterisk in that context as meaning a pointer. Why would you remove that?).
curses is probably the easiest way to do it.
And windows is not standard. It's windows API but it's not standard.
To be fair, he DID say it only works on windows...
True. Didn't Duoas put up something like this a while back? I wonder what his opinion is of this.
@chrisname
I'm sorry you find that code unreadable. It did try to make it look better and it is fairly simple.
If you observer more carefully I did not use any pointer using the LP (Long pointer) or P prefix. But, I do agree it does look err... "retarded" haha. (your quote)
The typedefs I used are what the ReadConosleInputA expects.
If I hadn't used normal typedefs such as DWORD (usually unsigned long) it would have looked like some very unusual Win API code. It could possibly even have been incorrect.
Don't blame me, blame the guys who made the Win API as it is.

@gcamptom
I think you are mistaking my topic for something else (cin.ignore?). Please reread. This is about getch... and it is vastly different from cin.ignore.

@tummchow
Yes, Duoas has contributes a lot but I don't remember ever seeing a getch one. I should probably double check just to be sure.

And, Windows API will be there as long as there is a Windows Operating System. Most compilers, if not all, native to windows environment will provide for a standard Win API library. So, this code should work on almost any modern Windows compiler.

@To the rest
As far as my knowledge goes, the wonderful getch() from conio.h was mainly made to work with DOS and later Windows. So, obviously this code only works on Windows.
However, there is working version of getch() for UNIX also.

I originally posted this code to help those getch() users who are new to C/C++ after looking at so many pieces code that relies on the conio.h library. (conio.h is Windows specific)
Oh, that code may not work on all keyboards... (My bad)

I would have posted something for UNIX but it seems that would be unnecessary thanks to ncurses pointed out by chrisname.

P.S:
Long post eh? Sorry about all those grammar and spelling mistakes.
Also, my apologies to whomsoever I have offended. I was only trying to be helpful.
Last edited on
Like I said, it's only unreadable to me because WinAPI is unreadable to me. It's not your fault. I'm sure pure C++ code (that is, code written using only the language and the standard C++ library)) you write is perfectly readable., That was not an insult to you.

However, there is working version of getch() for UNIX also.

That's part of libcurses. The C stdio library has getc() and getchar(), however.
Topic archived. No new replies allowed.