Windows.h Và Hàm Định Dạng Nội Dung Console (P2)

Windows.h Và Hàm Định Dạng Nội Dung Console (P2)

Ở phần 1, mình đã giới thiệu với các bạn về thư viện Windows.h và các hàm định dạng màn hình console. Trong bài viết này, mình sẽ nói về các hàm định dạng nội dung trong Console.

Nếu các bạn đã xem rồi thì chúng ta bắt đầu nào!

Hiển thị tiếng Việt và các ký tự đặc biệt

Console mặc định để Code page là 437 (OEM – United States), nó không hỗ trợ các ký tự đặc biệt cũng như tiếng Việt, nên nếu bạn hiển thị một chuỗi "Xin chào mọi người!" chẳng hạn, chắc chắn, nó sẽ bị lỗi font như hình dưới:

Dành cho các bạn chưa biết, Code page (còn được gọi là bộ ký tự (Character Set) hay bộ mã hóa (Encoding)) là một bảng các giá trị trong đó mỗi ký tự dược gán một con số đại diện. Một code page cho phép một máy tính xác định các ký tự và hiển thị nó cách chính xác.

Vậy để hiển thị tiếng Việt, ta phải chọn một code page phù hơp để thay thế cho 437. Unicode (uft-8) là một "ứng cứ viên sáng giá" đấy, với code page ID 65001, bộ mã này có thể hiển thị tới 1.112.064 ký tự.

Cú pháp:

BOOL WINAPI SetConsoleOutputCP(
  _In_ UINT wCodePageID
);

Tham số:

  • wCodePageID, như tên của nó là ID của code page bạn set cho Console. Như nói ở trên để hiển thị tiếng Việt và các ký tự đặc biệt ta dùng 65001.

Demo:

Thay đổi màu chữ

Cú pháp:

BOOL WINAPI SetConsoleTextAttribute(
  _In_ HANDLE hConsoleOutput,
  _In_ WORD   wAttributes
);

Tham số:

  • hConsoleOutput xem trong phần 1.
  • wAttributes là mã màu bạn một đặt cho chữ.

0 = Black      

8 = Gray

1 = Blue       

9 = Light Blue

2 = Green      

10 = Light Green

3 = Aqua       

11 = Light Aqua

4 = Red        

12 = Light Red

5 = Purple     

13 = Light Purple

6 = Yellow     

14 = Light Yellow

7 = White   

15 = Bright White

Từ 16 màu trên, ta có thể sử dụng công thức i * 16 + j để tạo ra các màu mới, trong đó i là mã màu nền, j là mã màu chữ. Ví dụ: 2 = 0 * 16 + 2 suy ra wAttributes = 2 thì màu nền là Black, màu chữ là Green; 80 = 5 * 16 + 0 suy ra wAttributes = 80 thì màu nền là Purple, màu chữ là Black.

Theo công thức đó, ta có thể xây dựng một hàm như sau:

void SetColor(int backgound_color, int text_color)
{
    HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);

    int color_code = backgound_color * 16 + text_color;
    SetConsoleTextAttribute(hStdout, color_code);
}

Demo:

Nói chính xác hơn thì background_colorhighlight_color mới đúng, nó không phải là màu nền cho cả console, mà chỉ những nơi có chữ.

Để thay đổi màu nền cho cả console, các bạn phải dùng câu lệnh system() (có thể mình sẽ nói về nó ở một bài viết sắp tới).

Di chuyển con trỏ đến vị trí (x; y)

Trước tiên, Console lấy gốc tọa độ là góc trên bên trái, trục x nằm ngang và trục y nằm dọc. Nó gần giống hệ tọa độ trong toán học, tuy nhiên khác một điều là chiều dương trục y là chiều đi xuống và cả hai trục đều không có chiều âm.

Cú pháp:

BOOL WINAPI SetConsoleCursorPosition(
  _In_ HANDLE hConsoleOutput,
  _In_ COORD  dwCursorPosition
);

