Reading Scan Codes from the Keyboard

nanodano 2 Tallied Votes 6K Views Share

Introduction

Hello everyone. This little code snippet shows you how to read in scan codes from the keyboard. It is slightly different than reading in a regular character. When you use the getch() function, it is normally returning an ASCII value. Some keyboards have extra keys though. These include the F1 - F12 function keys and the directional arrows to start. These keys do not have an ASCII code. A char data type is a one byte item. When you press a key that doesn't have an ASCII code, it returns two bytes. If the first byte is 0, then the next byte contains the scan code. In the following code, I include the scan code for many typical keys and how to read them.

Notes:

  • Even though there are two calls to getch() , it does not require two keystrokes.
  • Not all of these scan codes may be 100% accurate for all computers. It may, of course, need some modifications.
/* This program shows how to pick up the scan codes from a keyboard */

/* These define the scan codes(IBM) for the keys. All numbers are in decimal.*/
#define PAGE_UP     73
#define HOME        71
#define END         79
#define PAGE_DOWN   81
#define UP_ARROW    72
#define LEFT_ARROW  75
#define DOWN_ARROW  80
#define RIGHT_ARROW 77
#define F1          59
#define F2          60
#define F3          61
#define F4          62
#define F5          63
#define F6          64
#define F7          65
#define F8          66
#define F9          67
#define F10         68
#include <iostream>
#include <conio.h>

using namespace std;

void main()
{
	char KeyStroke;

	cout << "Press Escape to quit." << endl;
	
	do
	{
		KeyStroke =	getch();

		if (KeyStroke == 0)
		{
			KeyStroke = getch(); // Even though there are 2 getch() it reads one keystroke
			switch (KeyStroke)
			{
			case PAGE_UP:
				cout << "PAGE UP" << endl;
				break;
			case PAGE_DOWN:
				cout << "PAGE DOWN" << endl;
				break;
			case HOME:
				cout << "HOME" << endl;
				break;
			case END:
				cout << "END" << endl;
				break;
			case UP_ARROW:
				cout << "UP ARROW" << endl;
				break;
			case DOWN_ARROW:
				cout << "DOWN ARROW" << endl;
				break;
			case LEFT_ARROW:
				cout << "LEFT_ARROW" << endl;
				break;
			case RIGHT_ARROW:
				cout << "RIGHT_ARROW" << endl;
				break;
			case F1:
				cout << "F1" << endl;
				break;
			case F2:
				cout << "F2" << endl;
				break;
			case F3:
				cout << "F3" << endl;
				break;
			case F4:
				cout << "F4" << endl;
				break;
			case F5:
				cout << "F5" << endl;
				break;
			case F6:
				cout << "F6" << endl;
				break;
			case F7:
				cout << "F7" << endl;
				break;
			case F8:
				cout << "F8" << endl;
				break;
			case F9:
				cout << "F9" << endl;
				break;
			case F10:
				cout << "F10" << endl;
				break;
			default:
				cout << "Some other key." << endl;
			}
		}
		else
			cout << KeyStroke << endl;
	} 
	while (KeyStroke != 27); // 27 = Escape key
}
A simple program that shows you how to read the keyboard scan code for keys that don't have a normal ASCII code. It includes typical scan codes for the function keys and and the arrow keys.
viper33m 0 Newbie Poster

One modification for those under vista/visual 2008:

KeyStroke =getch();
if (KeyStroke == -32)  //weird, i know.... but it works
{
	KeyStroke = getch();
...}

thk you for the ideea. :hat off:

ramthegreatcv 0 Newbie Poster

thanks a lot..

if (KeyStroke == -32)

works on DevC++ Windows XP.

marco93 -87 Junior Poster

This "code" has no sense at all (case, case, case... horrible !!!!)
It's done in 1 line of code with Win32 api (VK)

William Hemsworth commented: stfu. -1
ramthegreatcv 0 Newbie Poster

@macro93 can u please explain how it can be done using Win32 api?

Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

win32 api doesn't work on non-Windows platforms, but this code snippet will work with some possible mods to the defines at the top.

lortech 0 Newbie Poster

I tried this and the left,right,up,down keys are returning aH aP and so on. F1-F9 work fine. So, If I wanted to control a stepper motor, I would need to learn how to use scan keys. Problem is, I need to figure why the scancodes for the arrow keys are not outputting correctly.

Can any of you try this? I am running xp pro.

ChEeZeBaLL 0 Newbie Poster

I compiled the code in Dev-C++ in Windows XP and the F1-F9 keys were working properly, however the arrow keys printed out αH, αP, etc...

When i changed the code to Keystroke == -32 the arrow keys worked correctly but the F1-F9 keys didn't work properly.

I solved the problem with the following code:

