По сути, выходные данные, возвращаемые GetAsyncKeyState (...), находятся на более низком уровне, чем вы хотите, если вас интересует семантически богатое действие пользователя, такое как «щелчок».GetAsyncKeyState (...) буквально просто сообщает вам, является ли клавиша вверх или вниз в этот момент - это не то, что вы хотите зациклить, потому что работающие компьютерные программы выполняются во множестве отдельных моментов.
Вам нужно «разобрать» эти изменения состояния в нужные вам действия пользователя с помощью простого конечного автомата.Будет работать что-то вроде следующего.Я включил логическое значение для запуска цикла сообщений, потому что если вы попытаетесь использовать это в приложении с графическим интерфейсом, все приложение будет зависать, пока оно ожидает ключа.Добавьте в цикл сообщений в качестве упражнения.Расширьте это для поддержки двойного щелчка в качестве еще одного упражнения.
class KeyListener
{
private:
enum class State {
Preclick,
ClickInProgress,
ClickComplete
};
int vkey_;
State state_;
bool isDown() const
{
return GetAsyncKeyState(vkey_) & 0x8000;
}
State UpdateState()
{
switch (state_) {
case State::Preclick:
state_ = (isDown()) ? State::ClickInProgress : State::Preclick;
break;
case State::ClickInProgress:
state_ = (isDown()) ? State::ClickInProgress : State::ClickComplete;
break;
case State::ClickComplete:
state_ = (isDown()) ? State::ClickInProgress : State::Preclick;
break;
}
return state_;
}
public:
KeyListener(int vkey) : vkey_(vkey)
{
Reset();
}
void Reset()
{
state_ = (!isDown()) ? State::Preclick : State::ClickInProgress;
}
void WaitForClick(bool pump_messages = false)
{
while (UpdateState() != State::ClickComplete)
if (pump_messages) {
// .. put a message loop here.
}
}
};
int main()
{
KeyListener clicky(VK_SPACE);
std::cout << "Try clicking the space bar" << std::endl;
while (true)
{
clicky.WaitForClick();
std::cout << "<Space bar click>" << std::endl;
}
return 0;
}