getAsyncKeyState not recognizing key input - c++

So I decided that I wanted to write a little keylogger tonight, just to learn about getAsyncKeyState. I'm trying to get my log to write to a file but the file's contents either show up blank or throw a random memory address at me (0x28fef0 before). I've heard that getAsyncKeyState doesn't function well with Windows 7 x64, is it true?
This is pretty aggravating, I was hoping to actually be able to get this running tonight.
while(1)
{
Sleep(20);
for(DWORD_PTR key = 8; key <= 190; key++)
{
if (GetAsyncKeyState(key) == HC_ACTION)
checkKey(key);
}
}
Function definition
void checkKey(DWORD_PTR key)
{
ofstream out;
out.open("log.txt");
if (key==8)
out << "[del]";
if (key==13)
out << "n";
if (key==32)
out << " ";
if (key==VK_CAPITAL)
out << "[CAPS]";
if (key==VK_TAB)
out << "[TAB]";
if (key==VK_SHIFT)
out << "[SHIFT]";
if (key==VK_CONTROL)
out << "[CTRL]";
if (key==VK_PAUSE)
out << "[PAUSE]";
if (key==VK_ESCAPE)
out << "[ESC]";
if (key==VK_END)
out << "[END]";
if (key==VK_HOME)
out << "[HOME]";
if (key==VK_LEFT)
out << "[LEFT]";
if (key==VK_UP)
out << "[UP]";
if (key==VK_RIGHT)
out << "[RIGHT]";
if (key==VK_DOWN)
out << "[DOWN]";
if (key==VK_SNAPSHOT)
out << "[PRINT]";
if (key==VK_NUMLOCK)
out << "[NUM LOCK]";
if (key==190 || key==110)
out << ".";
if (key >=96 && key <= 105)
{
key -= 48;
out << &key; // had ampersand
}
if (key >=48 && key <= 59)
out << &key; // amp'd
if (key !=VK_LBUTTON || key !=VK_RBUTTON)
{
if (key >=65 && key <=90)
{
if (GetKeyState(VK_CAPITAL))
out << &key; // amp;d
else
{
key = key +32;
out << &key; // amp'd
}
}
}
}
I'm seriously stumped by this issue and any help would be greatly appreciated. Why would a function like this work differently on a 64 bit system? Considering it's the only box I've got I can't run it on a 32 bit to check whether or not it's an isolated issue. Because I'm assuming that it's related to getAsyncKeyState and not my code (which compiles and creates a blank log file) I only included those two code snippets.

Well, firstly you don't want to be using GetAsyncKeyState if you are writing a key logger; GetAsyncKeyState gets the state of the key at the immediate moment you call the function. You need to be listening in on the Windows messages, for things like WM_KEYDOWN, WM_KEYUP, or depending on the purpose of the logger WM_CHAR, WM_UNICHAR etc...

You're using the function incorrectly. Reading the documentation before requesting help is usually a good idea...
I'll just quote MSDN here:
If the function succeeds, the return value specifies whether the key
was pressed since the last call to GetAsyncKeyState, and whether the
key is currently up or down. If the most significant bit is set, the
key is down, and if the least significant bit is set, the key was
pressed after the previous call to GetAsyncKeyState. However, you
should not rely on this last behavior; for more information, see the
Remarks.
That last part also means it's completely useless for a key logger.
PS: Consider using GetKeyNameText for translating virtual key codes into meaningful names.

For monitoring input, something like a keyboard hook is probably the way to go (look up SetWindowsHookEx with WH_KEYBOARD_LL on MSDN).
As noted elsewhere, you're not using GetAsyncKeyState correctly here.
As for why you're seeing an address appear:
out << &key; // amp'd
This is several places in your code: key is a DWORD_PTR, so &key is a pointer - this is likely where the addresses are coming from.

Related

c++ - GetAsyncKeyState makes my program crash when I open it

