C++ _getch() read multiple values - c++

#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
int main()
{
int c = 0;
while (c != 27) //esc key code
{
c = 0;
switch (c = _getch())
{
case KEY_UP:
cout << endl << "Up" << endl;//key up
break;
case KEY_DOWN:
cout << endl << "Down" << endl; // key down
break;
case KEY_LEFT:
cout << endl << "Left" << endl; // key left
break;
case KEY_RIGHT:
cout << endl << "Right" << endl; // key right
break;
default:
cout << endl << "null" << endl;
break;
}
}
return 0;
}
The output should be
Up
Down
Left
Right
But what I get is
null
Up
null
Down
null
Left
null
Right
Based on the output, the program will read in other key code which I have no idea what is that before reading the actual key code, I didn't have any cin before this, why? any solution?

Had you chosen to read the fine manual, you would have encountered this statement:
When reading a function key or an arrow key, each function must be called twice; the first call returns 0 or 0xE0, and the second call returns the actual key code.
That's how you can tell when 72 means arrow-up and when it's the letter H (which happens to have an ASCII code of 72).

Changes made:
I removed default from the switch statement. It was causing the null prints.
Furthermore I've also added kbhit() and #define KEY_ESC 27, and moved getch() to ouside of the switch statement.
#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define KEY_ESC 27
#include <conio.h>
#include <stdio.h>
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
int c = 0;
while ( c!= KEY_ESC ) //esc key code is 27
{
if (kbhit()) {
c = getch();
switch ( c )
{
case KEY_UP:
cout << endl << "Up" << endl;//key up
break;
case KEY_DOWN:
cout << endl << "Down" << endl; // key down
break;
case KEY_LEFT:
cout << endl << "Left" << endl; // key left
break;
case KEY_RIGHT:
cout << endl << "Right" << endl; // key right
break;
}//switch
}//if
}//while
return 0;
}

Related

Arrow key Input without pausing console [duplicate]

