SetKeyboardState doesnt work properly - c++

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.

Related

Counting correct and misplaced digits

This program is a "Codebreaker" game. In this section of the program, the computer checks the digits guessed by the player, compares each of them to every one of the digits in the secret code, and determines if the digit is "correct" or simply "misplaced." I can not get this section to work correctly. I wrote the code for "correct" and "misplaced" in different passes, and I know I need to replace the original variables with a letter so that one number is not checked as more than one and is instead replaced by either "y" or "z". When I run the program, the values for "correct" and "misplaced" are not correct. I am getting random values.
correct_digits = 0;
misplaced_digits = 0;
misplaced_digit = false;
/* Get and validate the player's guess using "get_player_code()"; increment guess counter */
player_code = get_player_code();
++num_guesses;
for(int x=0;x<CODE_LENGTH;x++){
if(player_code[x]==secret_code[x]){
correct_digits++;
secret_code[x]='y';
}
}
for(int x=0;x<CODE_LENGTH;x++){
for(int i=0;i<CODE_LENGTH;i++){
if(player_code[i]==secret_code[i]){
misplaced_digits++;
secret_code[i]='z';
}
}
}
/* Print player's guess and number of correct/misplaced digits */
cout << setw(40) << player_code << setw(15) << correct_digits << setw(15) << misplaced_digits << '\n';
Assuming player_code and secret_code will always be the same length (if player_code is less you will have undefined behavior) and assuming all of the code you're not showing us is correct, then all you need to do is fix this check:
if(player_code[i]==secret_code[i]){
You're checking the same character in each string. You want to compare a character in one of the strings to every character in the other. Your condition should be:
if(player_code[x]==secret_code[i]){

Returning to main menu from another inner menu using c++

I thought of making a sort of Point Of Sales (POS) program. So, as you open the program, a menu (the main menu) would open-up which is a scrolling menu (you can move up & down to select an item in the menu with the arrow keys) and the items in it are like "Start business day", "Stats", "Inventory" blah blah.
Now, when you press "Start Business day"(using enter), you would get another menu which would ask for things like "Take order " ........"Return to the main menu". This is where I am finding the problem. When I press "Return to the main menu", I am not able to move back to the main menu.
MY ATTEMPT
#include<iostream>
#include<conio.h>
#include<string>
#include<windows.h>
using namespace std;
int chk=0;
int sbd(void) //the order menu (start business day -> ' press ENTER')
{
int pointer=0;
string order[4]={"TAKE ORDER","CHECK MENU","MEMO","RETURN TO MAIN MENU"};
while(true)
{
system("cls");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),14);
cout<<"\t\t ZAIKA KATHI ROLLS\n";
cout<<"\t\t\tORDER MENU\n\n";
for(int i=0;i<=3;i++)
{
if( i==pointer)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),11);
cout<<"-> "<<order[i]<<endl<<endl;
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
cout<<" "<<order[i]<<endl<<endl;
}
}
while(true)
{
if(GetAsyncKeyState(VK_UP)!=0)
{
pointer-=1;
if(pointer==-1)
{
pointer=3;
}
break;
}
else if(GetAsyncKeyState(VK_DOWN)!=0)
{
pointer+=1;
if(pointer==4)
{
pointer=0;
}
break;
}
else if(GetAsyncKeyState(VK_RETURN)!=0)
{
switch(pointer)
{
case 3 : return 1;
}
}
}
Sleep(150);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
int pointer=0;
int flag=1;
string menu[6]={"START BUSINESS DAY","CONTINUE BUSINESS DAY","END BUSINESS DAY","INVENTORY MANAGEMENT","STATISTICS","SETTINGS"};
Mainmenu : while(true)
{
system("cls");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),14);
int i=0;
cout<<"\t\t ZAIKA KATHI ROLLS\n";
cout<<"\t\t\tMAIN MENU\n\n";
for(i=0;i<=5;i++)
{
if(i==pointer)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),11);
cout<<"-> "<<menu[i]<<endl<<endl;
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
cout<<" "<<menu[i]<<endl<<endl;
}
}
while(true)
{
if(GetAsyncKeyState(VK_UP)!=0)
{
pointer-=1;
if(pointer==-1)
{
pointer=5;
}
break;
}
else if(GetAsyncKeyState(VK_DOWN)!=0)
{
pointer+=1;
/* if(flag==0 && pointer==1)
pointer=3;
if(flag==1 && pointer==0)
pointer=1;*/
if(pointer==6)
{
pointer=0;
}
break;
}
else if(GetAsyncKeyState(VK_RETURN)!=0)
{
switch(pointer)
{
case 0 :chk=sbd();
if(chk==1)
goto Mainmenu;
}
}
}
Sleep(150);
}
return 0;
}
The best idea that came to my mind was to make the "start business day" as a function and in that function as we press "Return to main menu",the function will return a value which the main fuction will detect and then by using the goto fuction the program control will transfer to the main menu.Apparently thats not working, so can anyone please help me out of this?
What's happening is that when you press enter on "Return to main menu" it is in fact going back to the main menu. If you debug and step through it you'll see this. The problem is that as soon as it steps out of the sub-menu loop it goes into the main menu loop, checks to see if "enter" was pressed, passes the condition and enters the sub-menu loop again.
The thing is that you're not using GetAsyncKeyState function properly in your code:
if (GetAsyncKeyState(VK_RETURN) != 0)
It checks whether the value is zero. But according to the docs this function returns a SHORT.
The most significant bit is 1 if the key is pressed down, and 0 if not.
The least significant bit is 1 if the key was pressed since last calling GetAsyncKeyState. I assume this is what you want. So to begin with change the two spots in your code:
if (GetAsyncKeyState(VK_RETURN) != 0)
to:
if (GetAsyncKeyState(VK_RETURN) & 0x01 != 0)
We only want to check the least significant bit to see if the key was pressed since last time that function was called. If you do this it should work.
You can also write it like this using the Windows macro:
if (LOBYTE(GetAsyncKeyState(VK_RETURN)) != 0)
I should also mention you should probably get around to doing it this same way for key up and key down.
I really like it though, nice work.
Edit: GetAsyncKeyState() returns a short integer. It's most likely two bytes. When the function returns with this value it sets certain bits or flags to tell you information. Like I said, the most significant bit (the highest) tells you whether the key is down or not, the lowest significant bit tells you if the key has been pressed since the last call to that function.
So the returned number in binary will look like this (MSB) is most significant and (LSB) is least significant:
10000000 00000001
^ MSB ^ LSB
If this were an unsigned integer its value would be 32769. You're not interested in whether the key is currently down, but more interested in whether the key has been pressed since the last call to the function. You're only interested in the bit on the right. The bitwise operator & AND will compare two bit patterns and if and only if BOTH bits are 1, it will set the resulting bit to one. This is used with a mask so you can pluck out certain values, so to speak.
10000000 00000001 // Original value
00000000 00000001 // The mask
00000000 00000001 // Result
The result is 1. Then you can check whether the value is 1, and if it is then the key was pressed since the last call. It's a very low level way of doing things, but that's kinda how Windows works and Windows actually helps out by providing that macro LOBYTE() which does the same thing. The alternative is the function could have returned class/struct with bool values for each thing instead.
SECOND EDIT (FURTHER EXPLANATION):
The least significant bit will only be 1 if the key was pressed down since the last call to GetAsyncKeyState. So if you press down the enter key and keep it pressed for 3 seconds, the LSB will be set only on the first call to GetAsyncKeyState. However the MSB will continue to return with the MSB set, because this indicates whether the key is down. The following quick program should illustrate this nicely I think.
A short in our case has 2(bytes) 16 bits, so we're going to use the right bitshift operator >> to get it. I'm going to convert the return type from SHORT to USHORT. This is because bitshifting is undefined for signed integers which are negative because right shifting can propagate the leftmost bit. For example:
// Right shifting 7 bits
UNSIGNED INT
1000 0000 >> 7 = 0000 0001
SIGNED INT
1000 0000 >> 7 = 1111 1111 // We may get this instead which is not what we want
Start a new project and paste this and run, try pressing the enter key:
#include <iostream>
#include <Windows.h>
using namespace std;
int main()
{
while (true)
{
int count = 0;
USHORT funcResult = 0;
while ((funcResult = GetAsyncKeyState(VK_RETURN)) != 0)
// If MSB or LSB is set then condition is true
{
count++;
cout << "Return pressed " << count << " times in one loop\n";
cout << "MSB = " << (funcResult >> 15) << '\n';
cout << "LSB = " << (funcResult & 1) << '\n';
}
// You will see that the MSB is always 1, because it tells us
// if the key is down.
// However the LSB is 1 only on the first run of the while loop
}
}
So this is why adding Sleep() also fixes the problem, because if you press down the enter key for 400 ms and let go, and make the thread sleep for 500 ms, next time it checks the key won't be down, and the MSB won't be set.