So I'm making a game that runs on the console. I started with some functions to make drawing to the screen easier, and that worked fine. Then when I tried to add input (using the function GetAsyncKeyState), the program crashed as soon as I started the program. It said: "Text Game.exe has stopped working" Here's how I handled the code:
if(GetAsyncKeyState('A' && 0x8000)) {
x -= 1;
}
if(GetAsyncKeyState('D' && 0x8000)) {
x += 1;
}
if(GetAsyncKeyState('W' && 0x8000)) {
y += 1;
}
if(GetAsyncKeyState('S' && 0x8000)) {
y += 1;
}
If it helps, I got this method by reading this:
How to check if a Key is pressed
EDIT: So I ran it in debug mode, and it said it crashed when I ran a function I made called "refreshScreen();". I don't know why though. Here's the code:
void refreshScreen() {
system("CLS");
for ( int i = 0; i < screenHeight; i++ ) {
for ( int j = 0; j < screenWidth; j++ ) {
cout << screen[i][j];
}
cout << endl;
}
}
It's meant to clear the console, then print all of the contents of array "screen". "Screen", by the way, is the buffer that I write to.
If you are trying to use the GetAsyncKeyState as it's described in answers by the link you provided, you are doing it wrong.
Documentation says the following:
If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState.
So what is done in the answer by the link you provided:
if (GetAsyncKeyState('W') & 0x8000)
{ /*key is down*/ }
In the if statement there bitwise "and" operation is performed on return value of GetAsyncKeyState function and 0x8000 constant - which equals to 0x8000 the most significant bit is set or equals to 0 when it is not set.
What is your code doing:
if(GetAsyncKeyState('A' && 0x8000)) // ...
logical "and" operation between 'A' and 0x8000 constant - gives true which is casted to 1 and passed to GetAsyncKeyState as an argument.
[EDIT]: As it was mentioned in comments, 1 corresponds to left mouse button. So all if conditions will be true in case left mouse button is down and will be false otherwise. Probably, crash appears in different part of your program after unexpected change of x and y values. You should debug your program to localize the crash.

Prevent GetAsyncKeyState function from detecting inputs after it is called? C++

I have a game which is turn based. During your turn, it prompts you for a move and will ask for one key press input. As soon as a key press is detected, the game continues and you are no longer prompted until your next turn.
I am having problems though with GetAsyncKeyState function though because it stores key presses even after it is called.
From the MSDN website:
Determines whether a key is up or down at the time the function is called, and whether the key was pressed after a previous call to GetAsyncKeyState.
The bolded area is what is causing problems for me, as the user can spam key inputs while it is not his/her turn, then when it becomes his/her turn, the game will prompt the user and instantly confirm an input that was pressed from beforehand.
My function for this is very similar to this:
unsigned int getUserInput(){
while (true) //Await a user's input
{
if (GetAsyncKeyState(0x31))
{
return 1; //User pressed 1 key
}
else if (GetAsyncKeyState(0x32))
{
return 2; //User pressed 2 key
}
else if (GetAsyncKeyState(0x33))
{
return 3; //User pressed 3 key
}
else if (GetAsyncKeyState(0x34))
{
return 4; //User pressed 4 key
}
else if (GetAsyncKeyState(0x35))
{
return 5; //User pressed 5 key
}
else if (GetAsyncKeyState(0x36))
{
return 6; //User pressed 6 key
}
}
}
Should I just not use Asnc Key State in this case? If so, what is a better alternative?
The value that GetAsyncKeyState returns is a bit field. You can isolate the bit you are looking for with bitwise operations. In your specific case (for detecting if the key is currently pressed), you are looking for the high bit. You can test it like this:
if (GetAsyncKeyState(0x31) & 0x8000)
{
return 1; //User pressed 1 key
}
However, if I am understanding your problem description correctly, I don't think this will fully solve it. It sounds like you want the user to have to press the key down while the function is running (rather than just being able to hold the key down). What you should do for that, is at the beginning of the function check if the key is pressed. If it is, wait for it to be released. Something like this:
bool key_is_pressed = true;
while (key_is_pressed) {
key_is_pressed = false;
// the key codes you are checking are consecutive,
// so we can just loop over them
for (int key = '1'; key <= '6'; ++key) {
if (GetAsyncKeyState(key) & 0x8000))
key_is_pressed = true;
}
}
Then continue to the part where you wait for a key to be pressed.
Note that the text you highlight, "and whether the key was pressed after a previous call to GetAsyncKeyState", could actually have been the solution to your problem. That information is stored in a different bit (the low bit), so you could isolate that and ensure that the key wasn't previously pressed. Unfortunately, MSDN clearly documents that this behavior should not be relied upon. So you should pretty much always ignore everything but the hi bit when using GetAsyncKeyState.

