无需第三方应用!为Win10控制台终端启用彩色支持

提到在控制台输出彩色文字,大家都会想到使用“ANSI转义序列”(ESC \x1b \033

但自带的 cmd、Powershell 等终端并不能直接识别这样的序列,而是将其作为普通字符输出。

在此,本文给出了一种解决方案——虚拟终端序列。

为C语言控制台程序开启该特性后,即可完美实现彩色输出。

正文

简要介绍

虚拟终端序列是控制字符序列,可在写入输出流时控制游标移动、控制台颜色和其他操作。 在输入流上也可以接收序列,以响应输出流查询信息序列,或在设置适当模式时作为用户输入的编码。

序列的行为基于 VT100 和派生终端仿真器技术,尤其是 xterm 终端仿真器。

——摘自 Microsoft

默认情况下,这个模式是关闭的,因此需要通过代码开启。

参考代码

首先,构建一个函数来启用虚拟终端序列特性。

print.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#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

其次,在需要启用彩色的控制台中调用此函数即可。

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#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;
}

其它知识

ANSI 转义码格式

基本格式如下:

1
\x1b[(文字装饰);(颜色代码):

文字装饰:

0 1 3 4
正常 加粗 背景 下划线

颜色代码:

基本 8 色 基本高对比色 xterm 的 256色
30 ~ 37 90 ~ 97 0 ~ 256

其它更多的颜色可以参考:ANSI escape code

参考资料

  1. 浅析 1B[1;3;31mxterm.js1B[0m是什么?如何在终端输出带颜色等格式的字符串

  2. Microsoft官方文档:控制台虚拟终端序列