#include <windows.h>
#include <stdio.h>
 
// Prototypes
void ErrorExit(LPSTR);
void KeyEventProc(KEY_EVENT_RECORD);
void MouseEventProc(MOUSE_EVENT_RECORD);
void ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD);
 
int wmain(int argc, WCHAR **argv)
{
    HANDLE hStdin;
    DWORD cNumRead, fdwMode, fdwSaveOldMode, 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()");
      else
            wprintf(L"GetStdHandle() is OK!\n");
 
    // Save the current input mode, to be restored on exit.
    if (!GetConsoleMode(hStdin, &fdwSaveOldMode) )
        ErrorExit("GetConsoleMode()");
      else
            wprintf(L"GetConsoleMode() is OK!\n");
 
    // Enable the window and mouse input events.
    fdwMode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT;
    if (!SetConsoleMode(hStdin, fdwMode))
        ErrorExit("SetConsoleMode()");
      else
            wprintf(L"SetConsoleMode() is OK!\n");
 
    // Loop to read and handle the input events.
    while (counter++ <= 30)
    {
        // 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()");
            else
                  wprintf(L"ReadConsoleInput() is OK!\n");
 
        // 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);
                    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;
            }
        }
    }
    return 0;
}
 
void ErrorExit (LPSTR lpszMessage)
{
    fwprintf_s(stderr, L"%s\n", lpszMessage);
    ExitProcess(0);
}
 
void KeyEventProc(KEY_EVENT_RECORD ker)
{
    wprintf(L"  Key event: ");
 
    if(ker.bKeyDown)
        wprintf(L"key pressed!\n");
    else
            wprintf(L"key released!\n");
}
 
void MouseEventProc(MOUSE_EVENT_RECORD mer)
{
    wprintf(L"  Mouse event: ");
   
    switch(mer.dwEventFlags)
    {
        case 0:
            wprintf(L"button press!\n");
            break;
        case DOUBLE_CLICK:
            wprintf(L"double click!\n");
            break;
        case MOUSE_HWHEELED:
            wprintf(L"horizontal mouse wheel!\n");
            break;
        case MOUSE_MOVED:
            wprintf(L"mouse moved!\n");
            break;
        case MOUSE_WHEELED:
            wprintf(L"vertical mouse wheel!\n");
            break;
        default:
            wprintf(L"unknown\n");
            break;
    }
}
 
VOID ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD wbsr)
{
    wprintf(L"Resize event!\n");
}
 
