Setting the Cursor Position in a Win32 Console Application

Setting the Cursor Position in a Win32 Console Application

See SetConsoleCursorPosition API

Edit:

Use WriteConsoleOutputCharacter() which takes the handle to your active buffer in console and also lets you set its position.

int x = 5; int y = 6;
COORD pos = {x, y};
HANDLE hConsole_c = CreateConsoleScreenBuffer( GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
SetConsoleActiveScreenBuffer(hConsole_c);
char *str = "Some Text\r\n";
DWORD len = strlen(str);
DWORD dwBytesWritten = 0;
WriteConsoleOutputCharacter(hConsole_c, str, len, pos, &dwBytesWritten);
CloseHandle(hConsole_c);

c++ win32 set cursor position

You're approaching this slightly backwards. The SetCursorPos function works in screen cordinates and you want to set the cursor based on window / client coordinates. In order to do this you need to map from client to screen coordinates. The function ScreenToClient does the opposite. What you're looking for is ClientToScreen

For example:

ClientToScreen(hWnd, &pt);
SetCursorPos(pt.x,pt.y);

Documentation

  • http://msdn.microsoft.com/en-us/library/aa931003.aspx

How do I find the coordinates of the cursor in a console window?

As per the documentation for the SetConsoleCursorPosition function:

To determine the current position of the cursor, use the GetConsoleScreenBufferInfo function.

In general, if you know how to get or set something, the MSDN documentation for that function will hint at how to do the opposite. That is certainly true in this case.

If we look up the GetConsoleScreenBufferInfo function, we see that we've struck paydirt. It fills in a CONSOLE_SCREEN_BUFFER_INFO structure that, among other things, contains a COORD structure that indicates the current column and row coordinates of the cursor.

There is even an example. Package it up into a function if you want to make it convenient:

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;
}
}

As Michael mentioned already in a comment, GetCursorPos doesn't work because it is for the mouse cursor (the arrow), not the cursor (insertion point) in a console window. It is returning valid values, just not the values you are looking for. Lucky that the return types are different, otherwise they'd be easy to mix up. Calling it the "cursor" for a console window is sort of misleading, it probably should be called the caret.

How do I manipulate console cursor position in dotnet core?

In ConsolePal class you have private static IntPtr OutputHandle(that is the handle of the console on which you want to move the cursor), so int this class you have to expose a method to set the cursor position.
In this method you have to call system API SetConsoleCursorPosition(IntPtr hConsoleOutput, COORD cursorPosition);.
COORD is:

[StructLayout(LayoutKind.Sequential)]
internal struct COORD
{
internal short X;
internal short Y;
}

You can add DllImport of the previous method in Interop.mincore class (because it seems that is here where system DllImport are made), so somewhere where you want you can:

internal partial class Interop
{
internal partial class mincore
{
[DllImport("kernel32.dll", SetLastError=true)]
internal static extern bool SetConsoleCursorPosition(IntPtr hConsoleOutput, COORD cursorPosition);
}
}

The method to expose in ConsolePal can look like this:

public static void SetCursorPosition(int left, int top)
{
IntPtr consoleOutputHandle = OutputHandle;
COORD cursorPosition = new COORD {
X = (short) left,
Y = (short) top
};
Interop.mincore.SetConsoleCursorPosition(consoleOutputHandle, cursorPosition;
}

Note: add to the method some input check and some check on Interop.mincore.SetConsoleCursorPosition returned value

And in Console class simply expose a method that call ConsolePal.SetCursorPosition

public static void SetCursorPosition(int left, int top)
{
ConsolePal.SetCursorPosition(left, top);
}

I didn't test the code above so it may contain errors.

Edit

As @Jcl stated, it may not be welcome to use a custom version of .NET. In this case you can write a simple class to move the cursor(even this solution is only for Windows):

static class MyAwesomeConsoleExtensions
{
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetConsoleCursorPosition(IntPtr hConsoleOutput, COORD cursorPosition);
[StructLayout(LayoutKind.Sequential)]
private struct COORD
{
internal short X;
internal short Y;
}
private const int STD_OUTPUT_HANDLE = -11;

public static void SetCursorPos(int left, int top)
{
IntPtr consoleOutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD cursorPosition = new COORD
{
X = (short)left,
Y = (short)top
};
SetConsoleCursorPosition(consoleOutputHandle, cursorPosition);
}
}

Jump to console screen position defined by entering coordinate

You can use functions from Windows Console API.
For that, you just need to include windows.h header.

SetConsoleCursorPosition( HANDLE,COORD ) should do the trick.

Take a look at the documentation from Microsoft Docs.

Here's a demo example:

#include<iostream>
#include<windows.h>
#include<cstdio>

using namespace std;

void changeCursor( int columnPos, int rowPos )
{
HANDLE handle; /// A HANDLE TO CONSOLE SCREEN BUFFER

/// COORD STRUCTURE CONTAINS THE COLUMN AND ROW
/// OF SCREEN BUFFER CHARACTER CELL
COORD coord;

coord.X = columnPos;
coord.Y = rowPos;

/// RETURNS A HANDLE TO THE SPECIFIED DEVICE.

handle = GetStdHandle(STD_OUTPUT_HANDLE); /// STD_OUTPUT_HANDLE MEANS STANDARD
/// OUTPUT DEVICE(console screen buffer)

SetConsoleCursorPosition( handle,coord ); /// SETS CURSOR POSITION IN SPECIFIED
/// CONSOLE SCREEN BUFFER
}

int main()
{
int xCoord,yCoord;
cout<<"Lorem Ipsum is simply dummy text of \nthe printing and typesetting industry.\nLorem Ipsum has been the industry's standard \ndummy text ever since the 1500.";

cout<<endl<<endl<<"Coordinates of Column and Row(zero indexed): ";

cin>>xCoord>>yCoord;

getchar();
changeCursor(xCoord,yCoord); /// YOUR FUNCTION TO SET NEW CURSOR

getchar(); /// KEEP THE CONSOLE FROM TERMINATING

return 0;
}

Output:

Lorem Ipsum is simply dummy text of
the printing and typesetting industry.
Lor*e*m Ipsum has been the industry's standard
dummy text ever since the 1500.

Coordinates of Column and Row(zero indexed): 3 2

Notice here the coordinates need to be measured from TOP LEFT position i.e. (0,0) position of console screen.

The X ,Y values are Character Positions as they are pointing to SCREEN BUFFER CHARACTER CELL.

See a Sample Output here with specified cursor position.

How to print sentence in the position of the mouse cursor in VC++ Win32 application?

Use GetConsoleScreenBufferInfo to find the cursor position in console window. See this example

Tracking mouse position in a console program may not be useful. If you really need the position of mouse pointer, you have to convert from desktop coordinates to to console window coordinates.

Get the console window's handle GetConsoleWindow()
Use ScreenToClient to convert mouse pointer position from screen to client. Map the coordinates to CONSOLE_SCREEN_BUFFER_INFO::srWindow

COORD getxy()
{
POINT pt;
GetCursorPos(&pt);
HWND hwnd = GetConsoleWindow();

RECT rc;
GetClientRect(hwnd, &rc);
ScreenToClient(hwnd, &pt);

HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO inf;
GetConsoleScreenBufferInfo(hout, &inf);

COORD coord = { 0, 0 };
coord.X = MulDiv(pt.x, inf.srWindow.Right, rc.right);
coord.Y = MulDiv(pt.y, inf.srWindow.Bottom, rc.bottom);
return coord;
}

int main()
{
HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
while (1)
{
system("pause");
COORD coord = getxy();
SetConsoleCursorPosition(hout, coord);
cout << "(" << coord.X << "," << coord.Y << ")";
}
}

Win32 API console cursor not moving after WriteConsole

When ReadConsole reads stdin, it will append \r\n to the string. You have only excluded \n in the conditio. "string\r" will be passed to WriteConsole, and \r will return the cursor to the beginning of the line.
Try the following code:

#include <windows.h>
#include <iostream>
#include <string>
int main(int argc, char** argv)
{
std::wstring string;
wchar_t c;
DWORD u;
do {
ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), &c, 1, &u, NULL);
} while (u && (c == L' ' || c == L'\n'));
do {
string.append(1, c);
ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), &c, 1, &u, NULL);
} while (u && c != L' ' && c != L'\n' && c != L'\r');

WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), string.data(), string.length(), &u, NULL);
return 0;
}

How can I get the mouse position in a console program?

You'll need to use the *ConsoleInput family of methods (peek, read, etc). These operate on the console's input buffer, which includes keyboard and mouse events. The general strategy is:

  1. wait on the console's input buffer handle (ReadConsoleInput)
  2. determine the number of waiting events (lpNumberOfEventsRead)
  3. handle them as you see fit (i.e. MOUSE_EVENT and MOUSE_EVENT_RECORD)

You'll have to indicate that you want to retrieve mouse input using SetConsoleMode first though, as illustrated in this MSDN article.



Related Topics



Leave a reply



Submit