if (KeyStroke == 0 || -32)
Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

You mean like this if (KeyStroke == 0 || KeyStroke == -32)

ChEeZeBaLL 0 Newbie Poster

^oops, yeah that's what i meant.

Thanks.

tsahay2 0 Newbie Poster

thanks a mile mate..!!

pablo_bg 0 Newbie Poster

Hi, all!

I,ve made some changes in the program code and now everything works fine. Now you can read F11, F12, ARROW keys and the other keys as it must be.

/* This program shows how to pick up the scan codes from a keyboard */
	 
	/* These define the scan codes(IBM) for the keys. All numbers are in decimal.*/
	#define PAGE_UP     73
	#define HOME        71
	#define END         79
	#define PAGE_DOWN   81
	#define UP_ARROW    72
	#define LEFT_ARROW  75
	#define DOWN_ARROW  80
	#define RIGHT_ARROW 77
	#define F1          59
	#define F2          60
	#define F3          61
	#define F4          62
	#define F5          63
	#define F6          64
	#define F7          65
	#define F8          66
	#define F9          67
	#define F10         68
	#include <iostream>
	#include <conio.h>
	 
	using namespace std;
	 
	int main()
	{
		unsigned char KeyStroke,c; unsigned int KStroke;
	 
		cout << "Press Escape to quit." << endl << endl;
	 
		do
		{
		c = char(getch());	KeyStroke =	c;   KStroke = int(KeyStroke);  
            
            if (KStroke == 72){cout << "UP ARROW" << endl;} 
            if (KStroke == 80){cout << "DOWN ARROW" << endl;}
            if (KStroke == 75){cout << "LEFT ARROW" << endl;} 
            if (KStroke == 77){cout << "RIGHT ARROW" << endl;}
            if (KStroke == 83){cout << "Delete" << endl;} 
            if (KStroke == 73){cout << "PAGE UP" << endl;}
            if (KStroke == 81){cout << "PAGE DOWN" << endl;} 
            if (KStroke == 71){cout << "HOME" << endl;} 
            if (KStroke == 79){cout << "END" << endl;}
            if (KStroke == 133){cout << "F11" << endl;} 
            if (KStroke == 134){cout << "F12" << endl;} 
            if (KStroke == 82){cout << "Insert" << endl;} 
            if (KStroke == 9){cout << "Tab" << endl;}
	        	        
			if (KeyStroke == 0)
			{
				KeyStroke = getch(); // Even though there are 2 getch() it reads one keystroke
				switch (KeyStroke)
				{
				case F1:
					cout << "F1" << endl;
					break;
				case F2:
					cout << "F2" << endl;
					break;
				case F3:
					cout << "F3" << endl;
					break;
				case F4:
					cout << "F4" << endl;
					break;
				case F5:
					cout << "F5" << endl;
					break;
				case F6:
					cout << "F6" << endl;
					break;
				case F7:
					cout << "F7" << endl;
					break;
				case F8:
					cout << "F8" << endl;
					break;
				case F9:
					cout << "F9" << endl;
					break;
				case F10:
					cout << "F10" << endl;
					break;
				default:
					cout << "Some other key." << endl;
				}
			}
			if((KeyStroke!=0)&&(KeyStroke!=72)&&(KeyStroke!=80)&&(KeyStroke!=75)&&(KeyStroke!=77)&&(KeyStroke!=83)&&(KeyStroke!=73)&&(KeyStroke!=81)&&(KeyStroke!=71)&&(KeyStroke!=79)&&(KeyStroke!=133)&&(KeyStroke!=134)&&(KeyStroke!=89)&&(KeyStroke!=9)){cout<<c<<endl;}
            
		} 
		while (KeyStroke != 27); // 27 = Escape key
	}
pablo_bg 0 Newbie Poster

The only problem with these changes and the code at all, as you can see, is the conflic with conio.h library and getch(). And thats why when you press arrow keys or F11, F12 appear a letter (p) before it. I still can't resolve this but hope I'll find other solution.

Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

getch() will return either 0 or 224 when you press special keys like F1-F10 and arrow keys. If it doesn't return one of those two values then you just pressed a normal key. After getting either 0 or 224 you have to call getch() again, then convert that value to something with will not duplicate normal keys. I've seen two different methods of conversion, either can be used as long as you use them consistently.

  1. make the keystroke value negative. Such as keystroke = -getch();
  2. Add 255 to the value such as keystroke = getch() + 255;

Run this little program and press several keys to find out how it works.

#include <stdio.h>
#include <conio.h>

int main()
{
    int keystroke;
    while(1)
    {
        keystroke = getch();
        printf("keystroks = %d\n", keystroke);
        if( keystroke == 0 || keystroke == 224)
             keystroke = getch() + 255;
        printf("keystroks = %d\n", keystroke);
    }
            
}
Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

