Search code examples
c++windowswinapi

Precise key press event handling in console


I am coding this console app that updates the console every 500 millisecond. while it does that I want to set up a few key press actions. But using the following method is not precise and it misses a lot of key presses. Is it possible to have better precision?

I tried this:

void processInput() {
    if (GetAsyncKeyState(VK_LEFT) & 0x8000) {
        x_position--;
        detectCollision(positions);
    }
    if (GetAsyncKeyState(VK_RIGHT) & 0x8000) {
        x_position++;
        detectCollision(positions);
    }
    if (GetAsyncKeyState(VK_SPACE) & 0x8000) {
        rotate();
        detectCollision(positions);
    }
}

void setInterval(int interval) {
    while (true) {
        processInput();
        this_thread::sleep_for(chrono::milliseconds(interval));
    }
}

int main()
{
    int interval = 1;
    thread periodicThread(setInterval, interval);
    periodicThread.join();
}

Solution

  • Not just ReadConsoleInput, you need to use KEY_EVENT_RECORD struct from INPUT_RECORD struct. It indicates that the event is a keyboard event. At this point, the Avant member will contain a base_evante_record structure that provides detailed information about keyboard events, such as whether a key was pressed, the number of times the key was repeated, the virtual keycode, the virtual scan code, the Unicod or Assi character representation, and the status of the control key.

    See the code:

    #include <iostream>
    #include <windows.h>
    
    int main() {
        HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
        if (hStdin == INVALID_HANDLE_VALUE) {
            std::cerr << "GetStdHandle error\n";
            return 1;
        }
    
        const int maxEvents = 128;
        INPUT_RECORD irInBuf[maxEvents];
        DWORD cNumRead;
    
        while (true) {        
            if (!ReadConsoleInput(hStdin, irInBuf, maxEvents, &cNumRead)) {
                std::cerr << "ReadConsoleInput error\n";
                return 1;
            }
    
            for (DWORD i = 0; i < cNumRead; ++i) {
                if (irInBuf[i].EventType == KEY_EVENT) {
                    KEY_EVENT_RECORD& ker = irInBuf[i].Event.KeyEvent;
                    if (ker.bKeyDown) 
                 { 
       std::cout << "Key Pressed: " << ker.wVirtualKeyCode << std::endl;
                    }
                }
            }
        }
        return 0;
    }