C++ WinAPI Console Mouse Handler

During one of my college courses, I ran into several assignments in which I wished to use mouse input in the console.  Searching around on the internet gave me a good start on how to handle mouse input with WinAPI, but a lot of the implementations I found were pretty broken, firing off multiple mouse click events for a single click, totally thrashing the WinAPI InuptEvent queue, and other various nonsense.  Also, I wanted to maintain a state machine so that I could tell if a button was held, or when it was released, in addition to just handling the initial click.  I also wanted to handle double-click events, since they are supported natively through the API.  So, after fighting through these issues and digging through the WinAPI documentation in order to figure out what was causing them, here is my final, elegant solution for a console mouse handler:

HANDLE Mouse::m_stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
COORD Mouse::m_pos = Mouse::Coord(0, 0);
DWORD Mouse::m_state = 0;
DWORD Mouse::m_modifier_key_flags = 0;
DWORD Mouse::m_event_flags = 0;
DWORD Mouse::m_clicked = 0;
DWORD Mouse::m_held = 0;
DWORD Mouse::m_released = 0;


void Mouse::RefreshMouseInfo(bool wait_for_input)
{
DWORD EventCount;
DWORD NumRead;
INPUT_RECORD EventRecord;


do
{
GetNumberOfConsoleInputEvents(m_stdin_handle, &EventCount);
if(EventCount || wait_for_input)
ReadConsoleInput(m_stdin_handle, &EventRecord, 1, &NumRead);
}
while((EventCount || wait_for_input) && (EventRecord.EventType != MOUSE_EVENT));


//Check if the current event is a mouse event
if ((EventCount || wait_for_input) && EventRecord.EventType == MOUSE_EVENT)
{
m_pos = EventRecord.Event.MouseEvent.dwMousePosition;
m_state = EventRecord.Event.MouseEvent.dwButtonState;
m_modifier_key_flags = EventRecord.Event.MouseEvent.dwControlKeyState;
m_event_flags = EventRecord.Event.MouseEvent.dwEventFlags;
}


m_released = ~m_state & m_held;
m_held = m_state & (m_clicked | m_held);
m_clicked = m_state & ~m_held;
}


This isn't the entire Mouse class, but it is the entire driver function.  Everything else in the class is just a bunch of getter functions for simplifying the reading of the data.  Call this function once per loop in your main application loop, and you can easily handle single and double clicks, get which mouse buttons have been held, handle button releases, check whether or not modifier keys such as Ctrl, Shift, and Alt were held during the last button event, get the current coordinates of the cursor.  Also, all of the button checks can be done for each button of the mouse separately, up to a ridiculously large number of mouse buttons (32, I believe...).  The wait_for_input parameter determines whether or not this function call will block if there are no events available.  Specifying true will cause the entire program to pause and wait for you to move the mouse or click.  Otherwise, the program will continue as normal and just process the mouse as though nothing has changed (though the state machine will still cycle correctly).  Try both to understand which best fits your application.  I've attached the full .h and .c files to the bottom of the page.
ċ
mouse.zip
(3k)
Ben Whitman,
Nov 10, 2012, 1:52 PM