web-dev-qa-db-fra.com

Comment vérifier si une touche est pressée sur C++

Comment pourrais-je vérifier si une touche est enfoncée sous Windows?

6
snivy9014

Comme mentionné par d'autres, il n'y a pas de moyen multiplateforme de le faire, mais sous Windows, vous pouvez le faire comme ceci:

Le code ci-dessous vérifie si la clé "A" est en panne.

if(GetKeyState('A') & 0x8000/*Check if high-order bit is set (1 << 15)*/)
{
    // Do stuff
}

En cas de décalage ou similaire, vous devrez passer l’un de ces: https://msdn.Microsoft.com/de-de/library/windows/desktop/dd375731(v=vs.85).aspx

if(GetKeyState(VK_SHIFT) & 0x8000)
{
    // Shift down
}

Le bit de poids faible indique si la clé est basculée.

SHORT keyState = GetKeyState(VK_CAPITAL/*(caps lock)*/);
bool isToggled = keyState & 1;
bool isDown = keyState & 0x8000;

Oh et n'oublie pas de

#include <Windows.h>
11
Frank S.

Aucune fonction portable ne permet de vérifier si une touche est enfoncée et continue sinon. Cela dépend toujours du système. 

Solution pour Linux et autres systèmes compatibles posix:

Ici, pour le code de Morgan Mattews fournit la fonctionnalité kbhit() de manière compatible avec tout système compatible POSIX. Il utilise le truc de la désactivation de la mise en mémoire tampon au niveau termios.

Solution pour Windows:

Pour les fenêtres, Microsoft propose _kbhit()

2
Christophe

vérifier si une touche est enfoncée, si oui, alors faire des choses

Considérez 'select ()' si cette fonction (apparemment Posix) est disponible sur votre système d'exploitation.

'select ()' utilise 3 jeux de bits que vous créez avec les fonctions fournies (voir man select, FD_SET, etc.). Vous n'avez probablement besoin que de créer les bits d'entrée (pour l'instant)


depuis la page de manuel:

'select ()' "permet à un programme de surveiller plusieurs descripteurs de fichier en attendant qu'un ou plusieurs d'entre eux soient" prêts "pour une classe d'opérations d'E/S (entrée possible, par exemple). Un descripteur de fichier est considéré comme prêt si il est possible d'effectuer une opération d'E/S correspondante (par exemple, read (2) sans bloquer ...) "

Lorsque select est appelé:

a) la fonction regarde chaque fd identifié dans les ensembles, et si cet état indique que vous pouvez faire quelque chose (peut-être lire, écrire peut-être), select reviendra et vous laissera faire ... "tout ce que vous avez à faire" est balayer les bits, trouver le bit défini et agir sur le fd associé à ce bit. 

Le 1er ensemble (passé à select) contient les entrées actives fd (généralement des périphériques). Probablement 1 bit dans cet ensemble est tout ce dont vous aurez besoin. Et avec seulement 1 fd (c’est-à-dire une entrée du clavier), 1 bit, tout cela est assez simple. Avec ce retour de select, vous pouvez "faire des choses" (peut-être après avoir récupéré le caractère).

b) la fonction a également un délai d'expiration, avec lequel vous identifiez combien de temps attendre un changement d'état fd. Si l'état fd ne change pas, le délai d'expiration fera en sorte que 'select ()' revienne avec un 0. (c'est-à-dire sans entrée au clavier) Votre code peut faire quelque chose à ce moment aussi, peut-être une sortie.

fyi - fd sont typiquement 0,1,2 ... Souvenez-vous que C utilise 0 comme STDIN, 1 et STDOUT.


Configuration simple du test: j'ouvre un terminal (distinct de ma console) et tape la commande tty dans ce terminal pour trouver son identifiant. La réponse est typiquement quelque chose comme "/ dev/pts/0", ou 3, ou 17 ... 

Ensuite, je reçois un fd à utiliser dans 'select ()' en utilisant open:

// flag options are: O_RDONLY, O_WRONLY, or O_RDWR
int inFD = open( "/dev/pts/5", O_RDONLY ); 

Il est utile de cout cette valeur. 

Voici un extrait à prendre en compte (de man select):

  fd_set rfds;
  struct timeval tv;
  int retval;

  /* Watch stdin (fd 0) to see when it has input. */
  FD_ZERO(&rfds);
  FD_SET(0, &rfds);

  /* Wait up to five seconds. */
  tv.tv_sec = 5;
  tv.tv_usec = 0;

  retval = select(1, &rfds, NULL, NULL, &tv);
  /* Don't rely on the value of tv now! */

  if (retval == -1)
      perror("select()");
  else if (retval)
      printf("Data is available now.\n");  // i.e. doStuff()
      /* FD_ISSET(0, &rfds) will be true. */
  else
      printf("No data within five seconds.\n"); // i.e. key not pressed
1
2785528