首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Windows控制台圖形界面編程:SetConsoleTextAttribute 實現彩色文本與背景

     編輯:關於C語言

Windows Console 顏色屬性機制

Windows 控制台通過 SetConsoleTextAttribute 設置字符單元屬性,本質是一個 16 位 WORD,低 4 位控制前景色(字符顏色),高 4 位控制背景色,另有一位亮度位與反相位。

顏色常量定義與組合邏輯

基礎顏色常量(WinCon.h)

分類常量值(十六進制)含義
前景色FOREGROUND_BLUE0x0001藍色分量
FOREGROUND_GREEN0x0002綠色分量
FOREGROUND_RED0x0004紅色分量
FOREGROUND_INTENSITY0x0008亮度增強(高亮)
背景色BACKGROUND_BLUE0x0010藍色背景
BACKGROUND_GREEN0x0020綠色背景
BACKGROUND_RED0x0040紅色背景
BACKGROUND_INTENSITY0x0080背景亮度增強
特殊COMMON_LVB_REVERSE_VIDEO0x4000前景背景反相

常用顏色組合宏定義

// 前景色組合
#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", "服務啟動成功");

常見問題與避坑指南

  1. 顏色不生效:輸出重定向到文件/管道時,控制台屬性無效。需檢查 GetConsoleMode 或用 _isatty(_fileno(stdout)) 判斷是否為終端
  2. ANSI 轉義序列替代方案:Windows 10 TH2+ (v1511) 原生支持 VT100 轉義序列(\x1b[31m 紅字),可用 SetConsoleMode(hOut, ENABLE_VIRTUAL_TERMINAL_PROCESSING) 啟用,跨平台更友好
  3. 屬性持久化:SetConsoleTextAttribute 影響後續所有輸出,務必在關鍵輸出後恢復,否則污染後續日誌
  4. 亮度位誤區:FOREGROUND_INTENSITY 單獨使用產生高亮白(灰),而非某種顏色的亮色。亮紅需 FORE_RED | FOREGROUND_INTENSITY
  5. 背景色填滿:控制台背景色僅覆蓋已輸出字符區域。全屏背景需 system("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 做兼容回退。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved