掌握顏色屬性後,下一步是學會高效地向控制台寫入字符與屬性。Windows 提供三大核心 API——FillConsoleOutputAttribute、FillConsoleOutputCharacter、WriteConsoleOutputCharacter,配合 SMALL_RECT 區域結構,可實現批量填充、局部刷新、滾動模擬等高性能操作,遠超逐字符 printf。
| API | 功能 | 適用場景 |
|---|---|---|
FillConsoleOutputAttribute | 批量設置字符屬性(顏色等),不改變字符內容 | 整行/整屏變色、高亮選中區域 |
FillConsoleOutputCharacter | 批量填充單一字符,不改變屬性 | 清屏、繪製矩形邊框、進度條背景 |
WriteConsoleOutputCharacter | 在指定座標寫入字符串,保留原屬性 | 高速輸出文本、覆寫局部內容 |
SMALL_RECTtypedef struct _SMALL_RECT {
SHORT Left; // 左上角 X
SHORT Top; // 左上角 Y
SHORT Right; // 右下角 X
SHORT Bottom; // 右下角 Y
} SMALL_RECT;
配合 SetConsoleWindowInfo 可實現視窗縮放、滾動等效果。
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#define WIDTH 80
#define HEIGHT 25
int main(void) {
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD bufSize = {WIDTH, HEIGHT};
SetConsoleScreenBufferSize(hOut, bufSize);
SMALL_RECT rect = {0, 0, WIDTH-1, HEIGHT-1};
SetConsoleWindowInfo(hOut, TRUE, &rect);
// 綠色屬性
WORD attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
CHAR_INFO screen[WIDTH * HEIGHT];
COORD bufCoord = {WIDTH, HEIGHT};
COORD charPos = {0, 0};
SMALL_RECT writeRect = {0, 0, WIDTH-1, HEIGHT-1};
srand((unsigned)time(NULL));
while (1) {
// 1. 向下滾動:複製上一行到下一行
for (int y = HEIGHT-1; y > 0; --y)
memcpy(&screen[y*WIDTH], &screen[(y-1)*WIDTH], WIDTH*sizeof(CHAR_INFO));
// 2. 頂行生成新隨機字符
for (int x = 0; x < WIDTH; ++x) {
if (rand() % 10 == 0) {
screen[x].Char.AsciiChar = '0' + (rand() % 10);
screen[x].Attributes = attr;
} else {
screen[x].Char.AsciiChar = ' ';
}
}
// 3. 一次性寫入整屏
WriteConsoleOutput(hOut, screen, bufCoord, charPos, &writeRect);
Sleep(80);
}
return 0;
}
WriteConsoleOutput 配合 CHAR_INFO 陣列可單次系統調用更新整屏,避免頻繁上下文切換。CHAR_INFO 陣列輪換,消除閃爍。FillConsoleOutputAttribute。WriteConsoleOutputCharacter 的 nLength 必須 ≤ 字符串實際長度,否則會讀取越界內存。SMALL_RECT 的 Right/Bottom 是「包含」邊界,寬度 = Right-Left+1。GetConsoleMode 返回值判斷是否為真實控制台。