In the program you posted you will have to define all the special keys to have different values -- you can't use those values because they conflict with normal keys.

Then just delete lines 37-49 because they are all wrong. You won't get any of those values on the first call to getch().

The if statement on line 51 also needs to check for value of 224 because thats what is returned when an arrow key is pressed.

pablo_bg 0 Newbie Poster

Ancient Dragon, Thanks for the answer!

In your post you said that "getch() will return either 0 or 224 when you press special keys like F1-F10 and arrow keys" and I agree with you.

But how we can see and from your program code for every key there are 2 equal values except for the special keys where the first value is always 224, but the second value is different and unique for every funct. key. For example F11 and F12 have next 2 values: 1st 224 and 2nd 133 for F11 & 224 and 134 for F12.

In my code I am using the second value for my goal in lines 37 - 49. I am sure this code is not correct and thats why I am searching for another solution.

Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

As I said before, when a special key is pressed add the value 255 to the second call to getch() to make the key unique from all other keys on the keyboard. That way your program will always be able to distinguish F1 key from the semicolon, which also has key code of 59.

Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

Here is what I mean. Note that variable KeyStroke must be int, not char because it will have a value > 255 for special keys.

#include <iostream>
	#include <conio.h>
/* This program shows how to pick up the scan codes from a keyboard */
	 
	/* These define the scan codes(IBM) for the keys. All numbers are in decimal.*/
	#define PAGE_UP     (73+255)
	#define HOME        (71+255)
	#define END         (79+255)
	#define PAGE_DOWN   (81+255)
	#define UP_ARROW    (72+255)
	#define LEFT_ARROW  (75+255)
	#define DOWN_ARROW  (80+255)
	#define RIGHT_ARROW (77+255)
	#define F1          (59+255)
	#define F2          (60+255)
	#define F3          (61+255)
	#define F4          (62+255)
	#define F5          (63+255)
	#define F6          (64+255)
	#define F7          (65+255)
	#define F8          (66+255)
	#define F9          (67+255)
	#define F10         (68+255)
	 
	using namespace std;
	 
	int main()
	{
		int KeyStroke;
	 
		cout << "Press Escape to quit." << endl << endl;
	 
		do
		{
		    KeyStroke = getch();
                    if( KeyStroke == 0 || KeyStroke == 224)
                        KeyStroke = getch()+255;
			switch (KeyStroke)
			{
				case F1:
					cout << "F1" << endl;
					break;
				case F2:
					cout << "F2" << endl;
					break;
				case F3:
					cout << "F3" << endl;
					break;
				case F4:
					cout << "F4" << endl;
					break;
				case F5:
					cout << "F5" << endl;
					break;
				case F6:
					cout << "F6" << endl;
					break;
				case F7:
					cout << "F7" << endl;
					break;
				case F8:
					cout << "F8" << endl;
					break;
				case F9:
					cout << "F9" << endl;
					break;
				case F10:
					cout << "F10" << endl;
					break;
				default:
					cout << "Some other key." << KeyStroke << '\n';
			}
            
		}while (KeyStroke != 27); // 27 = Escape key
	}
pablo_bg 0 Newbie Poster

Ok, but how you will do it for F11, F12, ARROWS, HOME, END and the other funct. keys. This is the problem for me.

pablo_bg 0 Newbie Poster

Sorry, my mistake. I read again your example and find what you wnat to say me :) Thank you very much Ancient Dragon for the advise.

balucec 0 Newbie Poster

Hi all,
I need a method to intercept the key before it reaches my application
ie, I need to trap the keys pressed and convert it to my local language, Malayalam, and then display it in my app
thanks and regards

balucec 0 Newbie Poster

Hi all,
I need a method(in C language) to intercept the key before it reaches my application
ie, I need to trap the keys pressed and convert it to my local language, Malayalam, and then display it in my app
thanks and regards

in C language

Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

you will have to use Windows Hooks to do that

pritamprasad 0 Newbie Poster

can ne1 plz explain about using the code (keystroke == -32)... how it is implemenbted here...?

roshan_iiita 0 Light Poster

But this doesn't work on Linux. How can we detect the keys pressed on Linux ?

japun 0 Newbie Poster

How can i trap a user input using ascii code?
Wherein the user should input integer only ranging (0-99),
using loop structures.

Help me pls.. I'm fresh I.T student..

Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

The only way I know how is to use either termcap library or curses. Unlike MS-Windows, *nix supports a huge variety of monitory, keyboards, and terminals.

Zvjezdan23 -13 Junior Poster

That code didn't work for me so I modified it. This code will work for any situation that someone needs to use the up arrow, down arrow, left arrow, and right arrow.