I have been having a problem with detecting arrow key presses in my C++ console application. I have tried everything I have found, both here and on other tutorial sites, but all of them give me the same thing whenever I press the arrow:
Process returned 0 <0x0> execution time : 2.249 s
Press any key to continue.
Here are all the methods of detecting the key press that I have tried, all ending up the same way. These are the only two left in my code, the others I attempted I deleted instead of commenting out.
Method one:
c1 = getch();
if(c1 == 0)
{
c2 = getch();
if(c2 == 72) {cout << endl << "Up Arrow" << endl;}
else if(c2 == 80) {cout << endl << "Down Arrow" << endl;}
else{cout << endl << "Incorrect Input" << endl;}
}
Method two:
switch(getch()) {
case 65:
cout << endl << "Up" << endl;//key up
break;
case 66:
cout << endl << "Down" << endl; // key down
break;
case 67:
cout << endl << "Right" << endl; // key right
break;
case 68:
cout << endl << "Left" << endl; // key left
break;
}
Is there some error in my code which made me go back to my main method, or did it skip over some code? Is there a faster way to do this? I'm almost 100% sure that my other code doesn't have anything to do with this problem, because I isolated the code from be dependent on any other aspect of the program, and I kept having the same problem.
Again, I tried every method of getting the arrow key press that I could find, and I keep getting the same problem. If it matters, I'm on a Windows 8 Samsung ATIV Smart PC and using the keyboard dock.
Thanks in advance for any help.
#include <conio.h>
#include <iostream>
using namespace std;
#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
int main()
{
int c = 0;
while(1)
{
c = 0;
switch((c=getch())) {
case KEY_UP:
cout << endl << "Up" << endl;//key up
break;
case KEY_DOWN:
cout << endl << "Down" << endl; // key down
break;
case KEY_LEFT:
cout << endl << "Left" << endl; // key left
break;
case KEY_RIGHT:
cout << endl << "Right" << endl; // key right
break;
default:
cout << endl << "null" << endl; // not arrow
break;
}
}
return 0;
}
output like this:
Up
Down
Right
Left
Up
Left
Right
Right
Up
detected arrow key press!
The previous answer by arbboter is close but neglects the fact the arrow keys (and other special keys) return a scan code of two characters. The first is either (0) or (224) indicating the key is an extended one; the second contains the scan code value.
Without accounting for this, the ASCII values for "H", "K", "M", and "P" are misinterpreted as "Up", "Down", "Left", and "Right".
Here's a modified version of arbboter's code to demonstrate reading the extended value when one of the arrow keys is pressed:
#include <conio.h>
#include <iostream>
using namespace std;
#define KEY_UP 72
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define KEY_DOWN 80
int main()
{
int c, ex;
while(1)
{
c = getch();
if (c && c != 224)
{
cout << endl << "Not arrow: " << (char) c << endl;
}
else
{
switch(ex = getch())
{
case KEY_UP /* H */:
cout << endl << "Up" << endl;//key up
break;
case KEY_DOWN /* K */:
cout << endl << "Down" << endl; // key down
break;
case KEY_LEFT /* M */:
cout << endl << "Left" << endl; // key left
break;
case KEY_RIGHT: /* P */
cout << endl << "Right" << endl; // key right
break;
default:
cout << endl << (char) ex << endl; // not arrow
break;
}
}
}
return 0;
}
// Example for inputting a single keystroke in C++ on Linux
// by Adam Pierce <adam#doctort.org> on http://www.doctort.org/adam/nerd-notes/reading-single-keystroke-on-linux.html
// This code is freeware. You are free to copy and modify it any way you like.
// Modify by me Putra Kusaeri
#include <iostream>
#include <termios.h>
#define STDIN_FILENO 0
using namespace std;
int main()
{
// Black magic to prevent Linux from buffering keystrokes.
struct termios t;
tcgetattr(STDIN_FILENO, &t);
t.c_lflag &= ~ICANON;
tcsetattr(STDIN_FILENO, TCSANOW, &t);
// Once the buffering is turned off, the rest is simple.
cout << "Enter a character: ";
char c,d,e;
cin >> c;
cin >> d;
cin >> e;
cout << "\nYour character was ";
// Using 3 char type, Cause up down right left consist with 3 character
if ((c==27)&&(d==91)) {
if (e==65) { cout << "UP";}
if (e==66) { cout << "DOWN";}
if (e==67) { cout << "RIGHT";}
if (e==68) { cout << "LEFT";}
}
return 0;
}
reference
Here is an alternate way to do it without getch() using events (well commented and i tried to make it as simple as i could)
#include <iostream>
#include <Windows.h>
int main(int argc, char *argv[]){
HANDLE rhnd = GetStdHandle(STD_INPUT_HANDLE); // handle to read console
DWORD Events = 0; // Event count
DWORD EventsRead = 0; // Events read from console
bool Running = true;
//programs main loop
while(Running) {
// gets the systems current "event" count
GetNumberOfConsoleInputEvents(rhnd, &Events);
if(Events != 0){ // if something happened we will handle the events we want
// create event buffer the size of how many Events
INPUT_RECORD eventBuffer[Events];
// fills the event buffer with the events and saves count in EventsRead
ReadConsoleInput(rhnd, eventBuffer, Events, &EventsRead);
// loop through the event buffer using the saved count
for(DWORD i = 0; i < EventsRead; ++i){
// check if event[i] is a key event && if so is a press not a release
if(eventBuffer[i].EventType == KEY_EVENT && eventBuffer[i].Event.KeyEvent.bKeyDown){
// check if the key press was an arrow key
switch(eventBuffer[i].Event.KeyEvent.wVirtualKeyCode){
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN: // if any arrow key was pressed break here
std::cout<< "arrow key pressed.\n";
break;
case VK_ESCAPE: // if escape key was pressed end program loop
std::cout<< "escape key pressed.\n";
Running = false;
break;
default: // no handled cases where pressed
std::cout<< "key not handled pressed.\n";
break;
}
}
} // end EventsRead loop
}
} // end program loop
return 0;
}
(Thanks to a commenter I now know this code is not standard, though it will work if you compile with g++, more info in the comments)
Some of the answers given here are not considering the fact that on pressing an arrow key, 2 characters are received. Additionally, it is to be noted that input character should be unsigned char. This is because to determine if an arrow key was pressed, we use ASCII value 224, which can only be stored in an 8-bit character (unsigned char) and not the 7-bit signed char.
You can use below code snippet. 2 types of inputs are processed here. ch1 is the 1st character that user enters. This is the input that user is feeding. But in case of arrow keys, a sequence of 2 characters are received ch1 and ch2. ch1 identifies that some arrow key was pressed, ch2 determines the specific arrow key pressed.
const int KEY_ARROW_CHAR1 = 224;
const int KEY_ARROW_UP = 72;
const int KEY_ARROW_DOWN = 80;
const int KEY_ARROW_LEFT = 75;
const int KEY_ARROW_RIGHT = 77;
unsigned char ch1 = _getch();
if (ch1 == KEY_ARROW_CHAR1)
{
// Some Arrow key was pressed, determine which?
unsigned char ch2 = _getch();
switch (ch2)
{
case KEY_ARROW_UP:
// code for arrow up
cout << "KEY_ARROW_UP" << endl;
break;
case KEY_ARROW_DOWN:
// code for arrow down
cout << "KEY_ARROW_DOWN" << endl;
break;
case KEY_ARROW_LEFT:
// code for arrow right
cout << "KEY_ARROW_LEFT" << endl;
break;
case KEY_ARROW_RIGHT:
// code for arrow left
cout << "KEY_ARROW_RIGHT" << endl;
break;
}
}
else
{
switch (ch1)
{
// Process other key presses if required.
}
}
Check http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx and http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
#include<windows.h>
#include <stdio.h>
int main()
{
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
DWORD NumInputs = 0;
DWORD InputsRead = 0;
bool running = true;
INPUT_RECORD irInput;
GetNumberOfConsoleInputEvents(hInput, &NumInputs);
ReadConsoleInput(hInput, &irInput, 1, &InputsRead);
switch(irInput.Event.KeyEvent.wVirtualKeyCode)
{
case VK_ESCAPE:
puts("Escape");
break;
case VK_LEFT:
puts("Left");
break;
case VK_UP:
puts("Up");
break;
case VK_RIGHT:
puts("Right");
break;
case VK_DOWN:
puts("Down");
break;
}
}
#include <iostream>
#include <conio.h>
const int KB_UP = 72;
const int KB_DOWN = 80;
const int KB_RIGHT = 77;
const int KB_LEFT = 75;
const int ESC = 27;
int main() {
while (true) {
int ch = _getch();
if (ch == 224) {
ch = _getch();
switch (ch) {
case KB_UP:
std::cout << "up\n";
break;
case KB_DOWN:
std::cout << "down\n";
break;
case KB_RIGHT:
std::cout << "right\n";
break;
case KB_LEFT:
std::cout << "left\n";
break;
default: std::cout << "unknown\n";
}
}
else if (ch == ESC)
{
std::cout << "Escape pressed, going out!\n";
break;
}
}
}
This is very simular to some example above except that I used
_getchar()
instead of
getchar()
that visual studio (which I use to write and run my cod)
gives error about,
and I also put it in a loop till you press Escape bottom.

