Mouse and console

Apr 18, 2012 at 4:01pm
I've got this code for mouse clicking, getting x,y...
now when I put this in:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
for(;;)
{
if(_kbhit())
{
//do something
}
else if(MouseClick())
{
//do something else
}
}
//...
bool MouseClick()
{
	GetNumberOfConsoleInputEvents(rHnd, &num_events);
	if(num_events!=0)
	{
		INPUT_RECORD *eventBuffer = new INPUT_RECORD[num_events];
		ReadConsoleInput(rHnd, eventBuffer, num_events, &num_events_read);
		for (DWORD i = 0; i < num_events_read; ++i)
		{
			if(eventBuffer[i].EventType == MOUSE_EVENT)
			{
				if (eventBuffer[i].Event.MouseEvent.dwButtonState==FROM_LEFT_1ST_BUTTON_PRESSED)
				{
					X=eventBuffer[i].Event.MouseEvent.dwMousePosition.X;
					Y=eventBuffer[i].Event.MouseEvent.dwMousePosition.Y;
					num_events=0;
					num_events_read=0;
					return true;
				}
            }
          }
	delete[] eventBuffer;
	}
	return false;
}

It always works with detecting click, but even if you don't use the mouse the keyboard input doesn't detect every keypress...anyone got an idea why this happens?
Apr 18, 2012 at 5:07pm
It is my understanding that _kbhit() is a function that asynchronously tells you if a key has been hit and it doesn't intend to be in synchrony with every single key press. In other words, you are not guaranteed to get one true for every key hit.

What you need is a different function, but don't ask me as I don't know which one. Google up a bit.
Last edited on Apr 18, 2012 at 5:08pm
Apr 18, 2012 at 5:13pm
the funny thing is, that if I remove the mouse part of code, it works...
Apr 18, 2012 at 5:45pm
ReadConsoleInput() reads all selected console events, including key events. Your mouse code ignores all events not 'mouse'. Also, you are probably experiencing conflicts between the native API and the conio.h _getch() function.

What you should be doing is using ReadConsoleInput() in your main loop and switching off of the event type to the appropriate event handler.

Hope this helps.
Apr 19, 2012 at 6:09am
so I should use ReadConsoleInput() to get the keys also?
Apr 19, 2012 at 2:12pm
Yes. Your loop should be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// pseudocode //

SetConsoleMode( unbuffered + get_mouse_events );

while (!done)
  {
  ReadConsoleInput( user_input );
  switch (user_input.EventType)
    {
    case KEY_EVENT:
      done = handle_key_event( user_input.Event.KeyEvent );
      break;

    case MOUSE_EVENT:
      done = handle_mouse_event( user_input.Event.MouseEvent );
      break;

    case WINDOW_BUFFER_SIZE_EVENT:
      handle_size_event( user_input.Event.WindowBufferSizeEvent );
      break;

    ...
    }
  }

SetConsoleMode( restore );

[edit] Where handle_foo_event() are functions you have elsewhere in your code.

Hope this helps.
Last edited on Apr 19, 2012 at 2:13pm
Apr 19, 2012 at 2:29pm
thanks! just curious, what does SetConsoleMode() do? the microsoft page is kinda cheap with explanations...
Apr 19, 2012 at 2:46pm
I don't know what you mean by "cheap". It is very extensive and explicit.

Since you are trying to get unbuffered, no-echo input, you need to set the console input mode to not wait until the user presses ENTER to send input to the user. Also, you want to tell the console to give you mouse events.

Your startup code should look something like this:

1
2
3
4
5
6
7
8
9
10
11
HANDLE hInput = GetStdHandle( STD_INPUT_HANDLE );
DWORD original_console_mode;
if (!GetConsoleMode( hInput, &original_console_mode ))
  {
  cerr << "You must be a human to use this program.\n";
  return 1;
  }
SetConsoleMode( hInput, ENABLE_MOUSE_INPUT
  // | ENABLE_PROCESSED_INPUT    // Uncomment if you want the user to be able to press ^C to terminate
  // | ENABLE_WINDOW_INPUT       // Uncomment for window size events
  );

Your cleanup code should look something like this:

 
SetConsoleMode( hInput, original_console_mode );

Good luck!
Apr 19, 2012 at 6:14pm
ok, thanks, that's what I wanted to know :)
Topic archived. No new replies allowed.