#include "stdafx.h" #include #include #include #include "ConsoleHandler.h" // For special cursor positioning static bool consoleInit = false; static HANDLE hStdout, hStdin; static CONSOLE_SCREEN_BUFFER_INFO csbi; static WORD wOldColorAttrs; // Save the current console colors static short consoleWidth = 0; static short consoleHeight = 0; static short scrollBot = 0; // set at init: consoleHeight - 1 static short scrollTop = 0; // set at init: consoleHeight - consoleScrollHeight - 1 void Console_Init(short Left, short Top, short Width, short Height, short bottomScrollHeight) { hStdin = GetStdHandle(STD_INPUT_HANDLE); hStdout = GetStdHandle(STD_OUTPUT_HANDLE); if (!GetConsoleScreenBufferInfo(hStdout, &csbi)) { fprintf(stderr, "Error: Unable to get console buffer info. Code: %lu\n", GetLastError()); exit(1); } consoleWidth = Width; consoleHeight = Height; scrollBot = consoleHeight - 1; scrollTop = consoleHeight - bottomScrollHeight - 1; // Desired size (width x height) COORD newSize; newSize.X = consoleWidth; // columns newSize.Y = consoleHeight; // rows // Step 2: Set new buffer size if (!SetConsoleScreenBufferSize(hStdout, newSize)) { fprintf(stderr, "Error: Unable to set console buffer size. Code: %lu\n", GetLastError()); exit(1); } // Step 3: Set final window size to match buffer SMALL_RECT newWindow; newWindow.Left = 0; newWindow.Top = 0; newWindow.Right = newSize.X - 1; newWindow.Bottom = newSize.Y - 1; if (!SetConsoleWindowInfo(hStdout, TRUE, &newWindow)) { fprintf(stderr, "Error: Unable to set console window size. Code: %lu\n", GetLastError()); exit(1); } // end Console_SetWindowPosition(Left, Top); wOldColorAttrs = csbi.wAttributes; //SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_INTENSITY); } void Console_Close() { SetConsoleTextAttribute(hStdout, wOldColorAttrs); } void Console_Cls() { COORD coordScreen = { 0, 0 }; // home for the cursor DWORD cCharsWritten; DWORD dwConSize; // Get the number of character cells in the current buffer. if (!GetConsoleScreenBufferInfo(hStdout, &csbi)) { return; } dwConSize = csbi.dwSize.X * csbi.dwSize.Y; // Fill the entire screen with blanks. if (!FillConsoleOutputCharacter(hStdout, // Handle to console screen buffer (TCHAR)' ', // Character to write to the buffer dwConSize, // Number of cells to write coordScreen, // Coordinates of first cell &cCharsWritten)) { // Receive number of characters written return; } // Get the current text attribute. if (!GetConsoleScreenBufferInfo(hStdout, &csbi)) { return; } // Set the buffer's attributes accordingly. if (!FillConsoleOutputAttribute(hStdout, // Handle to console screen buffer csbi.wAttributes, // Character attributes to use dwConSize, // Number of cells to set attribute coordScreen, // Coordinates of first cell &cCharsWritten)) { // Receive number of characters written return; } // Put the cursor at its home coordinates. SetConsoleCursorPosition(hStdout, coordScreen); } void Console_SetWindowPosition(int x, int y) { HWND hwnd = GetConsoleWindow(); if (!hwnd) return; // Move the window to (x,y) in screen coordinates without changing size or z-order SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW); } void Console_Write(const char *text) { DWORD written; WriteConsole(hStdout, text, (DWORD)strlen(text), &written, nullptr); } void Console_WriteAt(short x, short y, const char *text) { DWORD written; if (hStdout) { Console_SetCursor(x, y); WriteConsole(hStdout, text, (DWORD)strlen(text), &written, nullptr); } else { printf("%s\n", text); } } void Console_SetCursor(short x, short y) { GetConsoleScreenBufferInfo(hStdout, &csbi); csbi.dwCursorPosition.X = (short)((x < 0) ? csbi.srWindow.Right + x : x); csbi.dwCursorPosition.Y = (short)((y < 0) ? csbi.srWindow.Bottom + 1 + y : y); SetConsoleCursorPosition(hStdout, csbi.dwCursorPosition); } void Console_ScrollBottomRegion() { short topLine = scrollTop + 1; short bottomLine = scrollBot; GetConsoleScreenBufferInfo(hStdout, &csbi); if (topLine < 0) topLine = csbi.srWindow.Bottom + topLine; if (bottomLine < 0) bottomLine = csbi.srWindow.Bottom + bottomLine; SMALL_RECT scrollRect = { 0, topLine, csbi.dwMaximumWindowSize.X - 1, bottomLine }; COORD dest = { 0, topLine - 1 }; CHAR_INFO fill = { ' ', { FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE } }; ScrollConsoleScreenBuffer(hStdout, &scrollRect, &scrollRect, dest, &fill); _putch('\r'); // Cursor to left margin } bool Console_AdvanceToNextLineIfNotRoomFor(short x, int scroll) { bool advanced = false; GetConsoleScreenBufferInfo(hStdout, &csbi); if (csbi.dwCursorPosition.X + x > csbi.dwMaximumWindowSize.X) { advanced = true; if (scroll == 1) { Console_ScrollBottomRegion(); } else { csbi.dwCursorPosition.Y++; } Console_SetCursor(0, csbi.dwCursorPosition.Y); } return advanced; } // Console_SetCursorVisibility // // Set the state of the cursor and provide the prior state so it // can be restored // // @param[in] bool the desired state, true is visible // @returns the prior state, true is visible // bool Console_SetCursorVisibility(bool visible) { CONSOLE_CURSOR_INFO cursorInfo; bool priorState = true; if (!GetConsoleCursorInfo(hStdout, &cursorInfo)) { // printf("***** Error: Unable to get cursor info.\n"); return priorState; } priorState = cursorInfo.bVisible; cursorInfo.bVisible = visible; // true = show, false = hide if (!SetConsoleCursorInfo(hStdout, &cursorInfo)) { // std::cerr << "Error: Unable to set cursor info.\n"; } return priorState; }