按行和列设置控制台屏幕大小和屏幕缓冲区

时间:2019-07-06 07:06:13

标签: c++ windows console

我试图调整控制台,特别是屏幕缓冲区大小和控制台的实际大小,最好是按字符的行和列。 我已经使用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);

1 个答案:

答案 0 :(得分:0)

您可以从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);

功能=>

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"\n\nContinue 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 25\n"
        L"size screen by using the SetConsoleScreenBufferSize and\n"
        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 of\n"
        L"200 x 200 - notice that the console\n"
        L"window size will not grow larger than\n"
        L"the physical screen size. Hit enter\n"
        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;
}