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