通过行和列设置控制台屏幕尺寸和屏幕缓冲区

Set console screen size and screen buffer by rows and columns

本文关键字:屏幕 缓冲区 控制台 设置      更新时间:2023-10-16

我正在尝试调节控制台,特别是屏幕缓冲区大小和控制台的实际大小,最好是通过字符的行和列。我已经使用SetConsoleScreenBufferSize成功更改了屏幕缓冲区大小,但是我在调整实际窗口本身的问题上存在问题。我尝试使用SetConsoleWindowInfo,它似乎不会影响任何内容,即使它确实想用行/列更改它。最终,我想做到这一点,以便用户也无法调整它的大小。无论如何,这是我相关的说明。

    hConsole = CreateConsoleScreenBuffer(
        GENERIC_READ | GENERIC_WRITE, 
        0, 
        NULL, 
        CONSOLE_TEXTMODE_BUFFER, 
        NULL
    );
    SMALL_RECT size = { 0, 0, 240, 240 }; // Test values
    SetConsoleActiveScreenBuffer(hConsole);
    SetConsoleScreenBufferSize(hConsole, { width, height });
    SetConsoleWindowInfo(hConsole, TRUE, &size);

您可以从MS中看到旧的演示函数: DemoSizeInfo

我将函数转换为unicode =>

#define WSTR1(x) L##x
#define WSTR2(x) WSTR1(x)
#define __WFILE__ WSTR2(__FILE__)
void perr(PWCHAR szFileName, int line, PWCHAR szApiName, DWORD dwError);
#define PERR(bSuccess, api) {if (!(bSuccess)) perr(__WFILE__, __LINE__, api, GetLastError());}
void resizeConBufAndWindow(HANDLE hConsole, SHORT xSize, SHORT ySize);
void demoSizeInfo(HANDLE hConOut);
// Test demo on your hConsole handle
demoSizeInfo(hConsole);

functions =>

void resizeConBufAndWindow(HANDLE hConsole, SHORT xSize, SHORT ySize)
{
    CONSOLE_SCREEN_BUFFER_INFO csbi; /* hold current console buffer info */
    BOOL bSuccess;
    SMALL_RECT srWindowRect; /* hold the new console size */
    COORD coordScreen;
    bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);
    PERR(bSuccess, L"GetConsoleScreenBufferInfo");
    /* get the largest size we can size the console window to */
    coordScreen = GetLargestConsoleWindowSize(hConsole);
    PERR(coordScreen.X | coordScreen.Y, L"GetLargestConsoleWindowSize");
    /* define the new console window size and scroll position */
    srWindowRect.Right = (SHORT)(min(xSize, coordScreen.X) - 1);
    srWindowRect.Bottom = (SHORT)(min(ySize, coordScreen.Y) - 1);
    srWindowRect.Left = srWindowRect.Top = (SHORT)0;
    /* define the new console buffer size */
    coordScreen.X = xSize;
    coordScreen.Y = ySize;
    /* if the current buffer is larger than what we want, resize the */
    /* console window first, then the buffer */
    if ((DWORD)csbi.dwSize.X * csbi.dwSize.Y > (DWORD)xSize * ySize)
    {
        bSuccess = SetConsoleWindowInfo(hConsole, TRUE, &srWindowRect);
        PERR(bSuccess, L"SetConsoleWindowInfo");
        bSuccess = SetConsoleScreenBufferSize(hConsole, coordScreen);
        PERR(bSuccess, L"SetConsoleScreenBufferSize");
    }
    /* if the current buffer is smaller than what we want, resize the */
    /* buffer first, then the console window */
    if ((DWORD)csbi.dwSize.X * csbi.dwSize.Y < (DWORD)xSize * ySize)
    {
        bSuccess = SetConsoleScreenBufferSize(hConsole, coordScreen);
        PERR(bSuccess, L"SetConsoleScreenBufferSize");
        bSuccess = SetConsoleWindowInfo(hConsole, TRUE, &srWindowRect);
        PERR(bSuccess, L"SetConsoleWindowInfo");
    }
    /* if the current buffer *is* the size we want, don't do anything! */
    return;
}