#include <iostream>
#include <string>
#include <cmath>
#include <math.h>
#include <algorithm>
#include <conio.h>
#include <windows.h>
#include <stdio.h>

#define PAGE_UP     73
#define HOME        71
#define END         79
#define PAGE_DOWN   81
#define UP_ARROW    72
#define LEFT_ARROW  75
#define DOWN_ARROW  80
#define RIGHT_ARROW 77
#define F1          59
#define F2          60
#define F3          61
#define F4          62
#define F5          63
#define F6          64
#define F7          65
#define F8          66
#define F9          67
#define F10         68

using namespace std;

int gotoxy(int x, int y) // used to make window
{  
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD point;
   	point.X = x-1;
	point.Y = y-1;     
   	SetConsoleCursorPosition(hConsole, point);
   	return SetConsoleCursorPosition(hConsole, point);
}

void object()
{
	cout << "7" << endl;
}

int main()
{
	system("mode 80,40");

	char ch_, key, key_, ch;
	char up, down, left, right;


	a: cout << "Press up arrow key: ";
	ch_ = getch();

	if (kbhit())
	{
		ch_ = getch();

		if (ch_ == UP_ARROW)
		{
			ch_ = UP_ARROW;
			up = ch_;
			cout << up << endl;
		}

		else if (ch_ != UP_ARROW)
		{
			cout << "Not the up arrow key" << endl;
			system("pause");
			system("cls");
			goto a;
		}
	}

	b: cout << "Press down arrow key: ";
	key = getch();

	if (kbhit())
	{
		key = getch();

		if (key == DOWN_ARROW)
		{
			key = DOWN_ARROW;
			down = key;
			cout << down << endl;
		}

		else if (key != DOWN_ARROW)
		{
			cout << "Not the down arrow key" << endl;
			system("pause");
			system("cls");
			goto b;
		}
	}

	c: cout << "Press left arrow key: ";
	key_ = getch();

	if (kbhit())
	{
		key_ = getch();

		if (key_ == LEFT_ARROW)
		{
			key_ = LEFT_ARROW;
			left = key_;
			cout << left << endl;
		}

		else if (key_ != LEFT_ARROW)
		{
			cout << "Not the left arrow key" << endl;
			system("pause");
			system("cls");
			goto c;
		}
	}

	d: cout << "Press right arrow key: ";
	ch_ = getch();

	if (kbhit())
	{
		ch_ = getch();

		if (ch_ == RIGHT_ARROW)
		{
			ch_ = RIGHT_ARROW;
			right = ch_;
			cout << right << endl;
		}

		else if (ch_ != RIGHT_ARROW)
		{
			cout << "Not the right arrow key" << endl;
			system("pause");
			system("cls");
			goto d;
		}
	}

	system("cls");

	int object_x = 15;
	int object_y = 20;

	gotoxy(object_x,object_y);
	object();

	int x = 1;
	int y = 1;

	char movement;

	for (int i = 0; i < 10; i++)
	{
	gotoxy(3,30);
	cout << "Enter movement key: ";
	movement = getch();
	gotoxy(3,30);
	cout << "                                      " << endl;

	if(kbhit())
	{
		movement = getch();

		if(movement == up)
		{
			int go_up = (object_y - y);
			object_y = go_up;

			gotoxy(object_x,object_y);
			object();
			gotoxy(3,30);
			cout << "You moved north" << endl;
		}

		else if (movement == down)
		{
			int go_down = (object_y + y);
			object_y = go_down;

			gotoxy(object_x, object_y);
			object();
			gotoxy(3,30);
			cout << "You went down" << endl;
		}

		else if (movement == left)
		{
			int go_left = (object_x - x);
			object_x = go_left;

			gotoxy(object_x,object_y);
			object();
			gotoxy(3,30);
			cout << "You went left" << endl;
		}

		else if (movement == right)
		{
			int go_right = (object_x + x);
			object_x = go_right;

			gotoxy(object_x,object_y);
			object();
			gotoxy(3,30);
			cout << "You went right" << endl;
		}
	}
	}

	system("pause");
	return 0;
}
Zvjezdan23 -13 Junior Poster

make the gotoxy(3,30); for you went north, left, down, right to gotoxy(3,29); and in line 164 make that also gotoxy(3,29);

Ancient Dragon 5,243 Achieved Level 70 Team Colleague Featured Poster

That code didn't work for me so I modified it. This code will work for any situation that someone needs to use the up arrow, down arrow, left arrow, and right arrow.

The problem with your program is that there is no difference between F1 and a semicolon because they both have the same ascii value. Same with all the other special keys you defined. That's why I added 255 to the ascii value for special keys so that the program would be able to distinguish them from normal keys. Some programmers just make the value of special keys negative, e.g. #defind F1 (-59)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.