How do you do this?[windows7]

Hello,

I want to use GetAsyncKeyState to create the most simple program(Just to feel how it works)

I want the console program to open a window, wait for me to press an arrow key on my keybaord(i.e up, down, left, right)

Then tell me what I pressed

What #include's should I use, as well?



Thanks for anyone that'll help!
Last edited on
If this is for a game, I strongly recommend you consider leaving the console and getting a graphic/window lib like SFML. Things like this are typically a lot easier to do with those kinds of libs than in they are in the console.

Also as an added perk... libs like SFML are portable, whereas the code I give below is Windows only.



That said... on windows, you can use the <Windows.h> header for GetAsyncKeyState.

GetAsyncKeyState is non-blocking, which means it will not wait for the key to be pressed, it will just return immediately with the real-time state of the key. If you want to wait for a key to be pressed, you will have to spin in a loop and continuously check the key state until one of them is pressed.

Example:

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
#include <Windows.h>

int waitForArrowKey()
{
    static const int keys[] = {  // the keys to check
        VK_UP,
        VK_DOWN,
        VK_RIGHT,
        VK_LEFT
        };

    int keypressed = 0;  // 0=no key pressed
       // otherwise, keypressed will contain which arrow key is pressed

    while( keypressed == 0 ) // keep looping until a key is pressed
    {
        // check all the keys in our 'keys' list to see if any of them are pressed
        for(auto key : keys)
        {
            if(GetAsyncKeyState(key) & 0x8000)
                keypressed = key;  // this key is pressed!
        }

        Sleep(10);  // do a short sleep between polls so the program doesn't
        //  suck up 100% CPU usage
    }

    return keypressed;  // return the key that was pressed
}



If you want to use this to print out which key the user pressed:

1
2
3
4
5
6
7
8
9
10
11
12
int main()
{
    int key = waitForArrowKey();  // wait for user to press arrow key

    switch(key)  // see which key they pressed
    {
    case VK_UP:     cout << "You pressed the Up key."; break;
    case VK_LEFT:   cout << "You pressed the Left key."; break;
    case VK_RIGHT:  cout << "You pressed the Right key."; break;
    case VK_DOWN:   cout << "You pressed the Down key."; break;
    }
}
And try this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<conio.h>
using namespace std;

int main()
{
    int key;
    key=getch();
    if(key==224)
    {
        key=getch();
        switch(key)
        {
            case 72: cout<<"UP"<<endl;break;
            case 80: cout<<"DOWN"<<endl;break;
            case 75: cout<<"LEFT"<<endl;break;
            case 77: cout<<"RIGHT"<<endl;break;
        }
    }
    else
    cout<<"Not an arrow key"<<endl;
    return 0;
}
conio.h is nonstandard and isn't included in [some] modern compilers.

But yeah I guess that is definitely simpler. Of course I would recommend you make an enum or at least some constants so you don't have those magic numbers.
Last edited on
First of all THANKS A LOT FOR THE EFFORT! This was really informative!
I just have a few basic questions ;

1)
'static const int keys", why are you using a constant here? And what does the 'static' mean?

2)
for(auto key : keys) - what does this do? I know how for functions, but I don't understand the command inside it

and lastly, what is the ' & 0x8000' , why is it needed?
'static const int keys", why are you using a constant here?


It's a lookup table. This allows you to keep all the keys you want to check in a single array. This lets you avoid copy/pasting blocks of code over and over for each key. Plus, if you want to add/remove keys later, all you have to do is change that array.

And what does the 'static' mean?


It's a style/performance thing.

static local variables are allocated once on first use and have a lifetime that persists throughout the life of the program.

Whereas non-static variables are allocated and initialized each and every time the function is called.

By making the constant array static, it'll only get initialized once rather than multiple times.

Functionally, the code will be the same regardless of whether or not you have static there, so it doesn't really matter. It's just an old habit of mine, really.

for(auto key : keys) - what does this do? I know how for functions, but I don't understand the command inside it


This is a range-based for loop, introduced in C++11. for(auto key : keys) loops for each element in the 'keys' container... and 'key' will be the current element inside that loop.

This loop:
1
2
3
4
5
        for(auto key : keys)
        {
            if(GetAsyncKeyState(key) & 0x8000)
                keypressed = key;  // this key is pressed!
        }


Is exactly the same as this loop:

1
2
3
4
5
        for(int i = 0; i < 4; ++i)
        {
            if(GetAsyncKeyState(keys[i]) & 0x8000)
                keypressed = keys[i];  // this key is pressed!
        }


The only differences are the first loop...
1) ...is more succinct.
2) ...doesn't need to know the size of the 'keys' array (notice how I had to hardcode in '4' in the 2nd loop).


and lastly, what is the ' & 0x8000' , why is it needed?


& 0x8000 masks out and isolates bit 15 from the returned value.

GetAsyncKeyState doesn't only give you the up/down state of the key... it actually gives you a few different pieces of info about the key. Since the only thing we're interested in is up/down state... I isolate that bit and force all other bits to zero.
Static allows the variable to have persistent data even when leaving the scope.

Const enforces the value of the variable, not allowing change/alteration to the variables.

Both may improve performance, and are used to restrict/maintain persistence of data; just my opinion.

http://msdn.microsoft.com/en-us/library/s1sb61xd.aspx
http://msdn.microsoft.com/en-us/library/07x6b05d.aspx

& 0x8000 is needed to properly use GetAsyncKeyState(key).
Here's your code, which is easy to understand for beginners...
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
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
float main ()
{

int a,b=0;
	
	
	
    int comp=0;
	while(1)
	{
		if(kbhit())
		{
			a=getch();
			
			if(a==77)
			{
				cout<<"you pressed right\n";
			}
			else if(a==75)
			{
				cout<<"you pressed left\n";
			}
			else if(a==72)
			{
				cout<<"you pressed up\n";;
			}
			else if(a==80)
			{
				cout<<"you pressed down\n";
			}
			
		}
		
	}
}
conio.h is nonstandard and isn't included in [some] modern compilers.


All windows compilers that I know of implements conio.h, OP already wants to write a windows only program, so what's the problem with it ?
All windows compilers that I know of implements conio.h,


Really? For some reason I thought I didn't have it installed but apparently I do. Whoops.

My mistake. Apologies.

OP already wants to write a windows only program, so what's the problem with it ?


Absolutely nothing.

Though OP did specifically say he wanted to use GetAsyncKeyState, so I guess I had that on my mind.


But yeah the conio.h solution is fine. The only thing I'd change is make some contants for those arrow keys rather than using magic numbers.
Topic archived. No new replies allowed.