Windows - Få mus og tastaturindgange i konsol C ++

Indlæg af Hanne Mølgaard Plasc

Problem



Hvordan får du mus og tastatur input i Windows C + + konsol applikation?
Er der nogen tilbagekaldelse, som vi kan registrere for at få input?


Også ved hjælp af ReadConsoleInput API er et blokerende opkald, så for at fortsætte med at få input og lave baggrundsopgaver, skal jeg bruge tråde. Er der nogen ikke-blokkerende APIS for at få input

Bedste reference


Det ser ud til, at PeekConsoleInput ikke blokkerer, så hvis du vil afstemme regelmæssigt, kan du bruge det og kun kalde ReadConsoleInput til, når du ved, at der er input til rådighed.
Der er også GetNumberOfConsoleInputEvents. [4] [5]

Andre referencer 1


Der er GetAsyncKeyState, som både er til tastaturet og musen. [6]

Andre referencer 2


Indtast billedbeskrivelse her [7]


Brug konsolens egen arrangementshåndterer til tastatur og mus - ReadConsoleInput( )


Læs mere her https://msdn.microsoft.com/en-us/library/windows/desktop/ms685035(v=vs.85).aspx[8]


#include <iostream>
#include <stdio.h>
#include <windows.h>


HANDLE hStdin; 
DWORD fdwSaveOldMode;

void ErrorExit(LPSTR);
void KeyEventProc(KEY\_EVENT\_RECORD); 
void MouseEventProc(MOUSE\_EVENT\_RECORD); 
void ResizeEventProc(WINDOW\_BUFFER\_SIZE\_RECORD);
void GetMousePosWin(MOUSE\_EVENT\_RECORD);
void gotoXY(int x, int y);

HANDLE console = GetStdHandle(STD\_OUTPUT\_HANDLE);
COORD CursorPosition;



int main() 
{ 
    DWORD cNumRead, fdwMode, i; 
    INPUT\_RECORD irInBuf[128]; 
    int counter=0;

    // Get the standard input handle. 

    hStdin = GetStdHandle(STD\_INPUT\_HANDLE); 
    if (hStdin == INVALID\_HANDLE\_VALUE) 
        ErrorExit("GetStdHandle"); 

    // Save the current input mode, to be restored on exit. 

    if (! GetConsoleMode(hStdin, &fdwSaveOldMode) ) 
        ErrorExit("GetConsoleMode"); 

    // Enable the window and mouse input events. 

    fdwMode = ENABLE\_WINDOW\_INPUT | ENABLE\_MOUSE\_INPUT; 
    if (! SetConsoleMode(hStdin, fdwMode) ) 
        ErrorExit("SetConsoleMode"); 

    // Loop to read and handle the next 100 input events. 
    gotoXY(33,10);
    std::cout << "xDB Menu Item 1";
    gotoXY(33,12);
    std::cout << "xDB Menu Item 2";
    gotoXY(33,14);
    std::cout << "xDB Menu Item 3";
    gotoXY(33,16);
    std::cout << "xDB Quit";
    while (!counter)//++ <= 200) 
    { 
        // Wait for the events. 

        if (! ReadConsoleInput( 
            hStdin,      // input buffer handle 
            irInBuf,     // buffer to read into 
            128,         // size of read buffer 
            &cNumRead) ) // number of records read 
            ErrorExit("ReadConsoleInput"); 

        // Dispatch the events to the appropriate handler. 

        for (i = 0; i < cNumRead; i++) 
        {
            switch(irInBuf[i].EventType) 
            { 
            case KEY\_EVENT: // keyboard input 
                KeyEventProc(irInBuf[i].Event.KeyEvent); 
                break; 

            case MOUSE\_EVENT: // mouse input 
                MouseEventProc(irInBuf[i].Event.MouseEvent);
                gotoXY(33,8);
                GetMousePosWin(irInBuf[i].Event.MouseEvent);
                break; 

            case WINDOW\_BUFFER\_SIZE\_EVENT: // scrn buf. resizing 
                ResizeEventProc( irInBuf[i].Event.WindowBufferSizeEvent );
                break; 

            case FOCUS\_EVENT:  // disregard focus events 

            case MENU\_EVENT:   // disregard menu events 
                break; 

            default: 
                ErrorExit("Unknown event type"); 
                break; 
            } 
        }
    } 

    // Restore input mode on exit.

    SetConsoleMode(hStdin, fdwSaveOldMode);

    return 0; 
}

