web-dev-qa-db-fra.com

Détection C++ lorsque l'utilisateur appuie sur la touche fléchée

J'ai eu du mal à détecter les pressions sur les touches fléchées dans mon application console C++. J'ai essayé tout ce que j'ai trouvé, ici et sur d'autres sites de tutoriels, mais ils me donnent tous la même chose chaque fois que j'appuie sur la flèche: 

Process returned 0 <0x0> execution time : 2.249 s
Press any key to continue.

Voici toutes les méthodes de détection de la pression de touche que j'ai essayées, toutes se terminant de la même manière. Ce sont les deux seuls qui restent dans mon code, les autres que j'ai essayés ont été supprimés au lieu d'être commentés. 

Méthode 1:

c1 = getch();
if(c1 == 0)
{

    c2 = getch();

    if(c2 == 72) {cout << endl << "Up Arrow" << endl;}
    else if(c2 == 80) {cout << endl << "Down Arrow" << endl;}
    else{cout << endl << "Incorrect Input" << endl;}

}

Méthode deux:

switch(getch()) {
case 65:
       cout << endl << "Up" << endl;//key up
    break;
case 66:
    cout << endl << "Down" << endl;   // key down
    break;
case 67:
    cout << endl << "Right" << endl;  // key right
    break;
case 68:
    cout << endl << "Left" << endl;  // key left
    break;
}

Existe-t-il une erreur dans mon code qui m'a amené à revenir à ma méthode principale ou a-t-il sauté un code? Y a-t-il un moyen plus rapide de faire cela? Je suis presque à 100% sûr que mon autre code n'a rien à voir avec ce problème, car je l'ai isolé du fait qu'il ne dépendait d'aucun autre aspect du programme et que je continuais à avoir le même problème. 

Encore une fois, j’ai essayé toutes les méthodes possibles pour appuyer sur la touche fléchée et j’ai toujours le même problème. Si cela compte, je suis sous Windows 8 Samsung ATIV Smart PC et j'utilise le dock clavier.

Merci d'avance pour votre aide. 

8
#include <conio.h>
#include <iostream>
using namespace std;

#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77

int main()
{
    int c = 0;
    while(1)
    {
        c = 0;

        switch((c=getch())) {
        case KEY_UP:
            cout << endl << "Up" << endl;//key up
            break;
        case KEY_DOWN:
            cout << endl << "Down" << endl;   // key down
            break;
        case KEY_LEFT:
            cout << endl << "Left" << endl;  // key left
            break;
        case KEY_RIGHT:
            cout << endl << "Right" << endl;  // key right
            break;
        default:
            cout << endl << "null" << endl;  // not arrow
            break;
        }

    }

    return 0;
}

sortie comme ceci:

Up

Down

Right

Left

Up

Left

Right

Right

Up

détecté appuyez sur la touche!

13
arbboter

