mouse position in console

need position relative to console window not relative to total screen
My XP computer died, now have windows 10.
DevC++ compiler no longer functions the same.
I have a program that works with yarn - size, weight, length, yards, meters, ounces, grams, etc.
This is very handy for weavers and knitters. It even runs on Windows 98.

It works fine from keyboard, but I would like to add mouse.
I have seen many ways to get pixel xy for entire screen, but not xy relative to the console window.
Because the console window can be any location on the screen, I see no constant.
If there is a way to determine where the window is currently located, that would help.
I want to click on the menu item rather than using the keyboard.

I can put xy for cout() and get xy from where it ends as (character) column/row.
I can get xy for the mouse pointer for the entire screen in xy bit mode.
When clicking on left mouse it puts mark on screen so that much works.
I need to set up a mouseover() function.
Last edited on
Adding mouse support to a console app is not a "write a couple of lines and done" kinda thing. It's just the way Windows (over) does consoles.

Get a better, newer compiler/IDE. Visual Studio, Code::Blocks, or even Embarcadero's Dev-C++ updated clone.

I'd personally recommend VS. C:B or E's Dev-C++ aren't as good at debugging as VS.

There are non-standard libraries/headers that could possibly do what you are looking for. Doing a 'net search might be useful so you can pick and choose what would work for you.
I have the latest Embarcadero DevC++
I downloaded Visual Studio and I would have a huge learning curve. In fact the demo 'hello world' would not compile so my evaluation of Microsoft's software has not improved.
Did you install the C++ package when you installed VS? By default C++ is NOT installed, it has to be manually selected.

It can also be added by modifying the install afterwards.

https://www.learncpp.com/cpp-tutorial/writing-your-first-program/

https://docs.microsoft.com/en-us/cpp/build/vscpp-step-1-create?view=msvc-170

Dev-C++, even the Embarcadero version, is crippled big time for C++ support. C++11 only, no C++ 14/17/20 available even though the underlying compiler suite would be capable of using later language standards. You can set the GNU language standard higher, though it is not standard C++.

What you are wanting to do, adding mouse support to a console window, will be a huge learning curve no matter what compiler tool chain you use. What you are wanting to do is not simple. Hooking into a console app is not for the faint of heart.

Easier would be to delve into WinAPI GUI app creation. Doing that is still a massive "things to learn" undertaking.

Years out of date, but gives a beginners' look at the WinAPI that might work with E's Dev-C++ without too many changes:

theForger's Win32 API Programming Tutorial - http://www.winprog.org/tutorial/

To get an idea just how messy things can get here's an old CPlusPlus article for creating a header-only way to add colors to a Win console:

http://www.cplusplus.com/articles/Eyhv0pDG/
The following program prints the position of the cursor relative to the upper-left corner of the console window's client area. The program reports a device coordinate. Make sure to completely read the documentation for each of the functions used here.

If you are not using Visual Studio, remove the two pragma directives and manually add the libraries kernel32 and user32 to the link line.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <windows.h>
#include <iostream>

#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "user32.lib")

int main()
{
  HWND console_wnd = GetConsoleWindow();
  POINT cursor_pos;
  
  if (GetCursorPos(&cursor_pos))
  {
    if (console_wnd && ScreenToClient(console_wnd, &cursor_pos));
    {
      std::cout << '(' << cursor_pos.x  << ", " << cursor_pos.y << ")\n";
      return 0;
    }
  }

  return 1;
}

Last edited on
looks good, I will try that and let you know. Thanks
If you want mouse support for console programs, then you're probably going to have to deal with the basic console API's for getting/putting events to the console.

See https://docs.microsoft.com/en-us/windows/console/readconsoleinput

and note the structure of INPUT_RECORD which gives access to console mouse events.

https://docs.microsoft.com/en-us/windows/console/input-record-str

Note that if you want to receive mouse events, you have to enable them. See
https://docs.microsoft.com/en-us/windows/console/setconsolemode
and ENABLE_MOUSE_INPUT
Last edited on
Just dug this up, and with some tweaking got it to work....

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#if 0
Program displays mouse position (x,y) in terms of character cells as one moves the mouse. In
addition, it displays whether the left or right button has been clicked.  This output is on
line #2 in upper left corner of console window.  In terms of character output, a keypress is
output on 1st line right above mouse movement displays.
#endif
// cl  Test3.cpp /O1 /Os /MT kernel32.lib                            // 124,416 bytes
// g++ test3.cpp -lkernel32 -oTest3_gcc.exe -mconsole -m64 -s -Os    //  43,008 bytes
// cl  Test3.cpp /O1 /Os /GS- TCLib.lib kernel32.lib                 //   4,608 bytes
//#define TCLib
#include <windows.h>
#ifdef TCLib
   #include "stdio.h"
