In this C++ Tutorial, we will discuss how to detect Key Presses. The supposedly simple task of registering a single key press (such as the button “a”) turns out to be a surprisingly hard task.
For starters, there is no “perfect platform-independent” method that will work for all Operating Systems (Either it will not work on some OS’s or it will work on them all, but lack some features). Secondly, there are many different ways of detecting key presses, which causes people to get a little confused.
We will do two things in this tutorial. First we will show you all the different techniques to “detect” key presses, and then we will explore a Platform Independent Solution that will be enough for most situations.
Detecting Key Presses – Techniques
We will first discuss Platform-dependent solutions for detecting key-presses, before discussing a Platform Independent solution. Let’s start with the Windows Operating System.
Here we have a solution which relies on the “windows.h” header file. This import gives us the ability to use the GetKeyState()
function. By passing in the correct key code to this function, we can “listen” for that specific key and then execute an action accordingly.
The below code “listens” for the Right Shift key to be pressed, and then terminates the loop and exits the program.
#include <iostream>
#include <conio.h>
#include <windows.h>
int main() {
char ch;
int flag = 1;
while (flag) {
if(GetKeyState(VK_RSHIFT) & 0x8000) {
std::cout << "Right Shift key pressed" << std::endl;
flag = 0;
}
}
return 0;
}
The bit flag 0x8000
determines if the key is currently pressed.
Here is a list of all the possible Key codes, along with their descriptions.
Virtual Code | Scan Code | Description |
---|---|---|
VK_LBUTTON | 0x01 | Left mouse button |
VK_RBUTTON | 0x02 | Right mouse button |
VK_CANCEL | 0x03 | Control-break processing |
VK_MBUTTON | 0x04 | Middle mouse button (three-button mouse) |
VK_XBUTTON1 | 0x05 | X1 mouse button |
VK_XBUTTON2 | 0x06 | X2 mouse button |
VK_BACK | 0x08 | BACKSPACE key |
VK_TAB | 0x09 | TAB key |
VK_SHIFT | 0x10 | SHIFT key |
VK_CONTROL | 0x11 | CTRL key |
VK_MENU | 0x12 | ALT key |
VK_PAUSE | 0x13 | PAUSE key |
VK_CAPITAL | 0x14 | CAPS LOCK key |
VK_NUMPAD0 to VK_NUMPAD9 | 0x60 – 0x69 | Numpad 0-9 key |
VK_F1 to VK_F12 | 0x70 – 0x7B | Function key F1 to F12 |
VK_NUMLOCK | 0x90 | NUM LOCK key |
VK_SCROLL | 0x91 | SCROLL LOCK key |
VK_LSHIFT | 0xA0 | Left SHIFT key |
VK_RSHIFT | 0xA1 | Right SHIFT key |
VK_LCONTROL | 0xA2 | Left CONTROL key |
VK_RCONTROL | 0xA3 | Right CONTROL key |
VK_LMENU | 0xA4 | Left MENU key |
VK_RMENU | 0xA5 | Right MENU key |
Detect Key Presses in Windows#2
There is one more technique we can use to detect Key presses in Windows, called _kbhit()
. This function is a bit unique in the sense that it only “detects” a keyboard press, it does not “consume” it. This means that if you type “a”, kbhit()
will return True, but “a” will still remain. So any subsequent _kbhit()
calls will also trigger unless we do something about it.
Let’s take a look at a small piece of code.
#include <conio.h>
#include <stdio.h>
int main( void ) {
// Display message until key is pressed.
while( !_kbhit() )
_cputs( "Waiting.... " );
// Use _getch to consume input.
printf( "\nKey struck was '%c'\n", _getch());
}
As you can see here, “Waiting” will continue to print until we press a key. We then consume the entered key at the end using _getch()
, and print it out.
We will talk more about _getch()
more at the end of this tutorial.
Detecting Key Presses in Linux
Here is some special code written by someone who wanted to create a “kbhit” for Linux (since it is Windows only). The following code contains a definition for _kbhit(), and then a small piece of code to show it’s working. You can learn more about this code on their website.
#include <stdio.h>
#include <sys/select.h>
#include <termios.h>
#include <stropts.h>
#include <unistd.h>
int _kbhit() {
static const int STDIN = 0;
static bool initialized = false;
if (! initialized) {
// Use termios to turn off line buffering
termios term;
tcgetattr(STDIN, &term);
term.c_lflag &= ~ICANON;
tcsetattr(STDIN, TCSANOW, &term);
setbuf(stdin, NULL);
initialized = true;
}
int bytesWaiting;
ioctl(STDIN, FIONREAD, &bytesWaiting);
return bytesWaiting;
}
int main(int argc, char** argv) {
printf("Press any key");
while (! _kbhit()) {
printf(".");
fflush(stdout);
usleep(1000);
}
return 0;
}
Platform Independent solution for Key Presses in C++
Let’s discuss a little trick we can use to get a single “character” from our Keyboard. For some situations, this technique will be more than enough. The best part about it is that it is Platform independent!
This technique makes use of the _getch()
function which takes a single character as input from the keyboard. It can also capture capital characters.
#include <iostream>
#include <conio.h>
int main() {
char ch;
//program pauses here until key is pressed
ch = _getch();
if(ch == 'a')
std::cout << "Key Pressed: a" << std::endl;
if(ch == 's')
std::cout << "Key Pressed: s" << std::endl;
else if(ch == 'A')
std::cout << "Key Pressed: A" << std::endl;
return 0;
}
This has a few limitations, such as not being able to detect multiple keys at once, and the fact that it “blocks” the execution of our program until we give some input. You can actually make this work for most situations regardless, especially if you wrap it in a loop (for more than one character).
_getch()
uses ASCII codes, so you can use integers instead of characters in your switch-case statements. This is useful for when you are taking input for non-alphabetical characters, like arrow keys.
This marks the end of the How to detect Key Presses in C++ Tutorial. Any suggestions or contributions for CodersLegacy are more than welcome. Questions regarding the tutorial content can be asked in the comments section below.
Hi there! I from Russia and I work on Mac. It don’t read [#include “conio.h”] that this file “not found”. Please, tell me what am I doing wrong and sorry, if I bad talk English. Thanks!
Чувак, conio.h это заголовочный файл из windows. ОС, которая стоит на маке (mac OS. OS X, не шарю, если честно), является Unix-системой. Попробуй линуксовый вариант, по идее, должно сработать.
use #include <conio.h>