How can I set the cursor position in a Win32 Console application? Preferably, I would like to avoid making a handle and using the Windows Console Functions. (I spent all morning running down that dark alley; it creates more problems than it solves.) I seem to recall doing this relatively simply when I was in college using stdio, but I can't find any examples of how to do it now. Any thoughts or suggestions would be greatly appreciated. Thanks.
Additional Details
Here is what I am now trying to do:
COORD pos = {x, y};
HANDLE hConsole_c = CreateConsoleScreenBuffer( GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL );
char * str = "Some Text\r\n";
DWDORD len = strlen(str);
SetConsoleCursorPosition(hConsole_c, pos);
WriteConsole(hConsole_c, str, len, &dwBytesWritten, NULL);
CloseHandle(hConsole_c)
The text string str is never sent to the screen. Is there something else that I should be doing? Thanks.
Using the console functions, you'd use SetConsoleCursorPosition. Without them (or at least not using them directly), you could use something like gotoxy in the ncurses library.
Edit: a wrapper for it is pretty trivial:
// Untested, but simple enough it should at least be close to reality...
void gotoxy(int x, int y) {
COORD pos = {x, y};
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output, pos);
}
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);
Yeah, you forgot to call SetConsoleActiveScreenBuffer. What exactly was the point of creating your own? Use GetStdHandle(STD_OUTPUT_HANDLE) to get a handle to the existing console.
You were probably using ANSI excape code sequences, which do not work with Windows 32-bit console applications.
#include <windows.h>
#include <iostream.h>
using namespace std;
int main(int argc, char *argv[])
{
int x,y;
cin>>x>>y;
SetCursorPos(x,y); //set your co-ordinate
Sleep(500);
mouse_event(MOUSEEVENTF_LEFTDOWN,x,y,0,0); // moving cursor leftdown
mouse_event(MOUSEEVENTF_LEFTUP,x,y,0,0); // moving cursor leftup //for accessing your required co-ordinate
system("pause");
return EXIT_SUCCESS;
}
Related
So I am following this tutorial here https://www.youtube.com/watch?v=xW8skO7MFYw and I am new to accessing console buffer and that. I started debugging when I realized my console looked like this https://ibb.co/896tGGL when I ran it. And I narrowed it down to this line of code
WriteConsoleOutputCharacter(hConsole, screen, nScreenWidth * nScreenheight, { 0,0 }, &dwBytesWritten);
the values in this are set to:
HANDLE hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
wchar_t* screen = new wchar_t[nScreenWidth * nScreenheight];
int nScreenWidth = 120;
int nScreenheight = 40;
DWORD dwBytesWritten = 0;
All the parts of your code that say
screen[y * nScreenWidth] = something;
should be
screen[y * nScreenWidth + x] = something;
And of course you need to loop to set the x coordinate.
If you look carefully you can actually see the # on the left edge of your screen. That's because you missed the x ccordinate out of your calculations.
I want to follow https://www.youtube.com/watch?v=xW8skO7MFYw&t=357s tutorial, but at one point the author manually allocates the console to be more efficient. He uses what looks like Windows specific instructions, but I want to achieve the same thing on Linux. I am on Debian 9.8 and using g++6.3. This is the code I want to duplicate on my Linux end.
#include <stdio.h>
#include <Windows.h>
int nScreenWidth = 120;
int nScreenHeight = 40;
wchar_t *screen = new wchar_t[nScreenWidth*nScreenHeight];
HANDLE hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
SetConsoleActiveScreenBuffer(hConsole);
DWORD dwBytesWritten = 0;
I already tried finding a solution to this and I couldn't find anything. Thanks I appreciate the help
I have trouble converting Mouse screen coordinates into the console 2D buffer when the font size is very small. The only method I have found was is this one:
COORD CursorToBuffer()
{
POINT ptCursor;
GetCursorPos(&ptCursor);
ScreenToClient(GetConsoleWindow(), &ptCursor);
/** Now ptCursor has the Mouse Position relative to the console client area. **/
COORD dwBufferPosition;
dwBufferPosition.X = ptCursor.x / dwFontWidth;
dwBufferPosition.Y = ptCursor.y / dwFontHeight;
return dwBufferPosition;
}
When the font is around 12x16, it is accurate. But when the font size is under 10x10, it starts to mess up.
Can I make this more accurate, or is there another method I should use?
Better than calculating the mouse position is getting its real value. Using ReadConsoleInput
Use ReadConsoleInput than you get an INPUT_RECORD with a MOUSE_EVENT_RECORD. It also contains the mouse position.
See sample code in the MSDN
I tested this program and seems to work fine for font sizes smaller than 10x10, it worked even without calling LPtoDPbut I left it in. It calls GetConsoleFontSize to get the font size and it prints it to the output so you can inspect the values as you make the font smaller. Hope it helps.
#include <Windows.h>
#include <sstream>
#include <iostream>
CONSOLE_FONT_INFO fontInfo;
HANDLE hStdout;
HWND hwnd;
HDC hdc;
COORD CursorToBuffer()
{
POINT ptCursor;
GetCursorPos(&ptCursor);
ScreenToClient(hwnd, &ptCursor);
/** Now ptCursor has the Mouse Position relative to the console client area. **/
COORD dwFontSize = GetConsoleFontSize(hStdout, fontInfo.nFont);
POINT dpFontSize = { dwFontSize.X, dwFontSize.Y };
LPtoDP(hdc, &dpFontSize, 0);
COORD dwBufferPosition;
dwBufferPosition.X = ptCursor.x / dpFontSize.x;
dwBufferPosition.Y = ptCursor.y / dpFontSize.y;
std::string fontSize = "fontSize: " + std::to_string(dpFontSize.x) + ' ' + std::to_string(dpFontSize.y) + "\n";
OutputDebugStringA(fontSize.c_str());
return dwBufferPosition;
}
void writeAt(int x, int y, std::string text)
{
COORD position = { x, y };
SetConsoleCursorPosition(hStdout, position);
std::cout << text;
}
int main()
{
hwnd = GetConsoleWindow();
hdc = GetDC(hwnd);
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
GetCurrentConsoleFont(hStdout, FALSE, &fontInfo);
while (1) {
COORD cursor = CursorToBuffer();
std::string txt = std::to_string(cursor.X) + " " + std::to_string(cursor.Y) + " \n";
writeAt(1, 1, txt);
}
return 0;
}
Other guys recommend the SetCurrentConsoleFontEx function but I don't know how to apply it to my project.
I want to change the font size of only some texts, not all texts.
Does SetCurrentConsoleFontEx() change the console's font size?
Or are there other ways to change it?
If there is, please show me the console function and a simple example.
Here is an example of using SetCurrentConsoleFontEx to change the console's font size. This affects the entire console window -- so like Joachim Pileborg already said, if you want mixed font sizes in a single console window, this won't help you.
#define _WIN32_WINNT 0x500
#include <Windows.h>
// PrintChars sends ASCII characters to console output
// for demonstration purposes.
// depends only on Win32 API
static void PrintChars() {
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD num_written;
static const char* cr_lf = "\r\n";
for(char c=' '; c<'\x7f'; ++c) {
WriteFile(hStdout, &c, 1, &num_written, NULL);
if(c % 16 == 15) WriteFile(hStdout, cr_lf, 2, &num_written, NULL);
}
WriteFile(hStdout, cr_lf, 2, &num_written, NULL);
}
// WaitEnter blocks execution until the user
// presses the enter key.
// depends only on Win32 API
static void WaitEnter() {
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
char buffer;
DWORD num_read;
do {
num_read = 0;
ReadFile(hStdin, &buffer, 1, &num_read, NULL);
} while(num_read && buffer != '\n');
}
int main() {
// Display some example characters
PrintChars();
// Wait for the user to see how the current font looks
WaitEnter();
// Get a handle to the current console screen buffer
HANDLE hcsb = CreateFileA("CONOUT$", GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
CONSOLE_FONT_INFOEX cfi = {sizeof(cfi)};
// Populate cfi with the screen buffer's current font info
GetCurrentConsoleFontEx(hcsb, FALSE, &cfi);
// Modify the font size in cfi
cfi.dwFontSize.X *= 2;
cfi.dwFontSize.Y *= 2;
// Use cfi to set the screen buffer's new font
SetCurrentConsoleFontEx(hcsb, FALSE, &cfi);
// Wait for the user to see the difference before exiting
WaitEnter();
CloseHandle(hcsb);
}
i want to issue commands to cmd prompt through WriteConsoleOutputCharacter(), i have tried the following code but did not respond any result just it write "Dir" at x y cord..
I don't know whether it is possible or not, if answer is not then suggest any other solution same like this. This program is a bit part of my application.
int main()
{
HANDLE hStdout;
processHandler* process = new processHandler();
process->start("cmd.exe");
AttachConsole(process->getPID());
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
coordScreen.X=csbi.dwCursorPosition.X;
coordScreen.Y=csbi.dwCursorPosition.Y;
WriteConsoleOutputCharacter( hConsole,"dir",3,coordScreen,&cCharsWritten );
coordScreen.X+=3;
SetConsoleCursorPosition(hConsole,coordScreen);
getch();
}