【技能分享】为C语言控制台终端启用彩色支持(无需第三方软件)
### 前言提到在控制台输出彩色文字,大家都会想到使用“ANSI转义序列”(`ESC` `\x1b` `\033`)
但自带的 cmd、Powershell 等终端并不能直接识别这样的序列,而是将其作为普通字符输出,非但没有美观效果,而且会让终端看起来很乱。
在此,本文给出了一种解决方案——虚拟终端序列。为C语言控制台程序开启该特性后,即可完美实现彩色输出。
### 效果图
使用之后的效果是这样的(cmd):
### 开工
#### 简要介绍
> 虚拟终端序列是控制字符序列,可在写入输出流时控制游标移动、控制台颜色和其他操作。 在输入流上也可以接收序列,以响应输出流查询信息序列,或在设置适当模式时作为用户输入的编码。
> 序列的行为基于 VT100 和派生终端仿真器技术,尤其是 xterm 终端仿真器。
——摘自 Microsoft
默认情况下,这个模式是关闭的,因此需要通过代码开启。(注意 Win7 系统可能不适用)
#### 参考代码
Step1,构建一个函数来启用虚拟终端序列特性。
新建一个 `print.c` ,这里面是开启特性的关键代码:
```c
#include "print.h"
/*!
* 为传统控制台启用色彩支持
*/
DWORD enableColorful(void)
{
#if PRINT_COLORFUL
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hOut == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
DWORD dwMode = 0;
if (!GetConsoleMode(hOut, &dwMode))
{
return GetLastError();
}
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (!SetConsoleMode(hOut, dwMode))
{
return GetLastError();
}
#endif
return 0;
}
```
然后新建一个 `print.h` 用于声明上面的函数,以及设置常用颜色的宏定义:
```c
#ifndef PRINT_H
#define PRINT_H
#include <stdio.h>
#include <windows.h>
DWORD enableColorful(void);
//* 配置 */
#define PRINT_COLORFUL 1// 是否启用彩色
//* 颜色定义 */
#define COLOR_GRAY "\033[37m"
#define COLOR_GREEN "\033[32m"
#define COLOR_YELLOW "\033[33m"
#define COLOR_DARKGRAY "\033[30m"
#define COLOR_BLACK "\033[30m"
#define COLOR_NOCOLOR "\033[0m"
#define COLOR_DEEPBLUE "\033[34m"
#define COLOR_RED "\033[31m"
#endif // PRINT_H
```
Step2,在需要启用彩色的控制台中调用此函数即可。
示例都在代码里啦,注释也很丰富~
`main.c`:
```c
#include "print.h"
int main()
{
enableColorful(); // 开启彩色支持
// 使用示例
printf(COLOR_GREEN "INFO: 这是一条提示信息\n" COLOR_NOCOLOR);
printf(COLOR_RED "ERROR: 这是一条错误信息\n" COLOR_NOCOLOR);
// 接下来的示例来自微软
// Try some Set Graphics Rendition (SGR) terminal escape sequences
wprintf(L"\x1b[31mThis text has a red foreground using SGR.31.\r\n");
wprintf(L"\x1b[1mThis text has a bright (bold) red foreground using SGR.1 to affect the previous color setting.\r\n");
wprintf(L"\x1b[mThis text has returned to default colors using SGR.0 implicitly.\r\n");
wprintf(L"\x1b[34;46mThis text shows the foreground and background change at the same time.\r\n");
wprintf(L"\x1b[0mThis text has returned to default colors using SGR.0 explicitly.\r\n");
wprintf(L"\x1b[31;32;33;34;35;36;101;102;103;104;105;106;107mThis text attempts to apply many colors in the same command. Note the colors are applied from left to right so only the right-most option of foreground cyan (SGR.36) and background bright white (SGR.107) is effective.\r\n");
wprintf(L"\x1b[39mThis text has restored the foreground color only.\r\n");
wprintf(L"\x1b[49mThis text has restored the background color only.\r\n");
return 0;
}
```
到此,新技能成功 Get √。
总体上来说,使用还是很方便而且简单的,欢迎各位小伙伴交流。
### 其它知识
#### ANSI 转义码格式
基本格式如下:
```
\x1b[(文字装饰);(颜色代码):
```
文字装饰:
| 0 | 1 | 3 | 4 |
| ---- | ---- | ---- | ------ |
| 正常 | 加粗 | 背景 | 下划线 |
颜色代码:
| 基本 8 色 | 基本高对比色 | xterm 的 256色 |
| --------- | ------------ | -------------- |
| 30 ~ 37 | 90 ~ 97 | 0 ~ 256 |
关于更多的颜色可以参考一下 Wiki:(https://en.wikipedia.org/wiki/ANSI_escape_code#Colors)
#### 一些值得参考的资料
1. [浅析 \x1B\(https://www.cnblogs.com/goloving/p/15015053.html)
2. Microsoft官方文档:[控制台虚拟终端序列](https://docs.microsoft.com/zh-cn/windows/console/console-virtual-terminal-sequences) 牛逼,大佬! 这个好像和bash一样使用\0xb[xxm 薛定谔消失的弦 发表于 2022-8-31 14:13
这个好像和bash一样使用\0xb
是的,但是直接printf的话无法使用,要用 API 临时开启一下虚拟终端特性 这个功能很小众!但很有创意!感谢楼主分享! 最近正在研究终端彩色输出,感谢分享 之前找好久都没找到,楼主强啊 windows下,直接使用system("cls") 就可以启用了。
页:
[1]