1、ANSI VT100 转义序列
ANSI 转义序列用于格式化控制台中的文本,例如改变文本颜色、定位光标或清除屏幕。现代系统的终端通常支持这些序列,但 Windows 命令提示符(CMD)和早期的控制台默认并不支持它们。Windows 控制台的限制, 历史上Windows 控制台(CMD)不支持 ANSI 转义序列。这是因为 Windows 控制台使用不同的系统来处理文本格式化和光标控制。然而,从 Windows 10(构建 10586 及之后版本)开始,Windows 原生支持 ANSI 转义序列,但可能需要通过编程启用它。
2、Windows 10 中启用 ANSI 转义序列
在 Windows 10(从构建 10586 起),可以通过使用 SetConsoleMode
函数来启用控制台对 ANSI 转义序列的支持。可以控制控制台是否解释 ANSI 转义序列。需要在标准输出(stdout)和标准错误(stderr)流上调用 SetConsoleMode
。具体来说,需要启用 ENABLE_VIRTUAL_TERMINAL_PROCESSING
标志。
#include <windows.h>
#include <stdio.h>
int main() {
// 获取标准输出的句柄
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (hConsole == INVALID_HANDLE_VALUE) {
fprintf(stderr, "错误: 无法获取控制台句柄\n");
return 1;
}
// 获取当前控制台模式
DWORD dwMode;
if (!GetConsoleMode(hConsole, &dwMode)) {
fprintf(stderr, "错误: 无法获取控制台模式\n");
return 1;
}
// 启用 ANSI 转义序列处理
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (!SetConsoleMode(hConsole, dwMode)) {
fprintf(stderr, "错误: 无法设置控制台模式\n");
return 1;
}
// 现在可以使用 ANSI 转义序列
printf("\x1b[31m这是一段红色文本\x1b[0m\n");
return 0;
}
3、旧版本的 Windows(Windows 10 之前)
对于早于 Windows 10 的版本,或者如果控制台不原生支持 ANSI 转义序列,可以使用外部库,或者使用 Windows 控制台 API 调用。
1)使用外部库
可以使用像 ANSI.SYS
这样的外部库,或者使用第三方库(如 PDCurses)来让 Windows 控制台支持 ANSI 转义序列。
#include <stdio.h>
#include <stdlib.h>
int main() {
// 检查是否支持 ANSI 转义序列
// 这通常需要外部库,如 ANSICON,在 Windows 10 之前的版本中
printf("\x1b[31mThis text is red!\x1b[0m\n"); // 红色文字
printf("\x1b[32mThis text is green!\x1b[0m\n"); // 绿色文字
printf("\x1b[33mThis text is yellow!\x1b[0m\n"); // 黄色文字
printf("\x1b[1mThis is bold text!\x1b[0m\n"); // 粗体文字
return 0;
}
2)使用 Windows 控制台 API 调用
可以通过使用 Windows 控制台 API(例如 SetConsoleTextAttribute
、SetConsoleCursorPosition
)来实现类似的效果,例如改变颜色和定位光标。虽然这比 ANSI 转义序列的功能少,但这些 API 调用可以用来控制控制台。
#include <windows.h>
#include <stdio.h>
void enable_virtual_terminal_processing() {
// 获取当前控制台的输出句柄
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (hConsole == INVALID_HANDLE_VALUE) {
printf("无法获取标准输出句柄.\n");
return;
}
// 获取当前控制台模式
DWORD dwMode;
if (!GetConsoleMode(hConsole, &dwMode)) {
printf("无法获取控制台模式.\n");
return;
}
// 启用虚拟终端处理
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
// 设置新的控制台模式
if (!SetConsoleMode(hConsole, dwMode)) {
printf("无法设置控制台模式.\n");
return;
}
}
void print_colored_text() {
// 启用虚拟终端处理,支持 ANSI 转义序列
enable_virtual_terminal_processing();
// 打印红色文本(使用 ANSI 转义序列)
printf("\033[31m这是红色文本\033[0m\n");
// 打印绿色文本
printf("\033[32m这是绿色文本\033[0m\n");
// 打印背景为蓝色的文本
printf("\033[44m背景是蓝色的文本\033[0m\n");
}
int main() {
print_colored_text();
return 0;
}
4、跨平台方法
如正在编写跨平台程序,并且需要在类 Unix 系统和 Windows 系统上都能工作,可以检测操作系统,并有条件地启用必要的转义序列处理。
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
// 在 Windows 上启用 ANSI 转义序列
void enable_virtual_terminal_processing() {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
if (hConsole == INVALID_HANDLE_VALUE) {
printf("无法获取标准输出句柄.\n");
return;
}
DWORD dwMode;
if (!GetConsoleMode(hConsole, &dwMode)) {
printf("无法获取控制台模式.\n");
return;
}
// 启用虚拟终端处理
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (!SetConsoleMode(hConsole, dwMode)) {
printf("无法设置控制台模式.\n");
return;
}
}
void print_colored_text() {
// 启用虚拟终端处理
enable_virtual_terminal_processing();
// 打印红色文本
printf("\033[31m这是一段红色文本\033[0m\n");
}
#else
// 对于类 Unix 系统,ANSI 转义序列原生支持
void print_colored_text() {
// 打印红色文本
printf("\x1b[31m这是一段红色文本\x1b[0m\n");
}
#endif
int main() {
// 打印带颜色的文本
print_colored_text();
return 0;
}