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

时间:2014-09-18 12:33:01

标签: 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);
}

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);

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

  

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

在我们的例子中,矩形的值与调用Topinfo.srWindow矩形的值相同(因为GetConsoleScreenBufferInfo()SetConsoleWindowInfo()为零)。但! ::GetLastError()失败并显示下一个@err,hr ERROR_INVALID_PARAMETER : The parameter is incorrect. unsigned int

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);
}

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

SetConsoleScreenBufferSize()

然后我会有同样的错误。

那么,我如何才能正确使用SetConsoleWindowInfo()和{{1}}?

2 个答案:

答案 0 :(得分:3)

SetConsoleWindowInfo()不会在屏幕上重新定位控制台窗口。此功能的名称具有误导性。它宁可滚动控制台窗口内的当前可见部分。请在此处查看this sample

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

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

答案 1 :(得分:1)

来自TurboVision port

void TDisplay::setCrtMode( ushort mode )
{
  int oldr = getRows();
  int oldc = getCols();
  int cols = uchar(mode >> 8);
  int rows = uchar(mode);
  if ( cols == 0 ) cols = oldc;
  if ( rows == 0 ) rows = oldr;
  checksize(rows, cols);
  COORD newSize = { cols, rows };
  SMALL_RECT rect = { 0, 0, cols-1, rows-1 };

  if ( oldr <= rows )
  {
    if ( oldc <= cols )
    {                           // increasing both dimensions
BUFWIN:
      SetConsoleScreenBufferSize( TThreads::chandle[cnOutput], newSize );
      SetConsoleWindowInfo( TThreads::chandle[cnOutput], True, &rect );
    }
    else
    {                           // cols--, rows+
      SMALL_RECT tmp = { 0, 0, cols-1, oldr-1 };
      SetConsoleWindowInfo( TThreads::chandle[cnOutput], True, &tmp );
      goto BUFWIN;
    }
  }
  else
  {
    if ( oldc <= cols )
    {                           // cols+, rows--
      SMALL_RECT tmp = { 0, 0, oldc-1, rows-1 };
      SetConsoleWindowInfo( TThreads::chandle[cnOutput], True, &tmp );
      goto BUFWIN;
    }
    else
    {                           // cols--, rows--
      SetConsoleWindowInfo( TThreads::chandle[cnOutput], True, &rect );
      SetConsoleScreenBufferSize( TThreads::chandle[cnOutput], newSize );
    }
  }
  GetConsoleScreenBufferInfo( TThreads::chandle[cnOutput], &TThreads::sbInfo );
}

ushort TDisplay::getRows()
{
  GetConsoleScreenBufferInfo( TThreads::chandle[cnOutput], &TThreads::sbInfo );
  return TThreads::sbInfo.dwSize.Y;
}

ushort TDisplay::getCols()
{
  GetConsoleScreenBufferInfo( TThreads::chandle[cnOutput], &TThreads::sbInfo );
  return TThreads::sbInfo.dwSize.X;
}