Voici un autre moyen de le faire sans getch () using events (bien commenté et j'ai essayé de le rendre aussi simple que possible)

#include <iostream>
#include <Windows.h>

int main(int argc, char *argv[]){

    HANDLE rhnd = GetStdHandle(STD_INPUT_HANDLE);  // handle to read console

    DWORD Events = 0;     // Event count
    DWORD EventsRead = 0; // Events read from console

    bool Running = true;

    //programs main loop
    while(Running) {

        // gets the systems current "event" count
        GetNumberOfConsoleInputEvents(rhnd, &Events);

        if(Events != 0){ // if something happened we will handle the events we want

            // create event buffer the size of how many Events
            INPUT_RECORD eventBuffer[Events];

            // fills the event buffer with the events and saves count in EventsRead
            ReadConsoleInput(rhnd, eventBuffer, Events, &EventsRead);

            // loop through the event buffer using the saved count
            for(DWORD i = 0; i < EventsRead; ++i){

                // check if event[i] is a key event && if so is a press not a release
                if(eventBuffer[i].EventType == KEY_EVENT && eventBuffer[i].Event.KeyEvent.bKeyDown){

                    // check if the key press was an arrow key
                    switch(eventBuffer[i].Event.KeyEvent.wVirtualKeyCode){
                        case VK_LEFT:
                        case VK_RIGHT:
                        case VK_UP:
                        case VK_DOWN:   // if any arrow key was pressed break here
                            std::cout<< "arrow key pressed.\n";
                            break;

                        case VK_ESCAPE: // if escape key was pressed end program loop
                            std::cout<< "escape key pressed.\n";
                            Running = false;
                            break;

                        default:        // no handled cases where pressed 
                            std::cout<< "key not handled pressed.\n";
                            break;
                    }
                }

            } // end EventsRead loop

        }

    } // end program loop

    return 0;
}

(Grâce à un commentateur, je sais maintenant que ce code n'est pas standard, même s'il fonctionnera si vous compilez avec g++, plus d'informations dans les commentaires.)

5
James
// Example for inputting a single keystroke in C++ on Linux
// by Adam Pierce <[email protected]> on http://www.doctort.org/adam/nerd-notes/reading-single-keystroke-on-linux.html
// This code is freeware. You are free to copy and modify it any way you like.
// Modify by me Putra Kusaeri


#include <iostream>
#include <termios.h>
#define STDIN_FILENO 0
using namespace std;
int main()
{
// Black magic to prevent Linux from buffering keystrokes.
    struct termios t;
    tcgetattr(STDIN_FILENO, &t);
    t.c_lflag &= ~ICANON;
    tcsetattr(STDIN_FILENO, TCSANOW, &t);

// Once the buffering is turned off, the rest is simple.
    cout << "Enter a character: ";
    char c,d,e;
    cin >> c;
    cin >> d;
    cin >> e;
    cout << "\nYour character was ";
// Using 3 char type, Cause up down right left consist with 3 character
    if ((c==27)&&(d=91)) {
        if (e==65) { cout << "UP";}
        if (e==66) { cout << "DOWN";}
        if (e==67) { cout << "RIGHT";}
        if (e==68) { cout << "LEFT";}
    }
    return 0;
}
1
Putra Kusaeri

Vérifiez http://msdn.Microsoft.com/en-us/library/windows/desktop/ms684961(v=vs.85).aspx et http://msdn.Microsoft.com/en- us/bibliothèque/windows/desktop/dd375731 (v = vs.85) .aspx

#include<windows.h>
#include <stdio.h>

int main()
{
    HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
    DWORD NumInputs = 0;
    DWORD InputsRead = 0;
    bool running = true;

    INPUT_RECORD irInput;

    GetNumberOfConsoleInputEvents(hInput, &NumInputs);

    ReadConsoleInput(hInput, &irInput, 1, &InputsRead);

    switch(irInput.Event.KeyEvent.wVirtualKeyCode)
    {
        case VK_ESCAPE:
        puts("Escape");
        break;

        case VK_LEFT:
        puts("Left");
        break;

        case VK_UP:
        puts("Up");
        break;

        case VK_RIGHT:
        puts("Right");
        break;

        case VK_DOWN:
        puts("Down");
        break;
    } 

}
1
user93353

La réponse précédente de arbboter est proche mais néglige le fait que les touches fléchées (et autres touches spéciales) renvoient un code de balayage de deux caractères. Le premier est soit (0), soit (224) indiquant que la clé est étendue; la seconde contient la valeur du code d'analyse.

Sans tenir compte de cela, les valeurs ASCII pour "H", "K", "M" et "P" sont interprétées à tort comme "Up", "Down", "Gauche" et "Droite".

Voici une version modifiée du code d'arbboter pour montrer la lecture de la valeur étendue lorsque l'une des touches fléchées est enfoncée:

#include <conio.h>
#include <iostream>
using namespace std;

#define KEY_UP    72
#define KEY_LEFT  75
#define KEY_RIGHT 77
#define KEY_DOWN  80

int main()
{
    int c, ex;

    while(1)
    {
        c = getch();

        if (c && c != 224)
        {
            cout << endl << "Not arrow: " << (char) c << endl;
        }
        else
        {
            switch(ex = getch())
            {
                case KEY_UP     /* H */:
                    cout << endl << "Up" << endl;//key up
                    break;
                case KEY_DOWN   /* K */:
                    cout << endl << "Down" << endl;   // key down
                    break;
                case KEY_LEFT   /* M */:
                    cout << endl << "Left" << endl;  // key left
                    break;
                case KEY_RIGHT: /* P */
                    cout << endl << "Right" << endl;  // key right
                    break;
                default:
                    cout << endl << (char) ex << endl;  // not arrow
                    break;
            }
        }
    }

    return 0;
}
0
Erik Anderson