SetKeyboardState doesnt work properly

I have program, then it's running it asks stuffs and then user has to press 1 to proceed I use GetKeyState() function to decide if number was pressed and SetKeyboardState() to set keys states back to original, but it doesn't work after second attempt. Whats wrong?
Code:
BYTE States[256];
GetKeyboardState(States);
cout << press 1 << endl;
while(!Started)
{
if(GetKeyState(VK_NUMPAD1))
{
Started = true;
}
}
SetKeyboardState(States);
cout << "press 1" << endl;
while(!Name)
{
if(GetKeyState(VK_NUMPAD1))
{
Name = true;
}
}
SetKeyboardState(States);
cout << "press 1" << endl;
while(!Located)
{
if(GetKeyState(VK_NUMPAD1))
{
Located = true;
}
}
The code looks a bit odd to me. I have a feeling that you've not got the optimal solution to your problem. But I don't know enough of your problem to say so for sure.
One thing sticks out though. Your test of the return value of GetKeyState() is wrong you should test it like this:
if(GetKeyState(VK_NUMPAD1)<0)
From the documentation:
If the high-order bit is 1, the key is down; otherwise, it is up.
The simple way to test for high-order bit being 1 is that the value is negative. Your code tests for any bit being set which will evaluate true for states other than the key being down.
I am no expert, but as far as I can see,
Your while(!Name) checks if variables are false. Inside the loop you set them to true and loop ends which leaves you unable to check key more then once.

Why can't I read all Ctrl + 'letters'