#else
   #include <stdio.h>
#endif

void cls(HANDLE hStdOut)
{
 CONSOLE_SCREEN_BUFFER_INFO csbi;
 COORD coordScreen = {0,0};
 DWORD cCharsWritten;
 DWORD dwConSize;
 
 GetConsoleScreenBufferInfo(hStdOut, &csbi);
 dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
 FillConsoleOutputCharacter(hStdOut,(TCHAR)' ',dwConSize,coordScreen,&cCharsWritten);
 GetConsoleScreenBufferInfo(hStdOut,&csbi);
 FillConsoleOutputAttribute(hStdOut,csbi.wAttributes,dwConSize,coordScreen,&cCharsWritten);
 SetConsoleCursorPosition(hStdOut,coordScreen);
 
 return;
}

int main(void)
{
 INPUT_RECORD ir[128];
 HANDLE       hStdInput  = NULL;
 HANDLE       hStdOutput = NULL;
 HANDLE       hEvent     = NULL;
 DWORD        nRead;                                                
 COORD        xy;
  
 hStdInput=GetStdHandle(STD_INPUT_HANDLE);
 hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
 cls(hStdOutput);
 SetConsoleMode(hStdInput,ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT|ENABLE_MOUSE_INPUT|ENABLE_EXTENDED_FLAGS);
 FlushConsoleInputBuffer(hStdInput);
 hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);                   //Event is created non-signaled (3rd param).
 HANDLE handles[2] = {hEvent, hStdInput};                     //Program loops monitoring two handles.  The
 while(WaitForMultipleObjects(2,handles,FALSE,INFINITE))      //1st handle ( handles(0) ) is an event which
 {                                                            //is initially set to non-signaled.  The 2nd
   ReadConsoleInput(hStdInput,ir,128,&nRead);                 //handle monitored by WaitForMultipleObjects()
   for(size_t i=0;i<nRead;i++)                                //is the standard input handle set up to
   {                                                          //allow access to mouse/keyboard input.  As
       switch(ir[i].EventType)                                //long as neither handle is in a signaled
       {                                                      //state, WaitForMultipleObjects() will block
        case KEY_EVENT:                                       //in an efficient wait state.  If any keypress
          if(ir[i].Event.KeyEvent.wVirtualKeyCode==VK_ESCAPE) //or mouse movement occurs, WaitForMultiple
             SetEvent(hEvent);                                //Objects will return TRUE and the input will
          else                                                //be read by ReadConsolInput().  If the [ESCAPE]
          {                                                   //key is pressed the event object represented
             xy.X=0;xy.Y=0;                                   //by hEvent will be set to a signaled state by
             SetConsoleCursorPosition(hStdOutput,xy);         //the SetEvent() Api function.  This will be
             printf                                           //picked up by the next WaitForMultipleObjects()
             (                                                //call, and the function will return FALSE and
              "AsciiCode = %d: symbol = %c\n",                //execution will drop out of the while loop
              ir[i].Event.KeyEvent.uChar.AsciiChar,           //and program termination will occur.
              ir[i].Event.KeyEvent.uChar.AsciiChar            //It is important to note that if the 3rd
             );                                               //parameter to WaitForMultipleObjects() is
          }                                                   //set to FALSE, the function will return if
          break;                                              //either of the handles in the HANDLE array
        case MOUSE_EVENT:                                     //represented by handles is signaled.
          xy.X=0, xy.Y=1;                                     
          SetConsoleCursorPosition(hStdOutput,xy);
          printf
          (
           "%.3d\t%.3d\t%.3d",
           ir[i].Event.MouseEvent.dwMousePosition.X,
           ir[i].Event.MouseEvent.dwMousePosition.Y,
           (int)ir[i].Event.MouseEvent.dwButtonState & 0x07   //mask out scroll wheel, which screws up//output
          );
          break;
       }
   }
 };
 
 return 0;
}


It reports the mouse position on the second line of the console window as you move the mouse. The third number is a left mouse button press. If you type a character that shows up (along with the asci code), on the top line. To exit the program properly, use the [ESC] key. Haven't worked with this stuff in ages!!!
Last edited on
Thanks to mbozzi I got it to work. I already am able to acquire the mouse buttons, so that is not included here.

