C++控制台:调整尺寸后仍留有滚动条空白区域
解决Windows控制台移除滚动条后残留空白区域的问题
我太懂你这个糟心的问题了——折腾半天把滚动条去掉,结果原来滚动条的位置留着空白,怎么看都别扭。咱们来一步步把这个问题搞定!
问题根源
你的代码里有个关键顺序错误:在移除滚动条样式之前就计算了窗口边框和客户区的差值。这时候窗口还带着滚动条,计算出来的l_diff_x和l_diff_y包含了滚动条的宽度/高度,等你把滚动条移除后,这个差值就不对了,导致窗口尺寸算大了,自然就留出空白。
修改后的代码
#include <windows.h> #include <iostream> const bool adjustWindowSize(const unsigned int p_console_buffer_width, const unsigned int p_console_buffer_height) { // 获取控制台窗口句柄 HWND l_window_handle(GetConsoleWindow()); if (l_window_handle == NULL) { std::cout << "GetConsoleWindow() failed\n"; return false; } // 移除不需要的窗口样式:滚动条、最大化/最小化按钮、尺寸调整框 LONG l_style(GetWindowLong(l_window_handle, GWL_STYLE)); l_style &= ~(WS_VSCROLL | WS_HSCROLL | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX); SetWindowLong(l_window_handle, GWL_STYLE, l_style); // 强制窗口更新样式,让滚动条立即消失 if (!SetWindowPos(l_window_handle, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED)) { std::cout << "SetWindowPos() for style update failed\n"; return false; } // 这里重新获取窗口和客户区尺寸,此时滚动条已经消失,计算的边框差值是准确的 RECT l_window_rect; if (!GetWindowRect(l_window_handle, &l_window_rect)) { std::cout << "GetWindowRect() failed\n"; return false; } RECT l_client_rect; if (!GetClientRect(l_window_handle, &l_client_rect)) { std::cout << "GetClientRect() failed\n"; return false; } // 获取控制台输出句柄 HANDLE l_console_handle(GetStdHandle(STD_OUTPUT_HANDLE)); if (l_console_handle == nullptr) { std::cout << "GetStdHandle() failed\n"; return false; } // 获取当前控制台字体信息 CONSOLE_FONT_INFO l_font_info; if (!GetCurrentConsoleFont(l_console_handle, false, &l_font_info)) { std::cout << "GetCurrentConsoleFont() failed\n"; return false; } // 计算目标客户区大小:字体尺寸 × 缓冲区行列数 unsigned int l_target_client_width(l_font_info.dwFontSize.X * p_console_buffer_width); unsigned int l_target_client_height(l_font_info.dwFontSize.Y * p_console_buffer_height); // 计算窗口边框的总宽度和高度(窗口整体尺寸 - 客户区尺寸) unsigned int l_border_width = l_window_rect.right - l_window_rect.left - (l_client_rect.right - l_client_rect.left); unsigned int l_border_height = l_window_rect.bottom - l_window_rect.top - (l_client_rect.bottom - l_client_rect.top); // 计算目标窗口的整体尺寸 unsigned int l_target_window_width = l_target_client_width + l_border_width; unsigned int l_target_window_height = l_target_client_height + l_border_height; // 设置窗口到目标尺寸 if (!SetWindowPos(l_window_handle, HWND_TOP, l_window_rect.left, l_window_rect.top, l_target_window_width, l_target_window_height, SWP_SHOWWINDOW)) { std::cout << "SetWindowPos() for resize failed\n"; return false; } // 设置控制台缓冲区大小,和窗口适配 COORD buffer_size = { (SHORT)p_console_buffer_width, (SHORT)p_console_buffer_height }; if (!SetConsoleScreenBufferSize(l_console_handle, buffer_size)) { std::cout << "SetConsoleScreenBufferSize() failed\n"; return false; } return true; } int main() { SetConsoleTitle(L"Console Test"); unsigned int l_buffer_x(100); unsigned int l_buffer_y(40); if (!adjustWindowSize(l_buffer_x, l_buffer_y)) { std::cout << "adjustWindowSize() failed\n"; return 1; } // 填充测试内容 for (unsigned int i(0); i < l_buffer_x * l_buffer_y; ++i) { std::cout << i % 10; } SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), COORD{0, 0}); return 0; }
关键改动说明
- 先更新样式再计算差值:移除滚动条样式后,立刻调用
SetWindowPos并传入SWP_FRAMECHANGED,强制窗口重新计算布局。这时候再获取窗口和客户区尺寸,得到的边框差值是完全不含滚动条的准确值。 - 简化边框差值计算:直接用窗口整体尺寸减去客户区尺寸,得到边框的总宽度和高度,比原来的坐标转换更直观不易错。
- 调整SetWindowPos参数:样式更新时用
SWP_NOMOVE | SWP_NOSIZE保证窗口位置和大小不变,只更新样式框架。
测试效果
运行修改后的代码,你会发现控制台窗口刚好适配缓冲区大小,滚动条完全消失,原来的空白区域也被填满了。
内容的提问来源于stack exchange,提问作者WraitheDX
相关产品推荐
相关产品推荐

