为什么有时不捕获输入事件,在 C++ 中

why input events are not being captured at sometimes, in c++

#include <Windows.h>
#include <vector>
using std::vector;

class event_handler{
private:
    DWORD n_evnts_read=0,n_evnts=0,evnt_type=0,mode=0;

public:
    int rec_indx = 0;
    vector<INPUT_RECORD> inrec;
    KEY_EVENT_RECORD kev;
    MOUSE_EVENT_RECORD mev;
    HANDLE hndlin = GetStdHandle(STD_INPUT_HANDLE);
    HANDLE hndlout = GetStdHandle(STD_OUTPUT_HANDLE);

    int cap_evnt_key(){

        n_evnts_read = n_evnts = evnt_type = 0;

        GetNumberOfConsoleInputEvents(hndlin, &n_evnts_read);
        if (n_evnts_read){
            inrec.resize(n_evnts_read);
            ReadConsoleInput(hndlin, &inrec[0], inrec.size(), &n_evnts);
            for(DWORD m = 0; m < n_evnts; m++)
                if (inrec[m].EventType == KEY_EVENT)
                {
                    kev = inrec[m].Event.KeyEvent;
                    fflush(stdin);
                    return 5;
                }
        }
        return -1;
    }

    int cap_evnt_mouse(){

        n_evnts_read = n_evnts = evnt_type = mode = 0;

        GetNumberOfConsoleInputEvents(hndlin, &n_evnts_read);
        if (n_evnts_read){
            inrec.resize(n_evnts_read);
            ReadConsoleInput(hndlin, &inrec[0], inrec.size(), &n_evnts);
            for(DWORD m = 0; m < n_evnts; m++)
                if (inrec[m].EventType == MOUSE_EVENT)
                {
                    mev = inrec[m].Event.MouseEvent;
                    fflush(stdin);
                    return 5;
                }
        }
        return -1;
    }

    DWORD key(){
        if (!kev.bKeyDown)
            return kev.wVirtualKeyCode;
        else
            return 0;
    }

    bool left_click(){
        if (mev.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
            return 1;
        else
            return 0;
    }
} evnt_hndlr;   

void test()
{
    short n = 0;
    COORD pos;

    while (1)
    {
        if (evnt_hndlr.cap_evnt_key() == 5)
        {
            if (evnt_hndlr.key() == VK_RIGHT)
                //do something
            else if (evnt_hndlr.key() == VK_LEFT)
                //do something
        }
        else if (evnt_hndlr.cap_evnt_mouse() == 5)
        {
            if (evnt_hndlr.left_click() == 1)
                //do something
        }
    }
    exit(0);
}

现在,当我在 main() 中 运行 test() 并尝试捕获一个 mouse/keyboard 事件时,有时它会给我一个信号,表明所需的事件已被捕获,但有时它会错过那个事件。

请给我一个可靠的捕获输入事件的方法(特别是当需要同时读取鼠标和键盘事件时),因为这个程序挂了(如果我没有使用错误的话)。另外,请向我解释为什么会出现此问题。这对用户来说确实很糟糕。

您没有处理读取的每个事件。您的代码有可能丢弃很多事件。每次调用 cap_evnt_...() 时,如果有任何新事件可供读取,则将已读取的所有事件丢弃到 vector 中但尚未处理。

尝试更像这样的东西:

#include <Windows.h>
#include <vector>

class event_handler{
private:
    std::vector<INPUT_RECORD> evnts;
    INPUT_RECORD inrec;
    HANDLE hndlin = GetStdHandle(STD_INPUT_HANDLE);
    HANDLE hndlout = GetStdHandle(STD_OUTPUT_HANDLE);

public:
    int cap_evnt_read() {
        if (evnts.empty()) {
            DWORD n_evnts = 0;
            GetNumberOfConsoleInputEvents(hndlin, &n_evnts);
            if (n_evnts == 0) return -1;
            evnts.resize(n_evnts);
            ReadConsoleInput(hndlin, &evnts[0], n_evnts, &n_evnts);
        }
        inrec = evnts.front();
        evnts.erase(events.begin());
        return inrec.EventType;
    }

    DWORD key() const {
        if (!inrec.Event.KeyEvent.bKeyDown)
            return inrec.Event.KeyEvent.wVirtualKeyCode;
        else
            return 0;
    }

    bool left_click() const {
        return (inrec.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED);
    }
}
evnt_hndlr;   

void test()
{
    while (true)
    {
        switch (evnt_hndlr.cap_evnt_read())
        {
            case KEY_EVENT:
            {
                if (evnt_hndlr.key() == VK_RIGHT)
                    // do something
                else if (evnt_hndlr.key() == VK_LEFT)
                    // do something
                break;
            }

            case MOUSE_EVENT:
            {
                if (evnt_hndlr.left_click())
                    // do something
                break;
            }
       }
    }
    exit(0);
}