Here is the simple function I added to my program listing.

/* ******************************************************************* */

void mouse (void)
{ // this gives pixel location within the console window
HWND console_wnd = GetConsoleWindow();
POINT cursor_pos;

if (GetCursorPos(&cursor_pos))
{
if (console_wnd && ScreenToClient(console_wnd, &cursor_pos));
{
mouseX = cursor_pos.x; mouseY = cursor_pos.y;
// mouseX and mouseY are globally defined for use throughout the program
}
}
} // now simple math will give character xy and mouseover

/* ****************************************************************** */

I already have included the required *.h files for other functions.

Sorry, I do not remember how to include the program listing to look good like all the others do.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
COORD GetConsoleCursorPosition(HANDLE hConsoleOutput)
{
    CONSOLE_SCREEN_BUFFER_INFO cbsi;
    if (GetConsoleScreenBufferInfo(hConsoleOutput, &cbsi))
    {
        return cbsi.dwCursorPosition;
    }
    else
    {
        // The function failed. Call GetLastError() for details.
        COORD invalid = { 0, 0 };
        return invalid;
    }
}

Sorry, I do not remember how to include the program listing to look good like all the others do.


Link on code tags...

https://www.cplusplus.com/articles/jEywvCM9/
Thanks to freddie1, I now know how to make it look good.

Also thanks to Freddie1, his listing is very complete and better than what I had been doing

Soon all those who work with yarn for weaving or knitting will be able to use the mouse
and not just the keyboard to evaluate their stash.
Glad it helped. Just updated it. Added cls function. I think I have versions of that that uses WaitForSingleObject() instead. Bit simpler perhaps. Want me to look for it an post it?
That might help. Perhaps just send me the web page. I do still have one problem, when I call my mouse() function, it does not always recognize the mouse click on the first try. Any ideas? If I run the program you gave me it sees it every time, but when I try to put it into a separate function - mouse() - sometimes I have to click more than once to get it???? I am only needing Left/Right mouse click and xy. The xy works perfectly every time, but sometimes misses to recognize mouse click. I think the problem is it only looks at button transition not position. I think I will test by putting the button state on screen as I get it.
I have finally reached success. Here is the mouse() function that works

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
38
39
40
41
42
/* ******************************************************************* */

VOID Mouse (void)		// gets mouse position in pixel location full screen - MouseX, MouseY
{					// and character location in console mode- mouseX, mouseY
					// and left / right mouse buttons in either mode
lMouse = false; rMouse = false;
MouseX = 0; MouseY = 0; mouseX = 0; mouseY = 0;  // these are all globally defined

#ifndef MOUSE_HWHEELED
#define MOUSE_HWHEELED 0x0008
#endif

HANDLE hStdInput,hStdOutput;                         
INPUT_RECORD ir[128];                                       
DWORD nRead;                                                
UINT i;
hStdInput = GetStdHandle(STD_INPUT_HANDLE);
hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
FlushConsoleInputBuffer(hStdInput);
SetConsoleMode(hStdInput,ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT |   ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS);
 
ReadConsoleInput(hStdInput,ir,128,&nRead); 
for(i=0;i<nRead;i++) 
	{				// mouse buttons and xy position within console in character spaces
		mouseX = ir[i].Event.MouseEvent.dwMousePosition.X;
                mouseY = ir[i].Event.MouseEvent.dwMousePosition.Y;
		if (ir[i].Event.MouseEvent.dwButtonState == 1) lMouse = true;
		if (ir[i].Event.MouseEvent.dwButtonState == 2) rMouse = true;
	}
						// Mouse buttons not in console mode 
	if ((GetAsyncKeyState(VK_LBUTTON) != 0)) lMouse = true;
	if ((GetAsyncKeyState(VK_RBUTTON) != 0)) rMouse = true;
	
    GetCursorPos(&pMouse); 					// mouse position in pixel for total screen
	if (xNeg) MouseX = pMouse.x - xFudge; else 	MouseX = pMouse.x + xFudge;
	if (yNeg) MouseY = pMouse.y - yFudge; else 	MouseY = pMouse.y + yFudge;
		// the x/y Neg and x/y Fudge allow minor adjustments and are globally defined
		// they are set up by - void calibrate (void) function
		// this allows pixel adjustment for fine work in graphics
}

/*  ******************************************************************* */
Last edited on
Topic archived. No new replies allowed.