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?
Asked
Active
Viewed 110 times
0
-
1You should be more specific about your OS-GUI API. I guess it's [tag:winapi]? – πάντα ῥεῖ Mar 13 '23 at 19:18
-
yup. It isn't a real GUI tho as it is all rendered inside a command prompt console as characters instead of a window – Norzka Mar 13 '23 at 20:41
-
1Why is there a hook at all, a low-level hook of all things? Would probably be helpful to invest some more time into understanding the problem you are trying to solve. – IInspectable Mar 13 '23 at 21:48
-
I need the hook so I am able to track the position of the mouse so I can determine if the mouse is on clickable object, then the hook also allows me to see if the mouse press was on the clickable object at which point I call an event call back for that object. Thats how I thought of solving this problem but if you got any other ideas then feel free to tell me – Norzka Mar 13 '23 at 22:25
-
If you want to implement a text-mode GUI with mouse support you don't need any hooks. Just have the system [tell you](https://learn.microsoft.com/en-us/windows/console/readconsoleinput) when something interesting happened. – IInspectable Mar 14 '23 at 15:14
2 Answers
2
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.

Remy Lebeau
- 555,201
- 31
- 458
- 770
-
How would I make it not block while waiting for input/message? with the `while(GetMessage(&msg,0,0,0,){}` loop, it doesn't actually seem to execute anything inside the loop like I expected it to – Norzka Mar 13 '23 at 19:24
-
1In this case, `GetMessage()` will not return, because it has no messages to give you. However, it will still *dispatch system messages* internally, such as messages used by the mouse hook. Try using `PeekMessage()` instead, which won't block the calling thread. Also, maybe use `GetQueueStatus()` or `MsgWaitForMultipleObjects()` to check if there are actually pending messages in the message queue before then calling `PeekMessage()` to process them. – Remy Lebeau Mar 13 '23 at 19:28
-
would you have any use cases of either (preferably both) since I am trying to find online how I would use it and nothing useful is coming up – Norzka Mar 13 '23 at 20:49
1
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]

Andreas Wenzel
- 22,760
- 4
- 24
- 39