This is the code for my scrolling menu where it display different values based on the 3 vectors, welcomeMenuVector, menuOptionsVector and menuActionVector:
welcomeMenuVector - Save function of title
menuOptionsVector - Save menu options of scrolling menu
menuActionsVector - Save the functions to perform after the menu option is selected
vector<string> menuOptionsVector;
vector<function<void()>> menuActionsVector;
vector<function<void()>> welcomeMenuVector;
void scrollingMenu(){
ShowConsoleCursor(false);
int pointer = 0;
while (true){
system("cls");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
welcomeMenuVector[0]();
for (unsigned int i = 0; i < menuOptionsVector.size(); ++i){
if (i == pointer){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
cout << center("> " + menuOptionsVector[i] + " <" ,getWindowWidth()) <<endl;
}
else{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
cout << center(" " + menuOptionsVector[i] + " ", getWindowWidth()) << endl;
}
}
while (true){
if (GetAsyncKeyState(VK_UP) != 0){
pointer -= 1;
if (pointer == -1){
pointer = menuOptionsVector.size() - 1;
}
break;
}
else if (GetAsyncKeyState(VK_DOWN) != 0){
pointer += 1;
if (pointer == menuOptionsVector.size()){
pointer = 0;
}
break;
}
else if (GetAsyncKeyState(VK_RETURN) != 0){ //when enter key is pressed
menuActionsVector[pointer]();
}
}
Sleep(100);
}
}
I will need to enter menu title, menu options and menu functions into vector before I need to call the scrollingMenu(). Hence, I will have to clear all the 3 vectors before entering values into vectors because there will be values inside as it might be used by another menu earlier.
This is my main page, user page and add user page:
void mainPage(){
clearMenuVectors();
welcomeMenuVector = { [](){mainPageWelcome(); } };
menuOptionsVector = { "Login", "Exit" };
menuActionsVector = {
[](){ userPage(); },
[](){ exit(0); }
};
scrollingMenu();
}
void userPage(){
clearMenuVectors();
welcomeMenuVector = { [](){userPageWelcome(); } };
menuOptionsVector = { "Add User", "Update User", "Delete User", "Exit" };
menuActionsVector = {
[](){ addUsers(); },
[](){ updateUsers(); },
[](){ deleteUsers(); },
[](){ exit(0); }
};
scrollingMenu();
}
void addUsers(){
clearMenuVectors();
welcomeMenuVector = { [](){cout << center("Which type of user would you like to add?", getWindowWidth()) << endl;; } };
menuOptionsVector = { "Add Admin", "Add Scheduler", "Add Professional", "Exit" };
menuActionsVector = {
[](){ /*addUser();*/ },
[](){ /*updateUsers();*/ },
[](){ /*deleteUsers();*/ },
[](){ exit(0); }
};
}
My main page works fine at first, I'm able to move up & down, after hitting enter on the Login menu option, it goes to the userPage, but here comes the problem, when I'm in the userPage, I can still see the menu options of userPage, but when I just move up/down it will then changed the menu options of addUsers (I haven't even hit the enter), even if I dont move up/down I hit enter on Add User option, nothing happens, I'm not sure what is the problem here.
If you change
[](){ /*addUser();*/ },
to
{ cout << "add user option 1" << endl; },
and it writes it continuously then the key is pressed.
GetAsyncKeyState
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 you need to check the least significant bit. In this case
if (GetAsyncKeyState(VK_RETURN) != 0)
should be
if (GetAsyncKeyState(VK_RETURN) & 0x1)
Related
So i am making a software to help me with an arduino project, it is supossed to be like PUTTY. I programed the arduino to play different notes from Q-I(C4-C5) and the software is supossed to play thoes notes but i need to make it detect when the Key is pressed and released, how do i do that? I searched and found something but it is not working like it's supposed to here is the code:
int main(){
int KeyGet;
while(1)
{
KeyGet = getch();
if (GetKeyState(0x51) & 0x8000)
{
cout<<"key is pressed"<< endl;
}
else if(GetKeyState(0x51)& 0x0001)
{
cout<<"key is released"<< endl;
}
}
return 0;
The program just prints "key is pressed" when i press Q(0x51) and not "key released" as it should, insted it prints "key released" when i press something else other the Q. And i tried GetAsyncKeyState and tried
If (GetKeyState(0x51) != 0)
it still doesent work.
GetKeyState() requires a window and a message loop to keep the state machine updated. But you do not have a message loop. Also, getch() would swallow any key press+release anyway.
Also, GetKeyState(0x51) & 0x0001 is not the right way to detect a key release. That bit is meant for detecting the toggle state of togglable keys like CapsLock, etc.
In your example, you would need to get rid of getch() and use GetAsyncKeyState() instead, eg:
int main(){
bool down = false;
while (1) {
if (GetAsyncKeyState(0x51) < 0) {
if (!down) {
down = true;
cout << "key is pressed" << endl;
}
}
else {
if (down) {
down = false;
cout << "key is released"<< endl;
}
}
Sleep(0);
}
return 0;
}
Otherwise, you can use a WH_KEYBOARD[_LL] hook via SetWindowsHookEx() instead, so you can receive actual key down/up notifications in real-time.
I am stuck with the input with no enter input.
I tried to use kbhit() + getch() from conio.h and it doesn't work on my system (Win10 and Ubuntu - unistd.h and termios.h). Program just skips block with these functions.
Then I used GetAsynkKeyState from windows.h. It works in the game (Level) though buggy, but doesn't in a Menu. Program as well skips (or something) block with input dispatch.
Menu input:
// The menu interface
bool Menu::SelectLevel() {
cout << "Select the level:" << endl;
size_t arrow_pos = 0;
// Prints level's names and char to exit the game
for (size_t i = 0; i <= _levels.size(); ++i) {
// Draw arrow before selected level
if (i == arrow_pos) {
cout << '>' << i + 1 << " - " << _levels[i].first[0] << endl;;
}
// Draw arrow before the exit select
else if (i == _levels.size() && i == arrow_pos) {
cout << '>' << "Exit" << endl;
}
// Draw the exit option
else if (i == _levels.size()) {
cout << ' ' << "Exit" << arrow_pos << endl;
}
// Draw levels list
else {
cout << ' ' << i + 1 << " - " << _levels[i].first[0] << endl;
}
}
// Input from keyboard TODO DOESN'T WORK!:
// If 's' pressed move arrow down
PoollingDelay(1);
if (GetAsyncKeyState(0x53) & 0x8000) {
++arrow_pos;
// If arrow reached top it goes to the bottom
if (arrow_pos == _levels.size() + 1) {
arrow_pos = 0;
}
}
// If 'w' pressed move arrow up
else if (GetAsyncKeyState(0x57) & 0x8000) {
--arrow_pos;
// If arrow reached bottom it goes to the top
if (arrow_pos == 65535) {
arrow_pos = _levels.size() + 1;
}
}
// If Return pressed
else if (GetAsyncKeyState(VK_RETURN) & 0x8000) {
// Don't think it would be worthy
if (arrow_pos < 1 || arrow_pos > _levels.size() - 1) {
throw runtime_error("Wrong select: " + to_string(arrow_pos));
}
// If player tired of this shit
if (arrow_pos == _levels.size() - 1) {
ClearTerminal();
return false;
}
// Play
PlayLevel(arrow_pos);
}
ClearTerminal();
return true;
}
Level input:
// TO DO DOESN'T WORK!:
void Level::ReadCommand() {
PoollingDelay(100);
if (GetAsyncKeyState(0x57)) {
Move(_NORTH);
}
else if (GetAsyncKeyState(0x41)) {
Move(_WEST);
}
else if (GetAsyncKeyState(0x53)) {
Move(_SOUTH);
}
else if (GetAsyncKeyState(0x44)) {
Move(_EAST);
}
else if (GetAsyncKeyState(0x45)) {
throw runtime_error(exit_the_lvl);
}
}
Short answer: you can't using only C++ and its standard library.
This is because the language is not designed to handle low-level hardware events. To do this, you need to rely on a separate library, dedicated to handle I/O. Lots of them, some are more or less easy to integrate. For simple games, SDL is nice.
I am making console style game in sfml. It's graphical interface but game itself contains console. I'm using Text Entered event for writing things in console but i also want to move the cursor (console cursor not mouse) with arrow keys. To be more specific in text entered event i am using event.text.unicode for key value. But arrow keys unicode values not working in my pc. I used 37 for left arrow, 39 for right arrow but it doesn't work. This is my console's key process function.
void Console::update(int unicode) {
if(unicode == 8) { // Backspace
deleteLast();
} else if(unicode == 13) { // Enter
newLine();
} else if(unicode == 37) { // Left arrow key
currentX--;
std::cout << "Left arrow" << std::endl;
} else if(unicode == 39) { // Right arrow key
currentX++;
std::cout << "Right arrow" << std::endl;
} else { // Normal characters
buffer[(currentY == 0) ? currentX : (currentY * maxColumn) + currentX] = (char)unicode;
currentX++;
if(currentX == maxColumn - 1) {
newLine();
}
std::cout << "[KEY TYPED] X: " << currentX << " Y: " << currentY << std::endl;
}
}
Thanks in advance :)
Edit: I think i solved. I used KeyPressed event for handling special keys. And TextEntered for handling normal characters.
For those having the same problem:
From an Event type variable, first check if its a keyboard event
if(event.type == sf::Event::KeyPressed)
Then check if its an arrow:
if(event.key.code == sf::Keyboard::Up)
//do stuff
if(event.key.code == sf::Keyboard::Down)
//do stuff
ok, so im kinda new to C++ and im trying to build a basic login program. iv got it to work except for one problem... this is what iv got
void InitialLogin()
{
cout << "\t\t ===========LOGIN==========" << endl;
cout << "\t\n\n\n\tUsername/>> " ;
getline(cin, sUsername);
cout << "\t\n\tPassword/>> ";
getline(cin, sPassword);
if (sUsername == "myname" && sPassword == "mypass")
{
cout << "\n\t\t\t--ACCESS GRANTED--";
system("CLS");
}
else if (sUsername != "myname" && sPassword != "mypass")
{
SetConsoleTextAttribute(h, FOREGROUND_RED);
cout << "\n\t\t\t--ACCESS DENIED--\n\n\n";
SetConsoleTextAttribute(h, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
main();
}
}
after i run this, if the login was successfull i have the following run after the screen is cleard...
void Initialization()
{
cout << "/>> Aquireing file list......" << endl;
cout << "/>> file list aquired........" << endl;
cout << "/>> determing file location.." << endl;
}
now my problem is, if i get the username or password wrong say once i get the initialization output twice, if i get it wrong twice, the output is three times.
i need to know how to clear the overflow or buffer or something...
please help :)
Your function is attempting to call main(). This is not legal C++.
You should return a status to see if the login worked or not. Then just loop until the status either becomes "true", or the user has run out of chances. Here is a small example:
bool InitialLogin();
int main()
{
int numChances = 3;
int numCount = 0;
bool loginOk = false;
while (numCount < numChances && !loginOk )
{
loginOk = InitialiLogin();
++numCount;
}
if ( !loginOk )
{
// number of chances ran out
return 0;
}
else
{
// proceed. Login was successful
}
}
bool InitialLogin()
{
//...
if (sUsername == "myname" && sPassword == "mypass")
{
//...
return true;
}
// anything here means that the login failed. There is no need for an if()
//...
return false;
}
I feel you are getting this because you are calling the main() function when both the password and username are incorrect (As a side note you might want to change the && in this check to || as you want access to be denied if either the password or username are incorrect).
You might want to consider getting the InitialLogin() function to return a bool to show weather the login was successful or not. If not the get it to run InitialLogin() again if successful then get it to proceed with the code.
In the place where you call InitialLogin() you can use a while loop to get it to repeat.
while(!InitialLogin()){}
So when InitialLogin() is not false (bad login) it will try again and when it is not true (good login) it will continue onto next section of code.
I'm writing an live video processing program in c++, and want to be able to toggle three windows with the same mjpeg stream, in color, grayscale, and monochrome. I have all the image feeds running, but, since my screen is small, I want to be able to toggle them on and off individually. To do this, I have written the code below, but calling destroyWindow("[windowname]"); stops the whole program, instead. I've already read the documentation, and putting void in front of it doesn't help. Can anybody tell me what I'm doing wrong?
Here's the code (it's in an infinite loop, until the break you see below is called):
imshow("Color", imageColor);
imshow("Monochrome", imageMonochrome);
imshow("Grayscale", imageGrayscale);
int keyPressed = waitKey(0);
if (keyPressed > 0)
{
cout << keyPressed;
cout << "key was pressed\n";
// Press C to toggle color window
if (99 == keyPressed)
{
if (colorOpen)
{
cout << "Color window closed\n";
void destroyWindow("Color");
colorOpen = false;
}
if (!colorOpen)
{
cout << "Color window opened\n";
imshow("Color", imageColor);
colorOpen = true;
}
}
// Press M to toggle monochrome window
if (109 == keyPressed)
{
if (monochromeOpen)
{
cout << "Monochrome window closed\n";
void destroyWindow("Monochrome");
monochromeOpen = false;
}
if (!monochromeOpen)
{
cout << "Monochrome window opened\n";
imshow("Monochrome", imagebw);
monochromeOpen = true;
}
}
// Press G to toggle grayscale window
if (103 == keyPressed)
{
if (grayscaleOpen)
{
cout << "Grayscale window closed\n";
void destroyWindow("Grayscale");
grayscaleOpen = false;
}
if (!grayscaleOpen)
{
cout << "Grayscale window opened\n";
imshow("Grayscale", image);
grayscaleOpen = true;
}
}
// Break out of infinite loop when [ESC] is pressed:
if (27 == keyPressed)
{
cout << "Escape Pressed\n";
break;
}
}
The code you pasted terminates after calling destroyWindow (by running off the end of main). If that's not what you want to happen, write code that does something else after calling destroyWindow. Perhaps you want a loop?