Question about the "GetAsyncKeyState" function

Hello,

I didn't understand what the function "GetAsyncKeyState" actually does.
I read the explanation on MSDN, but I still don't get what this function does.

Well, I know that this function gets a virtual key-code as a parameter,
But I don't get what is it doing with it..

If someone can explain me or maybe can give me a little example of using this function , I will be very grateful.

Thanks.
Last edited on
GetAsyncKeyState returns 0 if the key associated to the code given isn't presset non-0 if it is pressed.
Everything is in MSDN.
Dozens of samples (!)
To give a small example (if it helps):
1
2
3
4
if(GetAsyncKeyState(VK_UP))
{
printf("The Up Arrow Has Been Pressed\n");
}

At the time of exectuing this if statement, if the up arrow is being pressed in, it will say so - put this in a loop if you want to constantly read the key state (pressed (1), not pressed (0)).
If you want the keys to pass to the function, I believe they can be found in "winuser.h" on Windows, (on my include file they start at line 1738 with VK_LBUTTON 1).
Hope that helps a little more.
Last edited on
Thank you chris , but I have a little question.
To try to use this function, I wrote a little code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <windows.h>
#include <fstream>
using namespace std;

int main()
{
    int counter=0;
    ofstream myfile;
    myfile.open("example.txt");
    while(true)
    {
        if(GetAsyncKeyState(VK_ESCAPE))
        {
            counter++;
            myfile <<"Escape : " <<counter;
        }
    }
    return 0;
}


After I pressed one time Ecapse , my example.txt file contained
"Escape : 1Escape : 2Escape : 3Escape : 4Escape : 5Escape : 6Escape : ....70428Escape :

And after I pressed two times in contained
""Escape : 1Escape : 2Escape : 3Escape : 4Escape : 5Escape : 6Escape :...145526Escape :

Do someone have any clue why ?
Last edited on
Yes - because the while(true) loops constantly without any break in it or pause, it uses as much CPU as it can & every millisecond or so that the key is held down, counter increases - I get this problem a lot as well.
There is a useful function in windows.h called Sleep(x) where it pauses program execution for (x) milliseconds.
Maybe try this:

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

int main()
{
    int counter=0;
    ofstream myfile;
    myfile.open("example.txt");
    while(true)
    {
        if(GetAsyncKeyState(VK_ESCAPE))
        {
            counter++;
            myfile <<"Escape : " <<counter;
        }
        Sleep(10); // NEW LINE OF CODE - pauses for 10 milliseconds
    }
    return 0;
}


This still is not perfect, but you will get a lot less than 145526 escapes pressed ^^
Thanks a lot,
But there is a little problem.
I changed my code a bit .

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

int main()
{
    int counter=0;
    ofstream myfile;
    myfile.open("example.txt");
    while(true)
    {
        if(GetAsyncKeyState(VK_ESCAPE))
        {
            counter++;
            myfile <<"Escape : " <<counter;
            cout<<"Button pressed !"<<endl;
        }
        Sleep(100);
    }
    return 0;
}


Now it works great , and if I press 5 times on escape - the output is :
Button pressed !
Button pressed !
Button pressed !
Button pressed !
Button pressed !

But the problem is , the file is always empty.
I need to hold the escape button a lot of time , and then the file is filled a bit , but always he contains
Escape : 1Escape : 2Escape : 3Escape : 4Escape : 5Escape : 6Escape : ...42Escape

Any clue what should I do to fix it?
Last edited on
Well, what I've found from some testing is:..
I imagine the way you close the program is just exitting the process before it's had time to finish the file properly.
What I've done here is added it so that by pressing F1 it closes the file handle properly:
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
#include <windows.h>
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    unsigned int counter=0;
    ofstream myfile;
    myfile.open("example.txt");
    while(true)
    {
        if(GetAsyncKeyState(VK_ESCAPE))
        {
            counter++;
            myfile <<"Escape : " <<counter;
            cout<<"Button pressed !"<<endl;
        }
		if(GetAsyncKeyState(VK_F1))
		{
		myfile.close();
		return 0;
		}
        Sleep(100);
    }
    return 0;
}

I've also changed counter to an unsigned int, as I hope you cannot press Enter negative times... ;)

If you do not want to have to press F1 to stop this, I've done the same piece of code, except with the C standard input/output library, that re-opens the file for ammending so that it is updated properly.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <windows.h>
#include <stdio.h>

int main()
{
    unsigned int counter=0;
    FILE* myfile = fopen("example.txt","wb");
    while(true)
    {
        if(GetAsyncKeyState(VK_ESCAPE))
        {
			freopen("example.txt","ab",myfile);
            counter++;
			fprintf(myfile,"Escape : %d",counter);
            printf("Button pressed !\n");
        }
      Sleep(100);
    }
    return 0;
}



Also - if you want the code to only write the file with 1 line, ie the entire file contents is "Escape : 500":

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <windows.h>
#include <stdio.h>

int main()
{
    unsigned int counter=0;
    FILE* myfile = fopen("example.txt","wb");
    while(true)
    {
        if(GetAsyncKeyState(VK_ESCAPE))
        {
			freopen("example.txt","wb",myfile);
            counter++;
			fprintf(myfile,"Escape : %d",counter);
            printf("Button pressed !\n");
			fclose(myfile);
        }
      Sleep(100);
    }
    return 0;
}