Getch in combination with while-loop triggers loopcontent twice

I'm not really a programmer so my knownledge is extremely limited, I'm just hoping to get a very basic program working for a project. I've been googling around a lot and from what I've found I'm guessing it has to do with getch reading blank spaces or new lines as an input or something along those lines. None of the solutions I have found seem to fix the issue for me however (I might be implementing them wrong though).
This is in the main function:
while (roundNum <= 20)
{
roundNum++;
cout << roundNum / 2 << endl;
arrowKey();
}
And the arrowKey function (which I found by googling so I don) looks like this:
int arrowKey()
{
int c = 0;
switch ((c = _getch()))
{
case KEY_UP:
cout << endl << "Up" << endl;
break;
case KEY_LEFT:
cout << endl << "Left" << endl;
break;
case KEY_RIGHT:
cout << endl << "Right" << endl;
break;
case KEY_DOWN:
cout << endl << "Down" << endl;
break;
}
return 0;
}
The problem is that the roundNum reads out twice as well as adds two to the number for every arrow key press, like this:
1
1
Up
2
2
Right
3
3
etc
Help is greatly appreciated!
The problem is that a char can only hold 255 values. Thus, in order to get more unique values getch sometimes uses two values to represent a key code, an instruction and a value. For example, try hitting the F keys and you'll notice the same issue arise.
Ultimately, the behavior you are experiencing is due to the fact that getch is being called twice for the arrow keys.
To fix this, check if the instruction is for the arrow keys, in this case the value is 224 for the arrows keys. Once you have identified an arrow keys is being pressed read in the second value with another call to getch and there you will be able to find the actual key.
#include <iostream>
#include <conio.h>
using namespace std;
enum KeyCodes {
KEY_UP = 72,
KEY_LEFT = 75,
KEY_RIGHT = 77,
KEY_DOWN = 80
};
int arrowKey()
{
int c = _getch();
if (c == 224) {
//another value
int key = _getch();
switch (key)
{
case KEY_UP:
cout << endl << "Up" << endl;
break;
case KEY_LEFT:
cout << endl << "Left" << endl;
break;
case KEY_RIGHT:
cout << endl << "Right" << endl;
break;
case KEY_DOWN:
cout << endl << "Down" << endl;
break;
}
}
return 0;
}
int main() {
int roundNum = 0;
while (roundNum <= 20)
{
roundNum++;
cout << roundNum / 2 << endl;
arrowKey();
}
}
It's also worth pointing out that getch is not apart of the std library and could thus have some variation.

