System: Windows; Version c 23 Want to create an interactive button in a console application. For this to work, I need to get where a user clicked 1) relative to console window 2) NOT IN PIXELS, but in CONSOLE CELL UNITS. Things I tried:
using namespace std;
void GetMouseCursorPos(POINT *mC) {
*mC = POINT{0,0};
ScreenToClient(GetConsoleWindow(),mC);
mC->x = mC->x / font.dwFontSize.X;
mC->y = mC->y / font.dwFontSize.Y;
system("cls");
cout << mC->x << " " << mC->y;
}
int main (){
POINT mCoord;
while (true){
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_MOUSE_INPUT |
ENABLE_EXTENDED_FLAGS);
GetMouseCursorPos(&mCoord);
}
}
In fullscreen ALWAYS outputs 0 -4
Second try:
using namespace std;
void GetMouseCursorPos(POINT *mC) {
*mC = POINT{0,0};
ScreenToClient(GetConsoleWindow(),mC);
mC->x = mC->x / font.dwFontSize.X;
mC->y = LONG(mC->y - 22.5) / font.dwFontSize.Y;
system("cls");
cout << mC->x << " " << mC->y;
}
int main (){
POINT mCoord;
while (true){
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_MOUSE_INPUT |
ENABLE_EXTENDED_FLAGS);
GetMouseCursorPos(&mCoord);
}
}
Although 2nd try is better (but still not perfect)
Why the 2nd try is not perfect(Picture)
When you click on the red crosses
you select the slot leftside to it (not the slot itself)
Button class:
using namespace std;
class Button {
public:
int x;
int y;
int height;
int width;
string text;
string text1;
string text2;
int color = 7;
int itemColor = 7;
string getText() { return text; };
void setText(string text) { this->text = text; };
bool isPressed(int mX, int mY) {
if (mX >= this->x && mX <= this->x width && mY >= this->y && mY <= this->y height) {
return true;
}
return false;
};
void print() {
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), {static_cast<SHORT>(x 1), static_cast<SHORT>(y)});
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
for (int i = 0; i < width - 1; i ) {
cout << "-";
}
for (int i = 0; i < (height - 2); i ) {
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),
{static_cast<SHORT>(x), static_cast<SHORT>(y i 1)});
cout << "|";
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),
{static_cast<SHORT>(x width), static_cast<SHORT>(y i 1)});
cout << "|";
}
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),
{static_cast<SHORT>(x 1), static_cast<SHORT>(y height -
1)});
for (int i = 0; i < width - 1; i ) {
cout << "-";
}
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),
{static_cast<SHORT>(x 1),
static_cast<SHORT>(y height / 2)});
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
for (int i = 0; i < width / 2 - text.length() / 2 - 1; i ) {
cout << " ";
}
cout << text;
for (int i = 0; i < width / 2 - text.length() / 2 - 1; i ) {
cout << " ";
}
if (!text1.empty()) {
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),
{static_cast<SHORT>(x 1),
static_cast<SHORT>(y height / 2 1)});
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
for (int i = 0; i < width / 2 - text1.length() / 2 - 1; i ) {
cout << " ";
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), itemColor);
cout << text1[0];
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
cout << text1.substr(1);
for (int i = 0; i < width / 2 - text1.length() / 2 - 1; i ) {
cout << " ";
}
}
if (!text2.empty()) {
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),
{static_cast<SHORT>(x 1),
static_cast<SHORT>(y height / 2 - 1)});
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
for (int i = 0; i < width / 2 - text2.length() / 2 - 1; i ) {
cout << " ";
}
cout << text2;
for (int i = 0; i < width / 2 - text2.length() / 2 - 1; i ) {
cout << " ";
}
}
}
};
CodePudding user response:
By calling the function SetConsoleMode
with the argument ENABLE_MOUSE_INPUT
, you can set the console to report mouse events. These events can then be read using the function ReadConsoleInput
.
When reading a mouse event, you will get a MOUSE_EVENT_RECORD
structure. The dwMousePosition
member of this structure is in character-cell coordinates, not pixels.
Here is an example program:
#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD ir;
DWORD dwRead;
//set console to report mouse input events (but nothing else, including keyboard events)
if ( !SetConsoleMode( hInput, ENABLE_MOUSE_INPUT ) )
{
fprintf( stderr, "Error setting console mode!\n" );
exit( EXIT_FAILURE );
}
while ( ReadConsoleInput( hInput, &ir, 1, &dwRead ) && dwRead == 1 )
{
//ignore all non-mouse events, except for the key "q", which is a request to end the program
if ( ir.EventType != MOUSE_EVENT )
{
if (
ir.EventType == KEY_EVENT &&
ir.Event.KeyEvent.bKeyDown &&
ir.Event.KeyEvent.uChar.AsciiChar == 'q'
)
{
return 0;
}
continue;
}
//ignore all mouse events which don't involve mouse button presses
if ( ir.Event.MouseEvent.dwEventFlags != 0 && ir.Event.MouseEvent.dwEventFlags != DOUBLE_CLICK )
continue;
//determine whether mouse button was clicked or released
if ( ir.Event.MouseEvent.dwButtonState != 0 )
printf( "Mouse button clicked" );
else
printf( "Mouse button released" );
//print coordinates of mouse click/release
printf(
" at the following cell coordinates: [%u,%u]\n",
ir.Event.MouseEvent.dwMousePosition.X,
ir.Event.MouseEvent.dwMousePosition.Y
);
fflush( stdout );
}
fprintf( stderr, "Input error!\n" );
}
This program has the following output:
Mouse button clicked at the following cell coordinates: [24,9]
Mouse button released at the following cell coordinates: [24,9]
Mouse button clicked at the following cell coordinates: [46,10]
Mouse button released at the following cell coordinates: [60,12]
Mouse button clicked at the following cell coordinates: [45,17]
Mouse button released at the following cell coordinates: [31,10]
In order to quit the program, you must press the Q key.
Note that this program is only for demonstration purposes and is not optimized for performance. In a proper program in which performance may be an issue, it would probably be better to read more than one event at once using ReadConsoleInput
.