VOID ErrorExit (LPSTR lpszMessage) 
{ 
    fprintf(stderr, "\%s
", lpszMessage); 

    // Restore input mode on exit.

    SetConsoleMode(hStdin, fdwSaveOldMode);

    ExitProcess(0); 
}

VOID KeyEventProc(KEY\_EVENT\_RECORD ker)
{
    printf("Key event: ");

    if(ker.bKeyDown)
        printf("key pressed");
    else printf("key released");
}

VOID MouseEventProc(MOUSE\_EVENT\_RECORD mer)
{
#ifndef MOUSE\_HWHEELED
#define MOUSE\_HWHEELED 0x0008
#endif

    gotoXY(33,6);
    printf("Mouse event:                                               ");

    switch(mer.dwEventFlags)
    {

    case 0:
        if(mer.dwButtonState == FROM\_LEFT\_1ST\_BUTTON\_PRESSED)
        {
            gotoXY(46,6);
            printf("left button pressed");
        }
        else if(mer.dwButtonState == RIGHTMOST\_BUTTON\_PRESSED)
        {
            gotoXY(46,6);
            printf("right button pressed");
        }
        else
        {
            gotoXY(46,6);
            printf("button press");
        }
        break;
    case DOUBLE\_CLICK:
        gotoXY(46,6);
        printf("double click");
        break;
    case MOUSE\_HWHEELED:
        gotoXY(46,6);
        printf("horizontal mouse wheel");
        break;
    case MOUSE\_MOVED:
        gotoXY(46,6);
        printf("mouse moved");
        //gotoXY(12,13);
        //GetMousePosWin();
        break;
    case MOUSE\_WHEELED:
        gotoXY(46,6);
        printf("vertical mouse wheel");
        break;
    default:
        gotoXY(46,6);
        printf("unknown");
        break;
    }

}

// get Window pos through windows api
void GetMousePosWin(MOUSE\_EVENT\_RECORD mer)
{
    int x,y;
    // creates the handle i need to use
    //HANDLE OutputH;
    INPUT\_RECORD Inrec;
    DWORD evRead;
    HANDLE hStdIn;
    DWORD dwMode;
    bool Captured=false;

    hStdIn = GetStdHandle(STD\_INPUT\_HANDLE);
    dwMode = ENABLE\_WINDOW\_INPUT | ENABLE\_MOUSE\_INPUT;

    if( SetConsoleMode( hStdIn, dwMode | ENABLE\_MOUSE\_INPUT) == TRUE)

        GetConsoleMode(hStdIn, &dwMode);
        SetConsoleMode(hStdIn, (dwMode & (ENABLE\_MOUSE\_INPUT)));

        // grab the handle to the console so i can use it
        //OutputH = GetStdHandle(STD\_OUTPUT\_HANDLE);
        //printf("Strated"); //Debug line.

        do
        {
            PeekConsoleInput(hStdIn, &Inrec, 1, &evRead);

            if( evRead ) 
            { 
                ReadConsoleInput(hStdIn, &Inrec, 1, &evRead);
                x= Inrec.Event.MouseEvent.dwMousePosition.X ;
                y= Inrec.Event.MouseEvent.dwMousePosition.Y ;
                switch (Inrec.EventType )
                {

                case MOUSE\_EVENT:
                    {
                        Captured = true;
                        gotoXY(33,8);
                        std::cout << "x->  " << x << " ";
                        gotoXY(43,8);
                        std::cout << "y->  " << y << " ";
                        break;  
                    }
                }
            }

        }while(!Captured);

    if((x==33 && y==10) && mer.dwButtonState == FROM\_LEFT\_1ST\_BUTTON\_PRESSED)
    {
        gotoXY(47,10);
        std::cout << "xFB";
        gotoXY(33,21);
        std::cout << "You picked menu one";
        Sleep(1200);
        gotoXY(47,10);
        std::cout << " ";
        gotoXY(33,21);
        std::cout << "                   ";
    }
    if((x==33 && y==12) && mer.dwButtonState == FROM\_LEFT\_1ST\_BUTTON\_PRESSED)
    {
        gotoXY(47,12);
        std::cout << "xFB";
        gotoXY(33,21);
        std::cout << "You picked menu two";
        Sleep(1200);
        gotoXY(47,12);
        std::cout << " ";
        gotoXY(33,21);
        std::cout << "                   ";
    }
    if((x==33 && y==14) && mer.dwButtonState == FROM\_LEFT\_1ST\_BUTTON\_PRESSED)
    {
        gotoXY(47,14);
        std::cout << "xFB";
        gotoXY(33,21);
        std::cout << "You picked menu three";
        Sleep(1200);
        gotoXY(47,14);
        std::cout << " ";
        gotoXY(33,21);
        std::cout << "                     ";
    }
    if((x==33 && y==16) && mer.dwButtonState == FROM\_LEFT\_1ST\_BUTTON\_PRESSED)
    {
        gotoXY(40,16);
        std::cout << "xFB";
        gotoXY(33,21);
        std::cout << "You picked Quit";
        Sleep(1200);
        gotoXY(40,16);
        std::cout << " ";
        gotoXY(28,21);
        exit(0);
    }
}

VOID ResizeEventProc(WINDOW\_BUFFER\_SIZE\_RECORD wbsr)
{
    printf("Resize event
");
    printf("Console screen buffer is \%d columns by \%d rows.
", wbsr.dwSize.X, wbsr.dwSize.Y);
}

void gotoXY(int x, int y) 
{ 
    CursorPosition.X = x; 
    CursorPosition.Y = y; 
    SetConsoleCursorPosition(console,CursorPosition); 
}