Can't get _getch and Switch Case to work togeather in C++

I'm kinda new to C++ and I'm having an hard time with a little ""game"" I'm making.
Here I'm tryng to create a sort of menu that you can move through using the Arrow keys as inputs, and confirm using the Enter key, but despite not getting any error in the compiler the program just closes itself when I reach the second Switch Case.
What am I doing wrong? Thanks
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <windows.h>
#include <conio.h>
#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define ENTER 13
using namespace std;
int main()
{
struct Stats {
int Hp;
int Atk;
int Speed;
int Defense;
};
struct Defense {
bool IsWeakFire;
bool IsWeakIce;
bool IsWeakWind;
bool IsWeakElectric;
bool IsWeakLight;
bool IsWeakDark;
};
struct CharacterStats {
string Name;
string Desc;
string Persona;
Stats Stats;
Defense Defense;
}Characters[4];
//Program Start
cout << "You are now playng: ProjectPB \n" << endl <<
"MC Name> ";
cin >> Characters[0].Name;
cout << "\n \n The game will now start.";
for (int i=0;i<4;i++)
{
Sleep(500);
cout << ".";
}
system("cls");
//Fight start
int i = 0;
int sel = 1;
int c = 0;
while (i == 0) {
switch (sel)
{
case 1:
system("cls");
cout << " |ATTACK| PERSONA DEFEND" << endl;
system("pause");
break;
case 2:
system("cls");
cout << " ATTACK |PERSONA| DEFEND" << endl;
system("pause");
break;
case 3:
system("cls");
cout << " ATTACK PERSONA |DEFEND|" << endl;
system("pause");
} break;
Sleep(100);
int i = 0;
int sel = 1;
while (i == 0){
switch (sel)
{
case 1:
system("cls");
cout << " |ATTACK| PERSONA DEFEND" << endl;
system("pause");
break;
case 2:
system("cls");
cout << " ATTACK |PERSONA| DEFEND" << endl;
system("pause");
break;
case 3:
system("cls");
cout << " ATTACK PERSONA |DEFEND|" << endl;
system("pause");
} break;
Sleep(100);
int c = _getch();
switch (c)
{
case KEY_LEFT :
sel--;
if (sel <= 0)
{
sel = 3;
}
break;
case KEY_RIGHT :
sel++;
if (sel > 3)
{
sel = 1;
}
break;
case ENTER:
i = 1;
break;
}
}
}
return 0;
}
This must be because of the non-empty input buffer during this statement
int c = _getch();
To solve this,simply clear the buffer with this right before getch()
while ((getchar()) != '\n');

Cant make the loop work properly

