Hướng dẫn những cách đơn giản để đổi màu chữ trên console windows trong ngôn ngữ C cho newbie

Vào chủ đề chính, số là vài ngày trước tui có đi tìm hiểu cách vẽ màu trong ngôn ngữ c, có khá nhiều cách được đưa ra, một số thì khá rườm rà, một số khác phải add thêm thư viện vì không có sẵn ( như là graphic.h và winbgim.h ) nói chung là không thân thiện mấy với newbie. Cho nên tui viết bài này hướng dẫn cho các bạn ( newbie như tui ) cách để thêm màu sắc cho program.

Cách thứ nhất:

  • Cách đơn giản nhất, là sử dụng system ( "color ab"); trong đó a là màu nền ( background ) và b là màu của các ký tự ( characters ). Thay ab bằng các ký tự từ 0, 1, 2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,a ,b ,c ,d ,e ,f ( thập lục phân ) để được các màu như sau:
    0 = Black       8 = Gray
    1 = Blue        9 = Light Blue
    2 = Green       A = Light Green
    3 = Aqua        B = Light Aqua
    4 = Red         C = Light Red
    5 = Purple      D = Light Purple
    6 = Yellow      E = Light Yellow
    7 = White       F = Bright White
  • Demo dưới đây sẽ được nền trắng chữ đen.
#include <stdio.h>
#include <windows.h>
int main(){
    system("color f0");
    printf(" >Daynhauhoc.com< \n");
}

  • Tuy nhiên cách này không hề lính hoạt 1 tí nào, bạn ko thể dùng nhiều màu khác nhau cùng lúc, bạn muốn khai báo 1 biến thay cho mã màu để sử dụng linh hoạt hơn cũng ko được( tạo macro cũng là một giải pháp khá cùi bắp).

Cách thứ 2:

  • Thêm hàm dưới đây ( nhớ include windows.h )
void set_color ( int code ) {
    HANDLE color = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute( color , code );
}
  • Để sử dụng bạn chỉ việc gọi hàm này trước phần text muốn tô màu set_color( X ); Trong đó X là số nguyên từ 0 đến 256.
  • Cụ thể hơn ta cá thể mô tả X như sau:
    int X = a*16 + b; hoặc int X = a << 4 | b; hoặc int X = 0xab;
    Trong đó a ( background ) và b ( character ) là các số nguyên từ 0 đến 15 ( ký tự 0 đến f với kiểu thứ 3) tương ứng với các màu như đã nói ở cách 1.
  • Bạn có thể thắc mắc vì sao tui viết theo 3 kiểu như vậy. Nguyên do chủ yếu là để bạn thấy rõ hơn khả năng linh hoạt bằng cách sử dụng biến a và b trong kiểu thứ nhất. ( thiệt ra muốn làm màu thoi)
  • Vào một đêm mưa gió hôm kia tui có vọc thử giá trị rác và đã tìm được thêm 1 tí mở rộng nữa cho X. Cụ thể như sau:
    int X = n*16*16 + a*16 + b; hoặc int X = n << 8 | a << 4 | b; hoặc int X = 0xnab;
    với n là số nguyên từ 0 đến 15 ( ký tự từ 0 đến f );
    Tác dụng của nó là để vẽ mấy đường ngang,dọc hoặc caro ( cả ngang và dọc ). n trong khoảng giá trị 0 -> 3 bình thường , 4 -> 7 đường ngang, 8 -> 11 đường dọc, 12 -> 15 kẻ caro. Có thể rút gọn lại n từ 0 -> 3 với công thức sau int X = n << 10 | a << 4 | b;
  • Hãy áp dụng nó linh hoạt cùng với với system(“CLS”); bạn sẽ vẽ được những thứ đẹp lung linh :smile: .
  • Demo:
#include <stdio.h>
#include <windows.h>
void set_color( int code ) {
    HANDLE color = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute( color , code );
}
int main(){
    set_color( 0 << 10 | 0 << 4 | 7);
    system("CLS");
    set_color( 3 << 10 | 1 << 4 | 11);
    printf("  ####    #   #    #  #   # #   #   #   #   #   #   #  ###   ###    \n");
    printf("  #   #  # #   #  #   ##  # #   #  # #  #   #   #   # #   # #   #   \n");
    printf("  #   # #####   ##    # # # ##### ##### #   #   ##### #   # #       \n");
    printf("  #   # #   #   ##    #  ## #   # #   # #   #   #   # #   # #   #   \n");
    printf("  ####  #   #   ##    #   # #   # #   # #####   #   #  ###   ###    \n");
    printf("          #                                             #           \n\n");
    set_color( 1 << 10 | 0 << 4 | 10);
    printf("===============================\n");
    printf("<1>. Hack daynhauhoc.com       \n");
    printf("<2>. Quit                      \n");
    printf("===============================\n");
    printf("[ Select ]:");
    getchar();
    return 0;
}


Bài viết của một người mới học lập trình, nếu có thiếu sót xin vui lòng bỏ qua cho.
Tiện đây xin cảm ơn những người đã giáp đáp thắc mắc cho những câu hỏi cua tui trên diễn đàn, xin cảm ơn.

5 Likes

Mình bổ sung thêm cách thứ 3. :kissing:
Đó là dùng luôn ANSI Escape Sequences.

Demo:


Nếu muốn in ra một dòng chữ màu đỏ sử dụng ANSI Escape Sequences trên cmd thì ta gõ:

echo ^[[31mRed text^[[0m

image
Chú ý:

  • ^[ phải nhập bằng cách gõ ctrl + [.
  • ^[[0m là để đưa màu của console về bình thường, nếu không nó sẽ màu đỏ (do [31m) hết.

Muốn màu đậm hơn thì kết hợp với format bold style 1.

echo ^[[1;31mRed text^[[0m

image


Để sử dụng cái này trong C thì chỉ cần gọi echo qua system() trong thư viện stdlib.h. Escape character ^[ được thay bằng \e.

system("echo \e[1;31mRed text\e[0m");

Dựa vào những thứ trên ta hoàn toàn có thể viết một hàm tên set_color() nhận vào là một Escape Sequences để format cho echo.

void set_color(const char *color) {
    char cmd[512];
    sprintf(cmd, "echo|set /p=\"\e[%sm\"", color);
    system(cmd);
}

Bình thường thì echo nó sẽ tự thêm newline nên để echo mà không có newline thì dùng echo|set /p="content".

Viết code chạy thử:

#include <stdio.h>
#include <stdlib.h>

void set_color(const char *color) {
    char cmd[512];
    sprintf(cmd, "echo|set /p=\"\e[%sm\"", color);
    system(cmd);
}

int main() {
    set_color("01;31");
    printf("Red ");
    set_color("01;33");
    printf("and ");
    set_color("01;32");
    printf("Green\n");
    set_color("0");
}

image


Ngoài ra thì cách này cũng áp dụng được cho linux, nhưng thay vì dùng echo thì in thẳng format color bằng printf() luôn.

void set_color(const char *color) {
#ifdef __linux__
    printf("\e[%sm", color);
#else
    char cmd[512];
    sprintf(cmd, "echo|set /p=\"\e[%sm\"", color);
    system(cmd);
#endif
}

P/S: chạy thử trên wsl nhanh hơn trên cmd tầm 3s. :kissing:

Code phần demo ở đây
Nguồn tham khảo: stack overflow

6 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?