0

I'm writing a c++ console program for Windows using the windows.h include.

I've been trying to tailor the console size to fit my program output, but without finding a reliable way to obtain the value for width and height of a "cell" (the character boxes). I've tried both GetConsoleFontSize and GetConsoleScreenBufferInfo + GetDesktopWindow as demonstrated in the code sample below.

    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

    CONSOLE_FONT_INFO font_size;
    GetConsoleFontSize(hOut,GetCurrentConsoleFont(hOut, false, &font_size));

    CONSOLE_SCREEN_BUFFER_INFO csbi;
    GetConsoleScreenBufferInfo(hOut, &csbi);

    RECT desktop;
    // Get a handle to the desktop window
    const HWND hDesktop = GetDesktopWindow();
    // Get the size of screen to the variable desktop
    GetWindowRect(hDesktop, &desktop);

    // Calculate size of one cell in the console, expressed in pixels.
    COORD cell;
    // Screen width/max number of columns
    cell.X = desktop.right/ csbi.dwMaximumWindowSize.X;
    // Screen height/max number of rows
    cell.Y = desktop.bottom / csbi.dwMaximumWindowSize.Y;    

    // Change console size
    HWND console = GetConsoleWindow();
    MoveWindow(console, 0, 0, 10 * cell.X * 2, 10 * cell.Y, TRUE);
    MoveWindow(console, 0, 0, 10 * font_size.dwFontSize.X * 2, 10 * font_size.dwFontSize.Y, TRUE);

Of both attempts I expected a square window able to contain just about 20x10 cells (the height of the cells seem to be 2x the width), with some margin of error on one of the examples given the integer division. However, they both seemed to be approximately 25% too small, apart from the width of the first example with is about 10% too large.

I assume that the font size does not include the spacing between letters and that the dependencies of .dwMaxWindowSize (such as buffer size etc) comes into play, but I can't quite get either method straight.

If anyone has any knowledge of how to obtain the width/height of the cells in pixels reliably I'd be very grateful. Any information regarding what goes into the cells, what affects the return value of either function or other functions I can use to achieve my goal.

Also note that the size is ultimately going to be bigger, but since I wanted to manually count the rows/columns to debug I made it smaller.

6
  • 1
    It might help to use GetClientRect to only count the client area of the window instead of the total size of the window. docs.microsoft.com/en-us/windows/win32/api/winuser/…. Also you probably don't need the font size if you just do newClientWidth = oldClientWidth * newBufferColumns / oldBufferColumns and same with height/rows. And to set the window size you'd probably need to convert between client size and window size, but I imagine that to be a constant difference: newWindowWidth = newClientWidth + oldWindowWidth - oldClientWidth or something like that. Commented Aug 26, 2021 at 17:25
  • 1
    @Ruzihm Thank you! I'm also not sure why the question was marked as duplicate since it seems more complex than the linked question. Am I missing something? Commented Aug 26, 2021 at 19:26
  • I agree that it's not a duplicate, I'm voting to reopen Commented Aug 26, 2021 at 19:28
  • 1
    Now that the question has been reopened, I've removed the solution, and the commentary from the question. Feel free to post the solution as an answer if you want. You can get to the previous edits by clicking the edit button and copying the text from the revision history, so you don't have to type it again. Commented Aug 26, 2021 at 23:56
  • 1
    @Ruzihm I updated the question with a next to finished solution. I've been a little out of it due to getting vaccinated, so I've not really been able to make much progress since I posted the question. At least I feel like I'm on the right track now, so thanks a lot! Commented Aug 28, 2021 at 9:19

1 Answer 1

1

I almost have a solution now, but it still needs some work.

CONSOLE_SCREEN_BUFFER_INFO csbi;
HWND console = GetConsoleWindow();
// Resolution
RECT newClientSize, oldClientSize, newWindowSize, oldWindowSize;
// Colums, Rows
COORD newBuffer{20,50}, oldBuffer;

for (int i = 0; i < 2; i++) {
    // Calculate the starting amount of columns and rows.
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    oldBuffer.X = csbi.srWindow.Right - csbi.srWindow.Left + 1;
    oldBuffer.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;

    printf("%i\n", oldBuffer.X);
    printf("%i\n", oldBuffer.Y);
    
    // Get size of client area
    GetClientRect(console, &oldClientSize);
    
    newClientSize.right = oldClientSize.right * newBuffer.X / oldBuffer.X;
    newClientSize.bottom = oldClientSize.bottom * newBuffer.Y / oldBuffer.Y;

    // Get size of window area
    GetWindowRect(console, &oldWindowSize);

    newWindowSize.right = newClientSize.right + oldWindowSize.right - oldClientSize.right;
    newWindowSize.bottom = newClientSize.bottom + oldWindowSize.bottom - oldClientSize.bottom;

    MoveWindow(console, 0, 0, newWindowSize.right, newWindowSize.bottom, TRUE);

}

GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
oldBuffer.X = csbi.srWindow.Right - csbi.srWindow.Left + 1;
oldBuffer.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;

printf("%i\n", oldBuffer.X);
printf("%i\n", oldBuffer.Y);

What I don't understand is why it works when I repeat the code two or more times. The only thing I don't think I fully understand is the different between ClientRect and WindowRect. However, as always, there's a possibility that there's something else I'm missing.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.