The code below is supposed to let me choose an option from the menu and then display the appropriate line from the switch statement. It only works when I choose option 'g'. If I choose 'c', it displays the cout line but then it skips the loop and the program exits. What am I doing wrong?
#include <iostream>
#include <cctype>
using namespace std;
enum {c='c', p='p', t='t', g='g'}; // 0-3
int main(){
cout
<< "Elija una opcion del menu:" << endl
<< "c) carnivoros" << endl
<< "p) pianista" << endl
<< "t) Arbol" << endl
<< "g) Juegos" << endl;
char eleccion;
cin.get(eleccion);
while (eleccion >= c && eleccion <= g){
switch (eleccion)
{
case 'c' : cout << "Te gusta la carne e!\n"; break;
case 'p' : cout << "Sos pianista?\n"; break;
case 't' : cout << "Naturista!\n"; break;
case 'g' : cout << "Vicio!\n"; break;
}
cout
<< "Elija una opcion del menu:" << endl;
cin.get(eleccion);
}
_getche();
return 0;
}
You have two problems in your code:
cin.get(eleccion); doesn't clear the new line character from the input stream, so right the next time cin.get is called, it will read the newline character, which is outside the range you specified and it will terminate the loop. Use cin >> eleccion; instead to fix that.
As you assign ASCII letters to your enum, the bigges enum is NOT g but t, so your loop header should look like this:
while ( c <= eleccion && eleccion <= t){
This version still has the drawback, that your loop continues if you enter any char between c and t (which si most of the alphabet) even if it is not a valid selection. For that reason I'd change the program as follows:
using namespace std;
//enums are not needed
int main(){
cout << "Opciones:" << endl
<< "c) carnivoros" << endl
<< "p) pianista" << endl
<< "t) Arbol" << endl
<< "g) Juegos" << endl;
bool rightChar = true;
while (rightChar){
cout << "Elija una opcion del menu:" << endl;
char eleccion;
cin >> eleccion;
switch (eleccion)
{
case 'c': cout << "Te gusta la carne e!\n"; break;
case 'p': cout << "Sos pianista?\n"; break;
case 't': cout << "Naturista!\n"; break;
case 'g': cout << "Vicio!\n"; break;
default: rightChar = false;
}
}
return 0;
}
(eleccion >= c && eleccion <= g)
This line breaks it.
enum {c='c', p='p', t='t', g='g'}; // 0-3
The enum won't be c=0 ... g=3, but it will be c = 99, p = 112, t = 116, g = 103,
Thus, your if will turn into:
(eleccion >= 99 && eleccion <= 103)
And 112 and 116 clearly don't pass that condition.
Also as LightningRacisinOrbit pointed it out, you'll have a problem with the newline remaining in the buffer as well. A solution to it would be to use cin >> eleccion as MikeMB suggested.
You could change the condition in the if statement to
(eleccion >= c && eleccion <= t)
However it's still very ugly. Probably this would be the best:
(eleccion == c || eleccion == g || eleccion == p || eleccion == t)

C++ Detect when user presses arrow key

I have been having a problem with detecting arrow key presses in my C++ console application. I have tried everything I have found, both here and on other tutorial sites, but all of them give me the same thing whenever I press the arrow:
Process returned 0 <0x0> execution time : 2.249 s
Press any key to continue.
Here are all the methods of detecting the key press that I have tried, all ending up the same way. These are the only two left in my code, the others I attempted I deleted instead of commenting out.
Method one:
c1 = getch();
if(c1 == 0)
{
c2 = getch();
if(c2 == 72) {cout << endl << "Up Arrow" << endl;}
else if(c2 == 80) {cout << endl << "Down Arrow" << endl;}
else{cout << endl << "Incorrect Input" << endl;}
}
Method two:
switch(getch()) {
case 65:
cout << endl << "Up" << endl;//key up
break;
case 66:
cout << endl << "Down" << endl; // key down
break;
case 67:
cout << endl << "Right" << endl; // key right
break;
case 68:
cout << endl << "Left" << endl; // key left
break;
}
Is there some error in my code which made me go back to my main method, or did it skip over some code? Is there a faster way to do this? I'm almost 100% sure that my other code doesn't have anything to do with this problem, because I isolated the code from be dependent on any other aspect of the program, and I kept having the same problem.
Again, I tried every method of getting the arrow key press that I could find, and I keep getting the same problem. If it matters, I'm on a Windows 8 Samsung ATIV Smart PC and using the keyboard dock.
Thanks in advance for any help.
#include <conio.h>
#include <iostream>
using namespace std;
#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
int main()
{
int c = 0;
while(1)
{
c = 0;
switch((c=getch())) {
case KEY_UP:
cout << endl << "Up" << endl;//key up
break;
case KEY_DOWN:
cout << endl << "Down" << endl; // key down
break;
case KEY_LEFT:
cout << endl << "Left" << endl; // key left
break;
case KEY_RIGHT:
cout << endl << "Right" << endl; // key right
break;
default:
cout << endl << "null" << endl; // not arrow
break;
}
}
return 0;
}
output like this:
Up
Down
Right
Left
Up
Left
Right
Right
Up
detected arrow key press!
The previous answer by arbboter is close but neglects the fact the arrow keys (and other special keys) return a scan code of two characters. The first is either (0) or (224) indicating the key is an extended one; the second contains the scan code value.
Without accounting for this, the ASCII values for "H", "K", "M", and "P" are misinterpreted as "Up", "Down", "Left", and "Right".
Here's a modified version of arbboter's code to demonstrate reading the extended value when one of the arrow keys is pressed:
#include <conio.h>
#include <iostream>
using namespace std;
#define KEY_UP 72
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define KEY_DOWN 80
int main()
{
int c, ex;
while(1)
{
c = getch();
if (c && c != 224)
{
cout << endl << "Not arrow: " << (char) c << endl;
}
else
{
switch(ex = getch())
{
case KEY_UP /* H */:
cout << endl << "Up" << endl;//key up
break;
case KEY_DOWN /* K */:
cout << endl << "Down" << endl; // key down
break;
case KEY_LEFT /* M */:
cout << endl << "Left" << endl; // key left
break;
case KEY_RIGHT: /* P */
cout << endl << "Right" << endl; // key right
break;
default:
cout << endl << (char) ex << endl; // not arrow
break;
}
}
}
return 0;
}
// Example for inputting a single keystroke in C++ on Linux
// by Adam Pierce <adam#doctort.org> on http://www.doctort.org/adam/nerd-notes/reading-single-keystroke-on-linux.html
// This code is freeware. You are free to copy and modify it any way you like.
// Modify by me Putra Kusaeri
#include <iostream>
#include <termios.h>
#define STDIN_FILENO 0
using namespace std;
int main()
{
// Black magic to prevent Linux from buffering keystrokes.
struct termios t;
tcgetattr(STDIN_FILENO, &t);
t.c_lflag &= ~ICANON;
tcsetattr(STDIN_FILENO, TCSANOW, &t);
// Once the buffering is turned off, the rest is simple.
cout << "Enter a character: ";
char c,d,e;
cin >> c;
cin >> d;
cin >> e;
cout << "\nYour character was ";
// Using 3 char type, Cause up down right left consist with 3 character
if ((c==27)&&(d==91)) {
if (e==65) { cout << "UP";}
if (e==66) { cout << "DOWN";}
if (e==67) { cout << "RIGHT";}
if (e==68) { cout << "LEFT";}
}
return 0;
}
reference
Here is an alternate way to do it without getch() using events (well commented and i tried to make it as simple as i could)
#include <iostream>
#include <Windows.h>
int main(int argc, char *argv[]){
HANDLE rhnd = GetStdHandle(STD_INPUT_HANDLE); // handle to read console
DWORD Events = 0; // Event count
DWORD EventsRead = 0; // Events read from console
bool Running = true;
//programs main loop
while(Running) {
// gets the systems current "event" count
GetNumberOfConsoleInputEvents(rhnd, &Events);
if(Events != 0){ // if something happened we will handle the events we want
// create event buffer the size of how many Events
INPUT_RECORD eventBuffer[Events];
// fills the event buffer with the events and saves count in EventsRead
ReadConsoleInput(rhnd, eventBuffer, Events, &EventsRead);
// loop through the event buffer using the saved count
for(DWORD i = 0; i < EventsRead; ++i){
// check if event[i] is a key event && if so is a press not a release
if(eventBuffer[i].EventType == KEY_EVENT && eventBuffer[i].Event.KeyEvent.bKeyDown){
// check if the key press was an arrow key
switch(eventBuffer[i].Event.KeyEvent.wVirtualKeyCode){
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN: // if any arrow key was pressed break here
std::cout<< "arrow key pressed.\n";
break;
case VK_ESCAPE: // if escape key was pressed end program loop
std::cout<< "escape key pressed.\n";
Running = false;
break;
default: // no handled cases where pressed
std::cout<< "key not handled pressed.\n";
break;
}
}
} // end EventsRead loop
}
} // end program loop
return 0;
}
(Thanks to a commenter I now know this code is not standard, though it will work if you compile with g++, more info in the comments)
Some of the answers given here are not considering the fact that on pressing an arrow key, 2 characters are received. Additionally, it is to be noted that input character should be unsigned char. This is because to determine if an arrow key was pressed, we use ASCII value 224, which can only be stored in an 8-bit character (unsigned char) and not the 7-bit signed char.
You can use below code snippet. 2 types of inputs are processed here. ch1 is the 1st character that user enters. This is the input that user is feeding. But in case of arrow keys, a sequence of 2 characters are received ch1 and ch2. ch1 identifies that some arrow key was pressed, ch2 determines the specific arrow key pressed.
const int KEY_ARROW_CHAR1 = 224;
const int KEY_ARROW_UP = 72;
const int KEY_ARROW_DOWN = 80;
const int KEY_ARROW_LEFT = 75;
const int KEY_ARROW_RIGHT = 77;
unsigned char ch1 = _getch();
if (ch1 == KEY_ARROW_CHAR1)
{
// Some Arrow key was pressed, determine which?
unsigned char ch2 = _getch();
switch (ch2)
{
case KEY_ARROW_UP:
// code for arrow up
cout << "KEY_ARROW_UP" << endl;
break;
case KEY_ARROW_DOWN:
// code for arrow down
cout << "KEY_ARROW_DOWN" << endl;
break;
case KEY_ARROW_LEFT:
// code for arrow right
cout << "KEY_ARROW_LEFT" << endl;
break;
case KEY_ARROW_RIGHT:
// code for arrow left
cout << "KEY_ARROW_RIGHT" << endl;
break;
}
}
else
{
switch (ch1)
{
// Process other key presses if required.
}
}
Check http://msdn.microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx and http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
#include<windows.h>
#include <stdio.h>
int main()
{
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
DWORD NumInputs = 0;
DWORD InputsRead = 0;
bool running = true;
INPUT_RECORD irInput;
GetNumberOfConsoleInputEvents(hInput, &NumInputs);
ReadConsoleInput(hInput, &irInput, 1, &InputsRead);
switch(irInput.Event.KeyEvent.wVirtualKeyCode)
{
case VK_ESCAPE:
puts("Escape");
break;
case VK_LEFT:
puts("Left");
break;
case VK_UP:
puts("Up");
break;
case VK_RIGHT:
puts("Right");
break;
case VK_DOWN:
puts("Down");
break;
}
}
#include <iostream>
#include <conio.h>
const int KB_UP = 72;
const int KB_DOWN = 80;
const int KB_RIGHT = 77;
const int KB_LEFT = 75;
const int ESC = 27;
int main() {
while (true) {
int ch = _getch();
if (ch == 224) {
ch = _getch();
switch (ch) {
case KB_UP:
std::cout << "up\n";
break;
case KB_DOWN:
std::cout << "down\n";
break;
case KB_RIGHT:
std::cout << "right\n";
break;
case KB_LEFT:
std::cout << "left\n";
break;
default: std::cout << "unknown\n";
}
}
else if (ch == ESC)
{
std::cout << "Escape pressed, going out!\n";
break;
}
}
}
This is very simular to some example above except that I used
_getchar()
instead of
getchar()
that visual studio (which I use to write and run my cod)
gives error about,
and I also put it in a loop till you press Escape bottom.