Цветной текст в консоли Windows

Цветной текст в консоли Windows

Можно ли закрасить определённое слово в какой-то цвет так, чтобы другие оставались стандартного цвета? (типа system("color A"))

Ха-а-ароший вопрос! (с) День радио

Понятно, что можно, только как? После некоторых поисков по msdn.microsoft.com, родилось следующее решение.

Если не влезать в тонкости Windows API, код достаточно примитивный. Многие фрагменты просто взяты из примеров MSDN. На счёт «защиты от дурака» я тоже не особо заморачивался. Всё достаточно эскизно, однако работает. (Проверял под MS Visual Studio 2012 и Dev-C++ 5.5.3.)

Информацию по консольным функциям Windows API можно посмотреть в MSDN. (Там есть ещё много чего интересного!)

Код из main.cpp можно рассматривать как пример использования класса AnsiOut.

ansiout.h

#ifndef ANSIOUT_H
#define ANSIOUT_H

#include <windows.h> 

enum AnsiColor {
    ANSI_BLACK      = 0x00,
    ANSI_BLUE       = 0x01,
    ANSI_GREEN      = 0x02,
    ANSI_RED        = 0x04,
    ANSI_INTENSITY  = 0x08,

    ANSI_CYAN       = ANSI_BLUE | ANSI_GREEN,
    ANSI_MAGENTA    = ANSI_RED | ANSI_BLUE,
    ANSI_OLIVE      = ANSI_RED | ANSI_GREEN,
    ANSI_GRAY       = ANSI_BLUE | ANSI_GREEN | ANSI_RED,

    ANSI_DARKGRAY   = ANSI_INTENSITY | ANSI_BLACK,
    ANSI_LBLUE      = ANSI_INTENSITY | ANSI_BLUE,
    ANSI_LGREEN     = ANSI_INTENSITY | ANSI_GREEN,
    ANSI_LRED       = ANSI_INTENSITY | ANSI_RED,
    ANSI_LCYAN      = ANSI_INTENSITY | ANSI_BLUE | ANSI_GREEN,
    ANSI_LMAGENTA   = ANSI_INTENSITY | ANSI_RED | ANSI_BLUE,
    ANSI_YELLOW     = ANSI_INTENSITY | ANSI_RED | ANSI_GREEN,
    ANSI_WHITE      = ANSI_INTENSITY | ANSI_BLUE | ANSI_GREEN | ANSI_RED
};

class AnsiOut {
public:

    enum ErrorCodes { INVALID_COLOR = 0, GETSTDHANDLE, GETCONSOLESCREENBUFFERINFO, GETCONSOLEMODE, SETCONSOLETEXTATTRIBUTE };

    class AnsiOutException {
    private:
        ErrorCodes error_code;
    public:
        AnsiOutException(ErrorCodes code) : error_code(code) { }
        ErrorCodes get_code() { return error_code; }
    };

    AnsiOut();
    ~AnsiOut();

    void textAttr(AnsiColor text, AnsiColor background = ANSI_BLACK);
    void textAttrDefault();

private:
    HANDLE hStdout;
    WORD wOldColorAttrs;
    void textAttr(WORD attr);
};

#endif

ansiout.cpp

#include "ansiout.h"


AnsiOut::AnsiOut() {

    // Get handle to STDIN.
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hStdout == INVALID_HANDLE_VALUE) {
        throw AnsiOutException(GETSTDHANDLE);
    }

    // Save the current text colors. 
    CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
    if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) {
        throw AnsiOutException(GETCONSOLESCREENBUFFERINFO);
    }

    wOldColorAttrs = csbiInfo.wAttributes;
}

AnsiOut::~AnsiOut() {
    textAttrDefault();
}

void AnsiOut::textAttr(WORD attr) {

    // Set the text attributes to draw red text on black background. 
    if (!SetConsoleTextAttribute(hStdout, attr)) {
        throw AnsiOutException(SETCONSOLETEXTATTRIBUTE);
    }
}

void AnsiOut::textAttr(AnsiColor text, AnsiColor background) {
    if (text > 0x0f || background > 0x0f) {
        throw AnsiOutException(INVALID_COLOR);
    }
    textAttr(static_cast<WORD>(background << 4 | text));
}

void AnsiOut::textAttrDefault() {

    // Restore the original text colors. 
    if (!SetConsoleTextAttribute(hStdout, wOldColorAttrs)) {
        throw AnsiOutException(SETCONSOLETEXTATTRIBUTE);
    }
}

main.cpp

#include <iostream>
#include <cstdlib>
#include "ansiout.h"


using namespace std;

int main() {
    try {
        cout << "Default output" << endl;
        AnsiOut ao;
        for (int i = 0; i < 16; i++) {
            ao.textAttr(AnsiColor(i));
            cout << "Sample text";
            ao.textAttrDefault();
            cout << " - text color = " << hex << i << endl;
        }
        for (int i = 0; i < 16; i++) {
            ao.textAttr(ANSI_BLACK, AnsiColor(i));
            cout << "Sample text";
            ao.textAttrDefault();
            cout << " - back color = " << hex << i << endl;
        }

        cout << endl;

        cout << "Type ";
        ao.textAttr(ANSI_LRED);
        cout << "text ";
        ao.textAttr(ANSI_LGREEN);
        cout << "by ";
        ao.textAttr(ANSI_LMAGENTA);
        cout << "specified ";
        ao.textAttr(ANSI_WHITE);
        cout << "colors. ";
        ao.textAttr(ANSI_BLACK, ANSI_LGREEN);
        cout << "And";
        ao.textAttr(ANSI_BLACK, ANSI_BLACK);
        cout << " ";
        ao.textAttr(ANSI_GREEN, ANSI_YELLOW);
        cout << "background";
        ao.textAttrDefault();
        cout << "." << endl;

        cout << endl;
        ao.textAttr(ANSI_GREEN);
        cout << "Type a number: ";
        int num;
        ao.textAttr(ANSI_YELLOW);
        cin >> num;
    }
    catch (AnsiOut::AnsiOutException e) {
        cerr << "AnsiOutException: code = " << e.get_code() << endl;
    }

    cout << endl << "Default console colors. Bye!" << endl;

    system("pause");
    return 0;
}

Воу...Надо пожалуй изучить классы.А так спасибо огромное за ответ!

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.