在 Windows 上设置控制台窗口大小

gri*_*sha 2 c++ winapi

我知道关于如何设置控制台大小有很多问题。但是所有找到的解决方案对我来说都是一样的,我的代码对我不起作用。

好的,所以为了设置控制台窗口大小,我需要两个函数。它们是SetConsoleScreenBufferSize()和SetConsoleWindowInfo()。我的函数的第一个版本:

bool SetWindowSize(size_t width, size_t height)
{
    HANDLE output_handle = ::GetStdHandle(STD_OUTPUT_HANDLE);
    if(output_handle == INVALID_HANDLE_VALUE)
        return false;

    COORD coord = {};
    coord.X = static_cast<SHORT>(width);
    coord.Y = static_cast<SHORT>(height);
    if(::SetConsoleScreenBufferSize(output_handle, coord) == FALSE)
        return false;

    SMALL_RECT rect = {};
    rect.Bottom = coord.X - 1;
    rect.Right = coord.Y - 1;
    return (::SetConsoleWindowInfo(output_handle, TRUE, &rect) != FALSE);
}
Run Code Online (Sandbox Code Playgroud)

SetConsoleScreenBufferSize()不适用于所有值。从文档:

指定的宽度和高度不能小于控制台屏幕缓冲区的窗口的宽度和高度

让我们尝试获取当前窗口的大小并调用我们的函数。要获取窗口大小,我需要GetConsoleScreenBufferInfo()函数。main() 测试代码:

HANDLE output_handle = ::GetStdHandle(STD_OUTPUT_HANDLE);
if(output_handle == INVALID_HANDLE_VALUE)
    return 0;
CONSOLE_SCREEN_BUFFER_INFO info = {};
if(::GetConsoleScreenBufferInfo(output_handle, &info) == FALSE)
    return 0;
size_t width = info.srWindow.Right - info.srWindow.Left;
size_t height = info.srWindow.Bottom - info.srWindow.Top;
bool suc = SetWindowSize(width + 1, height + 1);
Run Code Online (Sandbox Code Playgroud)

在这种情况下SetConsoleScreenBufferSize()工作正常。下一个函数是SetConsoleWindowInfo(). 此功能适用于以下情况:

如果指定的窗口矩形超出控制台屏幕缓冲区的边界,则该函数失败。这意味着矩形的Top 和Left成员lpConsoleWindow(或计算的顶部和左侧坐标,如果bAbsolute为 FALSE)不能小于零。同样,Bottom和Right成员(或计算的底部和右侧坐标)不能分别大于 (screen buffer height – 1) 和 (screen buffer width – 1)。如果Right成员(或计算的右坐标)小于或等于Left成员(或计算的左坐标)或Bottom成员(或计算的底部坐标)小于或等于Top成员(或计算的顶部坐标),则该函数也会失败)。

在我们的例子中,矩形的值在调用 之后与矩形的值相同(因为Left和Top为零)。但!下一个失败info.srWindowGetConsoleScreenBufferInfo()SetConsoleWindowInfo()::GetLastError()

@err,hr ERROR_INVALID_PARAMETER : The parameter is incorrect.   unsigned int
Run Code Online (Sandbox Code Playgroud)

如果我交换这两个函数的调用:

bool SetWindowSize(size_t width, size_t height)
{
    HANDLE output_handle = ::GetStdHandle(STD_OUTPUT_HANDLE);
    if(output_handle == INVALID_HANDLE_VALUE)
        return false;

    SMALL_RECT rect = {};
    rect.Bottom = static_cast<SHORT>(width);
    rect.Right = static_cast<SHORT>(height);
    if(::SetConsoleWindowInfo(output_handle, TRUE, &rect) == FALSE)
        return false;

    COORD coord = {};
    coord.X = rect.Bottom + 1;
    coord.Y = rect.Right + 1;

    return (::SetConsoleScreenBufferSize(output_handle, coord) != FALSE);
}
Run Code Online (Sandbox Code Playgroud)

那么我会遇到同样的错误。

那么,我该如何正确使用SetConsoleScreenBufferSize()和SetConsoleWindowInfo()呢?

RED*_*AIR 5

SetConsoleWindowInfo() 不会在屏幕上重新定位控制台窗口。此函数的名称具有误导性。它而是滚动控制台窗口内的当前可见部分。在此处查看此示例。

如果要设置运行程序的控制台窗口的位置,请使用以下代码:

HWND hwnd = GetConsoleWindow();
RECT rect = {100, 100, 300, 500};
MoveWindow(hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,TRUE);
Run Code Online (Sandbox Code Playgroud)