C++: GetKeyState() a pour exécuter une seule fois
J'ai besoin d'écouter de touche de clavier états pour ma petite demande.
#include <windows.h>
#include <fstream>
#include <iostream>
using namespace std;
int main()
{
while(1)
{
if(GetKeyState(VK_SPACE) & 0x80)
{
cout << "Space pressed.\r\n";
DoSpaceKeyTask();
}
if(GetKeyState(OTHER_KEY) & 0x80)
{
cout << "Other key pressed.\r\n";
DoOtherKeyTask();
}
}
return 0;
}
Une fois que je clique sur certaines touches de mon clavier, ces fonctions a exécuté une seule fois. Ils sont juste quelques petites tâches pour mes applications, ce qui n'est pas liée à ce sujet.
Mon problème est que quand j'appuie sur une touche, il exécute les fonctions quelques fois, en raison de while(1)
boucle à quelques reprises au cours de la touche. Je ne peux pas utiliser Sleep()
dans ce cas, car elle ne veut toujours pas être efficace.
Je suis à la recherche d'une solution de ce genre.
- Je presse la touche ESPACE.
DoSpaceKeyTask()
exécute "une fois".- J'appuie sur d'AUTRES clés.
DoOtherKeyTask()
exécute "une fois".
J'ai comme 5 touches que j'utilise. Quelqu'un pourrait-il m'aider sur ce cas?
Ps. Si GetKeyState()
fonction n'est pas utile sur cette tâche, n'hésitez pas à proposer les vôtres. Ma fonction de connaissances est assez limité sur le C++.
- 1. Vous souhaitez
GetAsyncKeyState
pour cette boucle. 2. Vous devez masque avec0x8000
. Aussi, vous pouvez utiliserwhile (GetAsyncKeyState(...) & 0x8000)
à attendre pour aller jusqu'. - Voici un bon texte de présentation sur le point 1: blogs.msdn.com/b/oldnewthing/archive/2004/11/30/272262.aspx
- Salut chris, c'est toujours la même chose avec GetAsyncKeyState et 0x8000. Des idées?
- Vous devez soit utiliser un état de mécanisme, comme on le voit ci-dessous, ou utiliser quelque chose qui vous informe de touches/déprime, comme une fenêtre ou un crochet.
- L'état des mécanismes de regarder hacky. Comment puis-je rechercher pour ceux fenêtre/crochet sur Google? Que dois-je en général? Aussi, mon application s'exécute en arrière-plan, tandis que le réel de l'exécution de l'application sur le premier plan. Je veux juste pour automatiser certaines tâches. Comme si vous avez déjà joué à un jeu de RPG, je veux vendre mon ensemble de l'inventaire à un PNJ avec une seule touche.
- DoSpaceKeyTask() la fonction a juste à cliquer sur chaque élément dans mon inventaire. (la souris cliquez sur prédéfini coordonnées rapidement.) Alors oui, je suis à la recherche d'une solution sur ce point. J'ai utilisé KeyState, juste parce que mes recherches Google, il me l'a montré. Je veux juste obtenir de l'état des touches du clavier, quelle que soit l'application sur le premier plan. Je peux le fermer lorsque cela est nécessaire.
- Oh, qui efface les choses un peu mieux. La fonction que vous recherchez est
SetWindowsHookEx
. Il existe assez peu de bons exemples des différents crochets, mais celui que vous voulez, c'est le crochet de la fenêtre de jeu message de la procédure. Crochet pour vérifier les événements clés, et de les gérer de façon appropriée. - Merci, je vais regarder dès maintenant. 🙂
Vous devez vous connecter pour publier un commentaire.
Vos fonctions sont appelées plusieurs fois en raison de la durée de temps que le bouton reste enfoncé. Le système est très sensible. C'est donc une solution de contournement.
Vous pourriez faire quelque chose comme ceci (à définir un indicateur qui va assigner une valeur lorsque la touche est enfoncée, puis reasign lorsque la touche est en place).
Essayer cette approche:
ou comme Chris suggèrent à l'OP commentaire plus "moderne" async approche.
GetKeyState
est pour les messages lorsque vous avez besoin de l'etat au moment où le message a été envoyé.GetAsyncKeyState
est pour le droit de l'état maintenant. Aussi, 0x80 est 10000000. La documentation dit la haute bit sera fixé si c'est en bas, et qu'il retourne à court, donc 1000000000000000, ou 0x8000.if (WM_KEYDOWN) { switch (code) { case SPACE: if (last == UP) DoSomething(); ... } }
et de définir l'état à l'aide deWM_KEYDOWN
etWM_KEYUP
messages. Un crochet ne devrait pas être appelé jusqu'à ce que les actions du clavier se produire de trop; il devrait être ralenti autrement.J'ai eu le même problème. J'ai plusieurs clés qui agissent comme des boutons à bascule et ne voulez enregistrer la clé des événements une fois par la presse. Ma solution a été de faire un simple objet pour gérer la logique. Cela permet de maintenir le code principal propre:
Et ici est l'utilisation:
Je pense que vous préférez pour l'exécution de vos fonctions de "une fois" que lorsque vous avez sorti vos clés, pas quand vous avez déprimé (pressé) vers le bas.
Vous n'avez pas besoin de drapeaux et d'assistance variables à définir, d'allouer, d'attribuer à 0, et de mettre chacun à 1 et remis à 0 et ainsi de suite, afin d'atteindre cet objectif. Tout ce que vous avez besoin est juste: d'Abord, vous devez utiliser GetKeyState fonction à l'intérieur de la portée de tout(1) à vérifier lorsque vous avez déprimé une clé. Lorsque l'expression renvoie true, l'exécuteur pointeur (la flèche qui effectuent une ligne de code et procède ensuite à la prochaine ligne de code soit lors de l'étape ou étape de plus) va entrer dans le si de l'énoncé de la portée. Puis, immédiatement, de l'emprisonner à l'intérieur d'une boucle et de le garder emprisonné, tandis que la clé que vous avez déprimé est toujours vers le bas et d'arrêter avant qu'il s'apprête à exécuter la fonction et de le libérer lorsque vous avez sorti la touche vers le haut et laissez-le ensuite pour exécuter la fonction.
Par exemple, pour exécuter la DoSpaceKeyTask fonction seulement "une fois" quand vous avez déprimé et publié sur la barre d'espace, puis effectuez les opérations suivantes code qui devrait fonctionner:
Tout de même avec la DoOtherKeyTask fonction:
Si vous avez déjà utilisé soit BT_ de l'idée ou de Pawel Zubrycki idée, et maintenant vous voulez utiliser mon idée, alors vous pouvez supprimer tous les indicateurs et les variables qu'ils ont suggérées, parce que vous n'avez pas besoin de plus.
Par le chemin, j'ai déjà essayé le code que Pawel Zubrycki posté, mais il ne fonctionne pas pour moi. La sortie qui dit que j'ai pressé soit la barre d'espace ou des autres n'était pas affiché lorsque j'ai vraiment appuyé sur la barre d'espace ou d'autres clés que j'ai choisi.
Je sais que c'est assez vieux thread mais j'ai encore envie de partager ma solution. Je pense que la création d'une sorte de "flags" ou "active" n'est pas vraiment nécessaire. Voici mon code de bouclage tous les codes de touches:
Comme vous pouvez le voir, vous pouvez facilement simplement utiliser tout en et la même GetKeyState fonction d'attendre la clé unpress. Solution beaucoup plus simple.
Vous voulez un windows crochet à crochet le jeu et de réagir à l'entrée de clavier que le jeu devient. Maintenant, je n'ai pas vraiment fait ce type de crochet, mais je peux vous donner une bonne idée de l'écoulement. Je vais laisser à vous de couper l'espace en parcourant une carte de touches dont vous avez besoin, plutôt que d'un énorme répétitif, commutateur, et aussi pour les petites pliures je l'ai mis dans.
Note comment je
last [KEY_ONE]
. Je vous conseille d'utiliser unstd::map
pour stocker les clés dont vous avez besoin en leur vk code. Ensuite, vous pouvez simplement faire une boucle par la carte et les couper vers le bas beaucoup d'espace que d'un interrupteur pour le faire.