C/C++: Вывод цветного текста посредством WinAPI

Если вам доводилось делать попытки написания игр в виде "консольных" приложений Windows, то возможно вас интересовал вопрос,

А нельзя ли, к примеру, раскрасить выводимый текст?

И, стоит заметить, ответ на него не так уж и глубоко спрятан. Как факт, на MSDN есть целая секция, посвященная работе с консолями. Правда, она немного запутанная. И на английском. Но в остальном, нужную документацию в ней можно найти методом перебора функций из списка доступных. Но данная статья посвящена выводу цветного текста а не перебору, поэтому вернемся к нему.

Непосредственная "раскраска" текста выполняется через одну функцию Windows.h, именуемую SetConsoleTextAttribute. Возможно, было бы проще назвать ее "SetConsoleColor", дабы пользователь не тратил некое количество времени на угадывание имени функции в случае отсутствия документации, но она служит и для других целей (например подчеркивания текста), так что особо не пожалуешься.

Функция принимает два аргумента, обозначающие дескриптор вывода консоли и набор флагов соответственно.
Придерживаясь традиции запутанного изложения документации, описание функции не говорит нам, откуда можно было бы получить данный дескриптор, но на практике все просто. Поскольку в большинстве случаев перекрашенный текст должен выводиться на stdout, можно воспользоваться GetStdHandle:

HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

В качестве второго аргумента в функцию подается набор флагов (или целочисленная, если вы любите магические числа). Интересующие нас значения включают BACKGROUND_ и FOREGROUND_, обозначающие цвет фона и текста соответственно. То есть, при наличии ранее приведенной строки кода, вывод зеленого текста на экран может быть реализован так:

SetConsoleTextAttribute(hStdOut, FOREGROUND_GREEN);
printf("Green\n");

Если же нам нужно вывести, к примеру, желтый текст, это делается совмещением флагов:

SetConsoleTextAttribute(hStdOut,
    FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
printf("Yellow\n")

Для раскраски фона дела обстоят аналогично:

SetConsoleTextAttribute(hStdOut,
    BACKGROUND_BLUE | BACKGROUND_INTENSITY | FOREGROUND_RED |
    FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
printf("White on blue");

Так же стоит заметить, что при переносе строки или очистке экрана текущий цвет заполнит остаток строки или экран соответственно.

А теперь немного о самих цветах. Как-то так сложилось, что для консольных приложений выделяется целых 16 цветов, представленных в WinAPI 4-мя битами, отвечающими за красный, синий, и зеленый компоненты, и дополнительный бит "яркости" цвета.
В результате, доступная цветовая палитра выглядит где-то так:


Где RGBI - красный, зеленый, синий, интенсивность.

Посматривая на данную таблицу, можно задать логичный вопрос,

А что, если я хочу больше цветов?

И, стоит отметить, что в данном отношении не все так ужасно. В стандартной кодовой таблице символов для "совмещения цветов" есть три символа с индексами 176, 177, и 178 соответственно. Символ 177 является "клеточкой" для 50% совмещения, в то время как 176 и 178 содержат диагональные линии, представляющие заполнение в ~25% и ~75% соответственно. В результате, с помощью вывода данных символов с разными цветами фона и текста, мы можем получить некоторое разнообразие цветов:


Всего около 736 цветов, многие из которых вы, наверное, не хотели бы использовать.

Если это имеет интерес, исходный код вывода вышеприведенной иллюстрации можно взять ниже.

Код на Gist

Похожие записи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.