Tham số:

  • hConsoleOutput là một HANDLE đã nói ở phần 1.
  • dwCursorPosition là một COORD chứa 2 giá trị X, Y là tọa độ của con trỏ mà bạn muốn di chuyển đến. Cấu trúc COORD xem trong phần 1.

Để sử dụng cách đơn giản, các bạn xây dựng hàm sau:

void GoTo(SHORT posX, SHORT posY)
{
	HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD Position;
    Position.X = posX;
    Position.Y = posY;

	SetConsoleCursorPosition(hStdout, Position);
}

Khi GoTo đến một tọa độ và in gì đó, nếu tại đó đang có chữ thì nó sẽ in đè lên.

Và vì nó không có tọa độ âm, nên nếu các bạn truyền vào giá trị âm cho x hoặc y, nó GoTo(0, 0).

Demo:

Thay đổi Console Title 

Mặc định file .exe cosole khi chạy Title sẽ là đường dẫn của file. Tuy nhiên ta hoàn toàn có thể thay đổi nó.

Cú pháp:

BOOL WINAPI SetConsoleTitle(
  _In_ LPCTSTR lpConsoleTitle
);

Tham số:

  • lpConsoleTitle là một wchar_t có dạng L"string" hoặc TEXT("string").

Demo:

Ẩn/Hiện con trỏ

Để ẩn/hiện con trỏ chuột, các bạn sử dụng hàm SetConsoleCursorInfo().

Cú pháp:

BOOL WINAPI SetConsoleCursorInfo(
  _In_       HANDLE              hConsoleOutput,
  _In_ const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo
);

Tham số:

  • hConsoleOutput
  • lpConsoleCursorInfo là một con trỏ có cấu trúc CONSOLE_CURSOR_INFO:
typedef struct _CONSOLE_CURSOR_INFO {
  DWORD dwSize;
  BOOL  bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;

Trong đó, dwSize là kích thước của con trỏ. bVisible nếu TRUE con trỏ sẽ được hiện, nếu FALSE con trỏ sẽ ẩn, ta chỉ cần quan tâm đến tham số này.

Các bạn có thể viết một hàm như sau:

void ShowCur(bool CursorVisibility)
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO ConCurInf;
    
    ConCurInf.dwSize = 10;
    ConCurInf.bVisible = CursorVisibility;
    
    SetConsoleCursorInfo(handle, &ConCurInf);
}

Demo:

Vô hiệu hóa Select (bôi đen text)

Phải là "bôi trắng" chứ nhỉ :v

Select thuộc chế độ Quick Edit, vậy để không cho người dùng kéo chuột để bôi đen chữ, thì ta Disable Quick Edit Mode thôi. 

Sử dụng hàm SetConsoleMode().

Cú pháp:

BOOL WINAPI SetConsoleMode(
  _In_ HANDLE hConsoleHandle,
  _In_ DWORD  dwMode
);

Tham số:

  • hConsoleHandle ở đây là HANDLE đến Input.
  • dwMode để vô hiệu hóa Select là ~ENABLE_QUICK_EDIT_MODE (NOT của ENABLE là DISABLE).

Xây dựng hàm như sau:

void DisableSelection()
{
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);

    SetConsoleMode(hStdin, ~ENABLE_QUICK_EDIT_MODE);
}

Demo:

Kết

Mình đã giới thiệu đến các bạn về Windows.h và một số hàm trong trong thư viện này, các bạn có thể sử dụng để vọc vạch làm vài game Console khi chán làm bài tập giải thuật nhé.

Nếu thấy bài viết hay và giúp được gì đó cho các bạn hãy rate 5* và chia sẻ cho mọi người tham khảo. Nếu có thắc mắc hoặc thấy bài viết còn sai sót hãy để lại comment bên dưới :v

Cảm ơn các bạn!!!