目录
前言
本文章所使用的一些API为旧版API
,建议使用其它方案代替它们。
本文章多有些纰漏,若发现错误请在评论区指正。
注: 文章内所有代码均在VS2019下编译通过。
一、控制台缓冲区大小
一、获取缓冲区大小
GetConsoleScreenBufferInfo 可以获取到控制台窗口的一些信息。
BOOL WINAPI GetConsoleScreenBufferInfo(
_In_ HANDLE hConsoleOutput, // 输出句柄
_Out_ PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo // 缓冲区信息结构体
);
PCONSOLE_SCREEN_BUFFER_INFO 实际上是一个指针,可以使用_CONSOLE_SCREEN_BUFFER_INFO 或 CONSOLE_SCREEN_BUFFER_INFO 替代它。此结构体的原型为:
typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
COORD dwSize; // 缓冲区大小
COORD dwCursorPosition; // 控制台屏幕缓冲区中光标的列和行坐标
WORD wAttributes;
SMALL_RECT srWindow; // 显示窗口左上角和右下角的控制台屏幕缓冲区的坐标(即窗口大小)
COORD dwMaximumWindowSize; // 在给定当前屏幕缓冲区大小和字体和屏幕大小的情况下,它包含控制台窗口的最大大小(字符列和行)
} CONSOLE_SCREEN_BUFFER_INFO;
此结构体同样包含缓冲区光标位置的信息,在获取光标位置时可以使用此结构体。
下方代码将会输出缓冲区大小。
#include <stdio.h>
#include <Windows.h>
int main(int argc, char* argv[]) {
// 获取输出句柄
HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(outputHandle, &info);
printf("缓冲区大小: x=%hd, y=%hd\n", info.dwSize.X, info.dwSize.Y);
return 0;
}
二、设置缓冲区大小
(旧版API)SetConsoleScreenBufferSize 可以修改控制台的缓冲区大小。
WINBASEAPI
BOOL
WINAPI
SetConsoleScreenBufferSize(
_In_ HANDLE hConsoleOutput, // 输出句柄
_In_ COORD dwSize // 新缓冲区大小
);
此函数接受一个 COORD 结构体 作为参数,其原型为:
typedef struct _COORD {
SHORT X;
SHORT Y;
} COORD, *PCOORD;
下方代码将会设置缓冲区大小为115×40个字符。
#include <stdio.h>
#include <Windows.h>
int main(int argc, char* argv[]) {
// 获取输出句柄
HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
// 定义大小
COORD size = {
115, 40 };
// 应用
SetConsoleScreenBufferSize(outputHandle, size);
SetConsoleScreenBufferSize(outputHandle, size);
return 0;
}
不建议使用此API。
三、更详细的结构体
CONSOLE_SCREEN_BUFFER_INFOEX 结构体能够记录更多的控制台信息,并且也有与之匹配的获取(GetConsoleScreenBufferInfoEx)和设置(SetConsoleScreenBufferInfoEx)函数。多数情况下,笔者更推荐使用 CONSOLE_SCREEN_BUFFER_INFOEX,因为 CONSOLE_SCREEN_BUFFER_INFOEX 拥有与之匹配的函数,而 _CONSOLE_SCREEN_BUFFER_INFO 和 CONSOLE_SCREEN_BUFFER_INFO 仅有一个获取函数(GetConsoleScreenBufferInfo),所以,能用就用吧。
下面的代码演示了如何使用 CONSOLE_SCREEN_BUFFER_INFOEX。
#include <stdio.h>
#include <Windows.h>
int main(int argc, char* argv[]) {
// 获取输出句柄
HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFOEX info;
info.cbSize = sizeof(info); // 不要忘记指定结构体大小
GetConsoleScreenBufferInfoEx(outputHandle, &info);
printf(
"缓冲区大小: x=%hd, y=%hd\n"
"窗口大小: x=%hd, y=%hd\n"
"光标坐标: x=%hd, y=%hd\n"
, info.dwSize.X, info.dwSize.Y, info.srWindow.Right + 1, info.srWindow.Bottom + 1, info.dwCursorPosition.X, info.dwCursorPosition.Y);
return 0;
}
四、特性
新版控制台又出特性了。在使用 GetConsoleScreenBufferInfoEx 获取控制台缓冲区信息后,如果再次设置,控制台的大小竟会缩减1行!?笔者在 stackoverflow 查找到了解决方法——只需在获取信息后将 srWindow 的 Right 和 Bottom 加 1。请参阅下方代码。
#include <stdio.h>
#include <Windows.h>
int main() {
// 输出句柄
HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
// 控制台缓冲区信息
CONSOLE_SCREEN_BUFFER_INFOEX csbi;
csbi.cbSize = sizeof(csbi);
// 获取信息
GetConsoleScreenBufferInfoEx(outputHandle, &csbi);
printf("获取到的 srWindow 的值:{%d %d %d %d}\n", csbi.srWindow.Left, csbi.srWindow.Top, csbi.srWindow.Right, csbi.srWindow.Bottom);
csbi.srWindow.Right++;
csbi.srWindow.Bottom++;
printf("更正后的 srWindow 的值:{%d %d %d %d}\n", csbi.srWindow.Left, csbi.srWindow.Top, csbi.srWindow.Right, csbi.srWindow.Bottom);
return 0;
}
效果:
二、窗口大小
一、获取窗口大小
对于这种需求,CONSOLE_SCREEN_BUFFER_INFOEX 可以解决一切问题。但现在这里将依然使用 GetConsoleScreenBufferInfo 函数获取窗口大小。下面代码将会演示此功能。
#include <stdio.h>
#include <Windows.h>
int main(int argc, char* argv[]) {
// 获取输出句柄
HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(outputHandle, &info);
printf("窗口大小: x=%hd, y=%hd\n", info.srWindow.Right + 1, info.srWindow.Bottom + 1);
return 0;
}
注: srWindow会把0也算进窗口大小内,所以需要将结果加1得到正确的数字。
使用 CONSOLE_SCREEN_BUFFER_INFOEX 的样例在第一节的第三小节。
二、设置窗口大小
(旧版API)SetConsoleWindowInfo 可以做到这一点。
查阅 Microsoft Docs 了解此函数的参数。
下面的代码可以实现此功能。
#include <stdio.h>
#include <Windows.h>
int main(int argc, char* argv[]) {
// 获取输出句柄
HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
SMALL_RECT winSize = {
0, 0};
winSize.Right = 20 - 1;
winSize.Bottom = 10 -<