So I am trying to create a console button base (using low level mouse hook) for a console menu (which uses arrow keys and enter key for controls) that I have created before and both work fine alone but I have ran into a couple issues. the mouse hook requires (from what I understand) a message loop inorder to work which inturn blocks the thread and the menu requires the thread to not be blocked so it can take input from the keyboard and update the menu on screen. And so how would I get around this?
C++ How to allowing for Low Level Mouse callback to get called in a loop/ when wait for input
155 views Asked by Norzka At
2
There are 2 answers
0
On
Based on your description in the comments section of what you want to accomplish, you do not need a low-level mouse hook.
Instead, you can use the function ReadConsoleInput to wait for both keyboard and mouse events.
Here is an example:
#include <Windows.h>
#include <iostream>
#include <cctype>
void HandleKeyEvent( const KEY_EVENT_RECORD &key_event );
void HandleMouseEvent( const MOUSE_EVENT_RECORD &mouse_event );
int main( void )
{
HANDLE hStdin;
INPUT_RECORD input[128];
DWORD num_input;
hStdin = GetStdHandle( STD_INPUT_HANDLE );
SetConsoleMode( hStdin, ENABLE_MOUSE_INPUT );
while ( ReadConsoleInput( hStdin, input, sizeof input / sizeof *input, &num_input ) )
{
for ( DWORD i = 0; i < num_input; i++ )
{
switch ( input[i].EventType )
{
case KEY_EVENT:
HandleKeyEvent( input[i].Event.KeyEvent );
break;
case MOUSE_EVENT:
HandleMouseEvent( input[i].Event.MouseEvent );
break;
}
}
}
std::cerr << "Error calling ReadConsoleInput!\n";
}
void HandleKeyEvent( const KEY_EVENT_RECORD &key_event )
{
std::cout << "Key ";
if ( std::isprint( static_cast<unsigned char>(key_event.uChar.AsciiChar) ) )
std::cout << (char)std::toupper( static_cast<unsigned char>(key_event.uChar.AsciiChar) );
else
std::cout << "<unprintable>";
if ( key_event.bKeyDown)
{
std::cout << " down!\n";
}
else
{
std::cout << " up!\n";
}
}
void HandleMouseEvent( const MOUSE_EVENT_RECORD &mouse_event )
{
switch ( mouse_event.dwEventFlags )
{
case MOUSE_MOVED:
std::cout << "Mouse moved to [" << mouse_event.dwMousePosition.X << "," << mouse_event.dwMousePosition.Y << "]\n";
break;
case 0:
case DOUBLE_CLICK:
if ( mouse_event.dwButtonState )
std::cout << "At least one mouse button down at [" << mouse_event.dwMousePosition.X << "," << mouse_event.dwMousePosition.Y << "]\n";
else
std::cout << "All mouse buttons up at [" << mouse_event.dwMousePosition.X << "," << mouse_event.dwMousePosition.Y << "]\n";
break;
}
}
Here is an example output of that program:
Key W down!
Key W up!
Key A down!
Key A up!
Key D down!
Key D up!
Key S down!
Key S up!
Mouse moved to [16,1]
Mouse moved to [16,1]
Mouse moved to [16,1]
Mouse moved to [16,1]
Mouse moved to [16,1]
Mouse moved to [16,1]
Mouse moved to [16,1]
Mouse moved to [16,1]
Mouse moved to [16,1]
Mouse moved to [16,1]
Mouse moved to [16,1]
Mouse moved to [17,1]
Mouse moved to [17,1]
Mouse moved to [17,1]
Mouse moved to [17,1]
Mouse moved to [17,1]
Mouse moved to [17,1]
Mouse moved to [17,2]
Mouse moved to [17,3]
Mouse moved to [17,4]
Mouse moved to [17,5]
Mouse moved to [17,6]
Mouse moved to [17,7]
Mouse moved to [18,8]
Mouse moved to [18,9]
Mouse moved to [18,10]
Mouse moved to [18,11]
Mouse moved to [18,12]
Mouse moved to [18,13]
Mouse moved to [18,14]
Mouse moved to [18,15]
Mouse moved to [18,16]
Mouse moved to [18,17]
Mouse moved to [18,18]
Mouse moved to [19,19]
Mouse moved to [19,20]
Mouse moved to [19,21]
Mouse moved to [19,22]
Mouse moved to [19,23]
Mouse moved to [19,24]
Mouse moved to [19,25]
Mouse moved to [19,26]
Mouse moved to [19,27]
Mouse moved to [19,28]
Mouse moved to [20,29]
Mouse moved to [20,30]
Mouse moved to [20,31]
Mouse moved to [20,32]
Mouse moved to [20,33]
Mouse moved to [20,34]
Mouse moved to [20,35]
Mouse moved to [20,36]
Mouse moved to [20,37]
Mouse moved to [20,38]
Mouse moved to [21,39]
Mouse moved to [21,40]
Mouse moved to [21,41]
Mouse moved to [21,42]
At least one mouse button down at [21,43]
All mouse buttons up at [21,44]
Simply use separate threads. Run your menu in one thread (ie, the main thread), and run the mouse hook in another thread.
Otherwise, you can run everything in the main thread, simply code your message loop and input handling in such a way that they don't block the thread while waiting for messages/input to arrive, let them return to your code periodically so that you can do other work.