Windows 控制台通過 SetConsoleTextAttribute 設置字符單元屬性,本質是一個 16 位 WORD,低 4 位控制前景色(字符顏色),高 4 位控制背景色,另有一位亮度位與反相位。
| 分類 | 常量 | 值(十六進制) | 含義 |
|---|---|---|---|
| 前景色 | FOREGROUND_BLUE | 0x0001 | 藍色分量 |
| FOREGROUND_GREEN | 0x0002 | 綠色分量 | |
| FOREGROUND_RED | 0x0004 | 紅色分量 | |
| FOREGROUND_INTENSITY | 0x0008 | 亮度增強(高亮) | |
| 背景色 | BACKGROUND_BLUE | 0x0010 | 藍色背景 |
| BACKGROUND_GREEN | 0x0020 | 綠色背景 | |
| BACKGROUND_RED | 0x0040 | 紅色背景 | |
| BACKGROUND_INTENSITY | 0x0080 | 背景亮度增強 | |
| 特殊 | COMMON_LVB_REVERSE_VIDEO | 0x4000 | 前景背景反相 |
// 前景色組合 #define FORE_BLUE FOREGROUND_BLUE #define FORE_GREEN FOREGROUND_GREEN #define FORE_RED FOREGROUND_RED #define FORE_YELLOW (FORE_RED | FORE_GREEN) #define FORE_CYAN (FORE_BLUE | FORE_GREEN) #define FORE_MAGENTA (FORE_BLUE | FORE_RED) #define FORE_WHITE (FORE_RED | FORE_GREEN | FORE_BLUE) #define FORE_GRAY FOREGROUND_INTENSITY // 高亮白/灰 #define FORE_BRIGHT_RED (FORE_RED | FOREGROUND_INTENSITY) // 背景色組合 #define BACK_BLUE BACKGROUND_BLUE #define BACK_GREEN BACKGROUND_GREEN #define BACK_RED BACKGROUND_RED #define BACK_YELLOW (BACK_RED | BACK_GREEN) #define BACK_CYAN (BACK_BLUE | BACK_GREEN) #define BACK_MAGENTA (BACK_BLUE | BACK_RED) #define BACK_WHITE (BACK_RED | BACK_GREEN | BACK_BLUE) #define BACK_GRAY BACKGROUND_INTENSITY // 前景+背景組合 #define FG_BG(fg, bg) ((fg) | (bg))
#include <stdio.h>
#include <windows.h>>
int main(void) {
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hOut == INVALID_HANDLE_VALUE) return 1;
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hOut, &csbi); // 保存原屬性以便恢復
WORD origAttr = csbi.wAttributes;
// 定義演示顏色序列
struct { WORD attr; const char *desc; } demo[] = {
{FORE_BLUE, "藍色字符"}, {FORE_RED, "紅色字符"}, {FORE_GREEN, "綠色字符"},
{FORE_MAGENTA, "洋紅字符"}, {FORE_CYAN, "青色字符"}, {FORE_YELLOW, "黃色字符"},
{FORE_GRAY, "灰色字符"}, {FORE_WHITE, "白色字符"},
{BACK_BLUE, "藍色背景"}, {BACK_RED, "紅色背景"}, {BACK_GREEN, "綠色背景"},
{BACK_MAGENTA, "洋紅背景"}, {BACK_CYAN, "青色背景"}, {BACK_YELLOW, "黃色背景"},
{BACK_GRAY, "灰色背景"}, {BACK_WHITE, "白色背景"},
{FG_BG(FORE_RED, BACK_GREEN), "綠底紅字"},
{FG_BG(FORE_BRIGHT_RED, 0), "亮紅字符"}
};
for (size_t i = 0; i < sizeof(demo)/sizeof(demo[0]); ++i) {
SetConsoleTextAttribute(hOut, demo[i].attr);
printf("%s\n", demo[i].desc);
}
SetConsoleTextAttribute(hOut, origAttr); // 恢復原屬性
return 0;
}
// 臨時設置顏色輸出,自動恢復
void cprintf(WORD attr, const char *fmt, ...) {
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hOut, &csbi);
SetConsoleTextAttribute(hOut, attr);
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
SetConsoleTextAttribute(hOut, csbi.wAttributes);
}
// 使用示例
cprintf(FG_BG(FORE_WHITE, BACK_RED), "[ERROR] %s\n", "磁盤空間不足");
cprintf(FG_BG(FORE_YELLOW, BACK_BLUE), "[WARN] %s\n", "配置項缺失");
cprintf(FORE_GREEN, "[OK] %s\n", "服務啟動成功");
GetConsoleMode 或用 _isatty(_fileno(stdout)) 判斷是否為終端\x1b[31m 紅字),可用 SetConsoleMode(hOut, ENABLE_VIRTUAL_TERMINAL_PROCESSING) 啟用,跨平台更友好SetConsoleTextAttribute 影響後續所有輸出,務必在關鍵輸出後恢復,否則污染後續日誌FOREGROUND_INTENSITY 單獨使用產生高亮白(灰),而非某種顏色的亮色。亮紅需 FORE_RED | FOREGROUND_INTENSITYsystem("color 1F") 或填滿空格字符// 簡易跨平台適配頭文件
#ifdef _WIN32
#include <windows.h>
static HANDLE hOut = NULL;
void term_init() { hOut = GetStdHandle(STD_OUTPUT_HANDLE); }
void term_set_color(int fg, int bg) {
WORD attr = 0;
// 映射邏輯...
SetConsoleTextAttribute(hOut, attr);
}
#else
// ANSI 轉義序列
void term_init() {}
void term_set_color(int fg, int bg) {
printf("\033[%d;%dm", 30+fg, 40+bg);
}
#endif
#define TERM_RESET() term_set_color(7, 0)
SetConsoleTextAttribute 是 Windows 控制台著色的原生 API,通過位運算組合 16 種基本顏色。掌握前景/背景位分離、亮度位作用、屬性保存恢復、ANSI 替代方案,即可開發出視覺友好的命令行工具。現代跨平台項目建議優先使用支持 ANSI 的庫(如 fmtlib、spdlog),僅在舊版 Windows 做兼容回退。