While function doesn't work like I want it to

Had a new problem with the while function. As easy as it sounds, I still can't wrap my head around it.
Like my last program, this one closes unexpectedly after the correct and wrong messages.
I want this to loop after entering a number, so that the program won't stop.
Thanks for the help, if any.
#include <iostream>
using namespace std;
int main()
{
int X = 0; //setting the first variable
int num; //setting the second
while (X == 0) //this should happen whenever X is equal to 0
{
cout << "Type a number bigger than 3. "; //output
X++; //This should increase X, so that the next while function can happen
}
while (X == 1) //again, since I increased x by one, (0+1=1 obviously) this should happen
{
cin >> num; //standard input
if (num > 3) //if function: if num is bigger than three, then this should happen
{
cout << "Correct! Try again!" <<endl; //output
X--; //Here I'm decreasing x by one, since it was 1 before, now it becomes 0. This should make the "while (X == 0)" part happen again, so that another number bigger than three can be entered
}
if (num <= 3) //if function: if num is lesser than or equal to 3, this should happen
{
cout << "Wrong! Try again!" <<endl; //output
X--; //This is supposed to work like the "X--;" before, repeating the code from "while (X==0)"
}
}
}
now it becomes 0. This should make the "while (X == 0)" part happen again
Nope. While loops don't magically take effect at any point during execution of the program. You only enter a while loop when you've reached it from code above. Programs are executed top-to-bottom, generally.
You would need a loop around the entire program if you want to keep going round and round. Those whiles you have now should probably be ifs.
Merge the two while loops into one, while(true).
Put each previous while body into an if state with the clause from the old while in it.
while(true) {
if (X==0) {
// the X==0- case
} else if (X==1) {
// the X==1 case
}
}
in order to end your loop, do a break;.
You have to think of C++ programs as a sequence of instructions, like a recipe. while just means a loop: you check the condition. If true, you run the body. After running the body, you check only that condition again, and run the body if true. Whenever the condition is false at the start or end of the body of the while (the {} enclosed code after it), you end the loop and proceed to the next one.
The first loop runs, finishes, then the second loop runs in your code. Once the first loop exits, you do not go back into it just because the condition becomes true.
Understanding flow control is one of the "hard" steps of learning to program, so it is ok if you find this tricky.
There are many improvements you can do your code beyond getting it working -- there is, actually, little need for X at all. But baby steps! Once you get it working, you can ponder "how could I remove the variable X?".
Before making such fundamental changes to your program, you should get it working, and save a copy of it so you can "go back" to the last working version.
You want to wrap all that code in it's own while loop:
while (true /* or something */)
{
while (X == 0) //this should happen whenever X is equal to 0
{
// ...
}
At least put your second while loop inside the first one to get it working as intended. Otherwise your program has no reason to go back again.
Nevertheless it's not a good design.

Check multiple OR operators in IF statement

I have the following C++ code:
if(x==y||m==n){
cout<<"Your message"<<endl;
}
If x is equal to y or m is equal to n, the program prints "Your message". But if both conditions are true,the program tests only one of them and eventually prints one "Your Message".
Is there a way to print each "Your message" independently based on each condition using a single if statement?
The output would be identical to the below using multiple if statements.
if(x==y){
cout<<"Your message"<<endl;
}
if (m==n){
cout<<"Your message"<<endl;
}
Not that I'd ever do it this way, but ...
for(int i = 0; i < (x==y)+(m==n); ++i) {
std::cout << "Your message\n";
}
Let me expand on this. I'd never do it this way because it violates two principles:
1) Code for maintainability. This loop is going to cause the maintainer to stop, think, and try to recover your original intent. A pair of if statements won't.
2) Distinct input should produce distinct output. This principle benefits the user and the programmer. Few things are more frustrating than running a test, getting valid output, and still not knowing which path the program took.
Given these two principles, here is how I would actually code it:
if(x==y) {
std::cout << "Your x-y message\n";
}
if(m==n) {
std::cout << "Your m-n message\n";
}
Aside: Never use endl when you mean \n. They produce semantically identical code, but endl can accidentally make your program go slower.
I don't think that's possible. What you have inside your bracket is a statement which is either true or false, there's no such thing like a true/true or true/false statement. What you could do is a do/while loop with a break statement. But I don't think that's the way to go. Why do you want to avoid two if statements?
single "|" or "&" gaurantees both side evaluation even if the result can be determined by left side operator alone.
You could do something like this, to build up the "message":
string msg = "Your Message\n";
string buildSt = x == y ? m == n ? msg + msg : msg : m == n ? msg : "";
Compiler checks only one condition when both are true because you've connected your conditions with OR.
If even one condition in ORs chain is true there is no need to check others as a result already true and will be false if one of them is false. So if you think that your logic is right then there is no need to do multiple checks. Your code is asking that you will print a message if one of the conditions is true and program doing it. If you want something special for a case when both conditions are true then add it separately. Shortly you should never expect from the compiler to do all checks in the expressions connected by OR.
Regards,
Davit
Tested code:
#include <iostream>
#include <string>
using namespace std;
void main() {
int x=1;
int y=1;
int m=1;
int n=1;
string mess1="Your message 1\n";
string mess2="Your message 2\n";
cout<<((x==y)?mess1:"")+((m==n)?mess2:"");
getchar();
}
If you are trying to see if both statements are true an && is what you will want to use.
Take a look at Boolean Operators to see all of the possible options when comparing boolean (true/false) values.
To answer your question:
if ((x==y) && (m==n))
{
cout<<"Your Message"<<endl<<"Your Message"<<endl;
}
else if((x==y) || (m==n))
{
cout<<"Your Message"<<endl;
}

getAsyncKeyState not recognizing key input

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.