/*********************************************************************
* FUNCTION: perr(PCHAR szFileName, int line, PCHAR szApiName,        *
*                DWORD dwError)                                      *
*                                                                    *
* PURPOSE: report API errors. Allocate a new console buffer, display *
*          error number and error text, restore previous console     *
*          buffer                                                    *
*                                                                    *
* INPUT: current source file name, current line number, name of the  *
*        API that failed, and the error number                       *
*                                                                    *
* RETURNS: none                                                      *
*********************************************************************/
/* maximum size of the buffer to be returned from FormatMessage */
#define MAX_MSG_BUF_SIZE 512
void perr(PWCHAR szFileName, int line, PWCHAR szApiName, DWORD dwError)
{
    WCHAR szTemp[1024];
    DWORD cMsgLen;
    WCHAR *msgBuf; /* buffer for message text from system */
    int iButtonPressed; /* receives button pressed in the error box */
                        /* format our error message */
    wsprintf(szTemp, L"%s: Error %d from %s on line %d:n", szFileName,
        dwError, szApiName, line);
    /* get the text description for that error number from the system */
    cMsgLen = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 40, NULL, dwError,
        MAKELANGID(0, SUBLANG_ENGLISH_US), (LPTSTR)&msgBuf, MAX_MSG_BUF_SIZE,
        NULL);
    if (!cMsgLen)
        wsprintf(szTemp + lstrlen(szTemp), L"Unable to obtain error message text! n"
            L"%s: Error %d from %s on line %d", __FILE__,
            GetLastError(), "FormatMessage", __LINE__);
    else
        lstrcat(szTemp, msgBuf);
    lstrcat(szTemp, L"nnContinue execution?");
    MessageBeep(MB_ICONEXCLAMATION);
    iButtonPressed = MessageBox(NULL, szTemp, L"Console API Error",
        MB_ICONEXCLAMATION | MB_YESNO | MB_SETFOREGROUND);
    /* free the message buffer returned to us by the system */
    if (cMsgLen)
        LocalFree((HLOCAL)msgBuf);
    if (iButtonPressed == IDNO)
        exit(1);
    return;
}
/*************************************************************************
* FUNCTION: myPuts(HANDLE hConsole, PCHAR s)                             *
*                                                                        *
* PURPOSE: write a string to the given console buffer, appending a cr/lf *
*                                                                        *
* INPUT: the console to write to, and the string to write                *
*                                                                        *
* RETURNS: TRUE if success, FALSE if an error occured                    *
*************************************************************************/
BOOL myPuts(HANDLE hConsole, PWCHAR s)
{
    BOOL bSuccess;
    DWORD cCharsWritten;
    const PWCHAR crlf = L"n";
    BOOL retflag = TRUE;
    /* write the string to the console */
    bSuccess = WriteConsole(hConsole, s, lstrlen(s), &cCharsWritten, NULL);
    PERR(bSuccess, L"WriteConsole");
    retflag = bSuccess;
    /* put a carriage return & line feed after the string */
    bSuccess = WriteConsole(hConsole, crlf, lstrlen(crlf), &cCharsWritten, NULL);
    PERR(bSuccess, L"WriteConsole");
    if (!bSuccess)
        retflag = FALSE;
    return(retflag);
}
/*********************************************************************
* FUNCTION: setConTitle                                              *
*                                                                    *
* PURPOSE: simply set the current console title. Called by each demo *
*          function to specify the name of the source file that      *
*          contains the demo function.                               *
*                                                                    *
* INPUT: null terminated string                                      *
*********************************************************************/
void setConTitle(PCHAR szTitle)
{
    BOOL bSuccess;
    /* set the console title to the input string parameter */
    bSuccess = SetConsoleTitleA(szTitle);
    PERR(bSuccess, L"SetConsoleTitle");
    return;
}
/*****************************************************************
* FUNCTION: myGetchar(void)                                      *
*                                                                *
* PURPOSE: get a single character from the standard input handle *
*                                                                *
* INPUT: none                                                    *
*                                                                *
* RETURNS: the char received from the console                    *
*****************************************************************/
WCHAR myGetchar(void)
{
    HANDLE hStdIn; /* standard input */
    DWORD dwInputMode; /* to save the input mode */
    BOOL bSuccess;
    WCHAR chBuf; /* buffer to read into */
    DWORD dwRead;
    /* get the standard input handle to read from. There is only one */
    /* instance of standard input per process at any given time */
    hStdIn = GetStdHandle(STD_INPUT_HANDLE);
    PERR(hStdIn != INVALID_HANDLE_VALUE, L"GetStdHandle");
    /* save the console mode */
    bSuccess = GetConsoleMode(hStdIn, &dwInputMode);
    PERR(bSuccess, L"GetconsoleMode");
    /* disable line input. Echo input must be disabled when disabling */
    /* line input */
    bSuccess = SetConsoleMode(hStdIn, dwInputMode & ~ENABLE_LINE_INPUT &
        ~ENABLE_ECHO_INPUT);
    PERR(bSuccess, L"SetConsoleMode");
    /* read a character from the console input */
    bSuccess = ReadFile(hStdIn, &chBuf, sizeof(chBuf), &dwRead, NULL);
    PERR(bSuccess, L"ReadFile");
    /* restore the original console input mode */
    bSuccess = SetConsoleMode(hStdIn, dwInputMode);
    PERR(bSuccess, L"SetConsoleMode");
    return(chBuf);
}
/********************************************************************
* FUNCTION: getConX(HANDLE hCon)                                    *
*                                                                   *
* PURPROSE: to get the current width of the console output buffer   *
*                                                                   *
* INPUT: the handle to get the information for                      *
*                                                                   *
* RETURNS: the width of the current console output buffer, in chars *
********************************************************************/
SHORT getConX(HANDLE hCon)
{
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    BOOL bSuccess;
    bSuccess = GetConsoleScreenBufferInfo(hCon, &csbi);
    PERR(bSuccess, L"GetConsoleScreenBufferInfo");
    return(csbi.dwSize.X);
}
/*********************************************************************
* FUNCTION: getConY(HANDLE hCon)                                     *
*                                                                    *
* PURPROSE: to get the current height of the console output buffer   *
*                                                                    *
* INPUT: the handle to get the information for                       *
*                                                                    *
* RETURNS: the height of the current console output buffer, in chars *
*********************************************************************/
SHORT getConY(HANDLE hCon)
{
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    BOOL bSuccess;
    bSuccess = GetConsoleScreenBufferInfo(hCon, &csbi);
    PERR(bSuccess, L"GetConsoleScreenBufferInfo");
    return(csbi.dwSize.Y);
}
void demoSizeInfo(HANDLE hConOut)
{
    SHORT sConX, sConY; /* save the current console dimensions */
    setConTitle(__FILE__);
    myPuts(hConOut, L"Let's resize the console buffer and window to a 40 x 25n"
        L"size screen by using the SetConsoleScreenBufferSize andn"
        L"SetConsoleWindowInfo APIs. Hit enter to continue...n");
    myGetchar();
    sConX = getConX(hConOut);
    sConY = getConY(hConOut);
    resizeConBufAndWindow(hConOut, (SHORT)40, (SHORT)25);
    myPuts(hConOut, L"Now let's resize to a large size ofn"
        L"200 x 200 - notice that the consolen"
        L"window size will not grow larger thann"
        L"the physical screen size. Hit entern"
        L"to continue...n");
    myGetchar();
    resizeConBufAndWindow(hConOut, (SHORT)200, (SHORT)200);
    myPuts(hConOut, L"Now let's resize back to our original size screen.n"
        L"Hit enter to continue...n");
    myGetchar();
    resizeConBufAndWindow(hConOut, sConX, sConY);
    myPuts(hConOut, L"Now we're back to our original size. Hit enter to return...");
    myGetchar();
    return;
}