I've made a program that allows me to read all the stand-alone function keys (that I thought to test, at least) on my keyboard. I have it designed so that I can refer to any single key input as a single value. It handles Return, F1-F12, delete, backspace, arrows etc
I just thought to test modifications of input. I already made sure shift works, but now I decided to test Ctrl and Alt.
Question 1
Why does Alt not modify any of the input key codes?
Question 2
Why can I not capture certain Ctrl + combinations?
Eg. Ctrl + s; Ctrl + 1-9;
Ctrl + 2 works, but I think it might be due to having my keyboard set as UK.
This is the code I am using.
Please note, I am not necessarily asking how to capture these key combinations (unless it is a simple modification or two). I only want to know why I am unable to.
#include <iostream>
#include <conio.h>
#include <cwchar>
union wide_char
{
short Result;
char C[2];
};
int main()
{
wchar_t R;
int N;
wide_char user_input;
//Loops forever, this is only a proof of concept program proving this is possible to incorporate into a larger program
while(true)
{
user_input.C[0] = 0;
user_input.C[1] = 0;
//Loop twice, or until code causes the loop to exit
//Two times are neccessary for function keys unfortunately
for(int i = 0; i < 2; ++i)
{
//While there isn't a key pressed, loop doing nothing
while(!kbhit()){}
//Grab the next key from the buffer
//Since the loop is done, there must be at least one
user_input.C[i] = getch();
switch(user_input.C[i])
{
case 0:
case -32:
//The key pressed is a Function key because it matches one of these two cases
//This means getch() must be called twice
//Break switch, run the for loop again ++i
break;
default:
//The character obtained from getch() is from a regular key
//Or this is the second char from getch() because the for loop is on run #2
//Either way we need a wide char (16 bits / 2 Bytes)
if(user_input.C[1] != 0)
//Function keys {Arrows, F1-12, Esc}
//We now combine the bits of both chars obtained
//They must be combined Second+First else the F1-12 will be duplicate
//This is because on F1-12 getch() returns 0 thus won't affect the combination
R = user_input.Result;
else
//Regular key press
R = user_input.C[0];
//Display our unique results from each key press
N = R;
std::cout << R << " R = N " << N << std::endl;
if( R == 'a' )
std::cout << "a = " << N << std::endl;
//Manually break for loop
i = 3;
break;
}
}
//We need to reset the array in this situation
//Else regular key presses will be affected by the last function key press
}
}
This is very specific to your environment. You're using conio which is specific to DOS / Windows.
Most of the Ctrl + alpha key values are bound to characters 1 - 26, and certain others are bound to other values under 31, to map to ASCII control characters. But some, like Ctrl + S have special meaning (Ctrl + S is XOFF in ASCII), and so might get 'eaten' by your environment.
Fundamentally, the issue you're facing is the fact that getch approximates an old-school serial terminal interface. They only expose keyboard events at a "least common denominator" level, as opposed to a lower level that would allow you to distinguish modifier keys, etc. and give you a better way to deal with special keys such as function keys.
(As you've noticed, function keys, have special multi-byte sequences. Again, this is due to emulating old-school serial terminals, where the keyboard might be at the other end of a remote link.)
To get a lower-level (and therefore more direct and flexible interface) you need to use a more platform-specific library, or a richer library such as SDL. Either would give you a lower level view of the inputs from the keyboard.

How I can prevent every key being sent to KeyboardUpFunc in GLUT?

I'm fairly new to OpenGL, and I am writing a simple game in 2D, for fun. However, I ran into an issue I am having a hard time wrapping my head around.
It seems that whenever my keyboardUpFunc is called, that not only the key that has actually come up sent to the function, but every single key currently being pressed as well.
I'm using a simple key buffer to manage the keys, keyUp marks the key as up and is only called in this function. keyDown is called in my keyboardFunc. isDown returns a boolean value of whether or not the key is pressed. Take this code for example:
#include <iostream>
...
void keyboardUp(unsigned char key, int x, int y)
{
keys.keyUp(key);
if (keys.isDown('s') == false)
{
std::cout << "It's resetting s as well!" << std::endl;
}
// reset acceleration here, for each key
if ( (key == 'w') || (key == 's') )
{
yStep = 0.1;
}
if ( (key == 'a') || (key == 'd') )
{
xStep = 0.1;
}
std::cout << key << " is now up." << std::endl;
}
If you run this code, if you for example, hold S and D, then release the D key, you will note that S has been marked as up too, since this is the only location keyUp is being called.
Assuming my keyBuffer code is working correctly (and it is, but let me know if you want me to post it...), is there any way to get around this? Where if you were holding a key, and then pressed another key, the application would go back to what you were doing when you were just holding the original key? Instead of marking both as up? Or is this not feasible with GLUT?
Not very clear what is going wrong.. But where/how exactly are you calling this function ?? Directly in the Main Game loop, or are you checking certain conditions in an 'update' function. I ask because you need to check for input every run of the infinite loop, and if you are using a boolean to determine if a key is down, you should essentially reset it after its corresponding action has been performed. Anyway, just my 2 cents.
I changed my implementation of the keyboard buffer, and what I was describing above now works. The difference is that before I was using a vector to pile on the keys that were being pressed, whereas now, I am using a fixed-size array of boolean values.
Apparently, a vector implementation of a key buffer won't work properly with GLUT.