That works for me.
Last edited on
Thank you very much , I appreciate it.
No problems mate =)
Sorry to join the conversation late...

The GetAsyncKeyState() function is not ideal for what you are trying to do.

All it does is simply check the actual, current-at-this-nanosecond position of a key on the keyboard. Doing that is almost always incorrect.

Instead, read the console input using the proper input functions.
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdio.h>
#include <windows.h>

int main()
{
    DWORD        mode;          /* Preserved console mode */
    INPUT_RECORD event;         /* Input event */
    BOOL         done = FALSE;  /* Program termination flag */
    unsigned int counter = 0;   /* The number of times 'Esc' is pressed */

    /* Don't use binary for text files, OK?  ;-) */
    FILE* myfile = fopen( "example.txt", "w" );

    /* Get the console input handle */
    HANDLE hstdin = GetStdHandle( STD_INPUT_HANDLE );

    /* Preserve the original console mode */
    GetConsoleMode( hstdin, &mode );

    /* Set to no line-buffering, no echo, no special-key-processing */
    SetConsoleMode( hstdin, 0 );

    /* Give the user instructions */
    printf(
        "Press Escape as many times as you like.\n"
        "Press anything else to quit.\n\n"
        );

    while (!done)
    {
        if (WaitForSingleObject( hstdin, 0 ) == WAIT_OBJECT_0)  /* if kbhit */
        {
            DWORD count;  /* ignored */

            /* Get the input event */
            ReadConsoleInput( hstdin, &event, 1, &count );

            /* Only respond to key release events */
            if ((event.EventType == KEY_EVENT)
            &&  !event.Event.KeyEvent.bKeyDown)
                switch (event.Event.KeyEvent.wVirtualKeyCode)
                {
                    case VK_ESCAPE:
                        counter++;
                        fprintf( myfile, "Escape: %d\n", counter );
                        printf( "Button pressed!\n" );
                        break;
                    default:
                        done = TRUE;
                }
        }
    }

    /* All done! */
    printf( "You pressed the Escape key %d times\n", counter );
    fclose( myfile );
    SetConsoleMode( hstdin, mode );
    return 0;
}

Get more information about all the functions I used by googling "msdn function-name", or just visit
http://msdn.microsoft.com/en-us/library/ms682073(VS.85).aspx

This example only responds to key release events. Chances are you will want to respond to key press events for your game (or whatever you are making). Un-negate line 40 to do that. ;-)

Hope this helps.
Hi,

The solution you have given is very useful. Iam trying it in Windows mobile in C++ (win32 console application) to check the key state of all virtual key codes, where I got problem is Iam not able to detect state of VK_HOME,VK_F3(TALK), and also when I try to write the virtual key code in to file Iam getting repeatedly . Though I used Sleep()with different values from 100... 1000.Iam not able to fix the problem. Code snippet is,



code:
#include "stdafx.h"
#include <windows.h>
#include <commctrl.h>
#define MAX_EVENTS_BUFF 500

int _tmain(int argc, _TCHAR* argv[])
{
INT vkIndex,index=0;
FILE* write,*read;
write=fopen("UserKeyEvents.txt","w+b");
INT events[MAX_EVENTS_BUFF];
memset(&events,0,sizeof(events));
while(true)
{
for(vkIndex=VK_LBUTTON;vkIndex<=VK_DBE_ENTERDLGCONVERSIONMODE;vkIndex++)
{
if(GetAsyncKeyState(vkIndex))
{
events[index]=vkIndex;
index++;
break;
}
}
if(vkIndex==115)//virtual key code of END key
{
fwrite(events,sizeof(events),1,write);
fclose(write);
read=fopen("UserKeyEvents.txt","r+b");
fread(events1,sizeof(events1),1,read);//to find what are the keycodes there in the file
fclose(read);
return 0;
}
Sleep(100);
}
return 0;
}

Can anybody kindly tell me what am I doing wrong and correct it.
Thanks in advance for any help.


If you want to use GetAsyncKeyState but are only concerned with handling the actual transitions, then you have to keep track of the transitions yourself.


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
40
41
42
43
44
45
46
47
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
	int counter=0;
	ofstream myfile;
	short prev_escape = 0, curr_escape = 0;
	myfile.open("c:\\example.txt");

	while(true)
	{
		//This if statement is required to ignore key repeat, which causes the return value to increment
		if(GetAsyncKeyState(VK_ESCAPE))
			curr_escape = 1;
		else
			curr_escape = 0;

		//Here we only process on the actual transition 
		//IE when the current value has changed from the previous value
		if(prev_escape != curr_escape)
		{
			
			//Could move counter to the if statement below to only increment on either the press or release
			counter++;

			//Is this a key press, or a key release?
			if(curr_escape){
				myfile <<"Escape pressed : " << counter << endl;
				cout<<"Escape pressed !" << endl;
			}
			else{
				myfile <<"Escape released : " << counter << endl;
				cout<<"Escape released !" << endl;
			}

			prev_escape = curr_escape;
		}
        
	}
	//Close the file on exit, and whatever is buffered gets written to file before the application exits
	myfile.close();
	return 0;
}


That code only processes on the key transitions, and ignores everything else. No need for any sleeps at all, unless you want to reduce CPU usage.
Instead of using while(true) you should be using a GetMessage() or PeekMessage() loop.
Topic archived. No new replies allowed.