Pokročilá práce s konzolí v C++

C++ Základní konstrukce C++ Pokročilá práce s konzolí v C++

V následujícím tutoriálu si ukážeme, jak změnit barvu textu v konzoli. Dále nastavíme konzoli titulek a naučíme za měnit pozici kurzoru nebo ho úplně vypnout.

Změna barvy textu v konzoli

Začneme tím, že si vytvoříme nový projekt (nebo otevřeme starý) a do souboru s kódem vložíme asi tohle:

#include <iostream>  //standartní výstup
#include <windows.h> //tady jsou definované funkce, které budeme používat
using namespace std;

int main(void)
{
        cin.get(); //opatření, aby se program hned neukončil a čekal na stisk kávesy Enter
        return 0;
}

Asi nejjednodušší způsob jak změnit barvu textu je použít funkci system(). Té jako parametr předáme řetězec "color xy", kde za x a y dosadíme šestnáctkové hodnoty 0-F. X mění barvu pozadí a y barvu textu.

číslo barva
0 ponechat původní barvu
1 tmavě modrá
2 tmavě zelená
3 tmavě tyrkysová
4 tmavě červená
5 tmavě růžová (fialová)
6 tmavě žlutá
7 šedá
8 tmavě šedá
9 modrá
A zelená
B tyrkysová
C červená
D růžová (fialová)
E žlutá
F bílá

Například pro tmavě zelený text na modrém pozadí stačí napsat:

system("color 92");

Hlavní nevýhoda této funkce je, že změní barvu veškerého textu. Pokud chceme měnit jen jeho část, musíme na to jít složitěji. Asi nejlepší je použít:

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), /*barva*/)

K tomu si připravíme seznam barev (všimněte si stejného pořadí barev jako u funkce system()):

#define black 0
#define dark_blue 1
#define dark_green 2
#define dark_cyan 3
#define dark_red 4
#define dark_magenta 5
#define dark_yellow 6
#define grey 7
#define dark_grey 8
#define blue 9
#define green 10
#define cyan 11
#define red 12
#define magenta 13
#define yellow 14
#define white 15

nebo

enum Colors{black, dark_blue, dark_green, dark_cyan, dark_red, dark_magenta, dark_yellow, grey, dark_grey,
        blue, green, cyan, red, magenta, yellow, white};

Pak si vytvoříme funkci pro změnu barvy:

void set_text_color(int background_color, int foreground_color)
{
        //barvu získáme jako hodnotu barvy textu přičtenou k šestnáctinásobku hodnoty barvy pozadí
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), background_color*16+foreground_color);
}

Každý výstup na konzoli po zavolání této funkce bude mít zvolenou barvu. K tomu si můžeme vytvořit funkci pro výstup barevného textu:

void colored_cout(int background_color, int foreground_color, const char* text)
{
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), background_color*16+foreground_color);//nová barva
        cout << text;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), grey);//nastavení původní (základní) barvy
}

Tuhle funkci si můžeme přetížit i pro další datové typy:

void colored_cout(int background_color, int foreground_color, bool value)
{
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), background_color*16+foreground_color);//nová barva
        cout << value;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), grey);//původní barva
}
void colored_cout(int background_color, int foreground_color, short number)
{
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), background_color*16+foreground_color);//nová barva
        cout << number;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), grey);//původní barva
}
void colored_cout(int background_color, int foreground_color, int number)
{
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), background_color*16+foreground_color);//nová barva
        cout << number;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), grey);//původní barva
}
void colored_cout(int background_color, int foreground_color, float number)
{
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), background_color*16+foreground_color);//nová barva
        cout << number;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), grey);//původní barva
}
void colored_cout(int background_color, int foreground_color, double number)
{
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), background_color*16+foreground_color);//nová barva
        cout << number;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), grey);//původní barva
}

Funkčnost můžeme vyzkoušet například jednoduchým cyklem, který zobrazí všechny možné kombinace barev.

for(int i = 0; i<16; i++)
        for(int j = 0; j<16; j++)
        {
                colored_cout(i, j, i*16+j);
                colored_cout(i, j, " Hello world\n");
        }

Změna titulku konzole

Změny titulku můžeme docílit například takto:

system("Title Text coloring");

Tento způsob by se ale neměl používat (stejně jako system("color 0F") ). Proto použijeme funkci SetConsoleTitle. Té jako parametr předáme nový titulek konzole ve tvaru TEXT("nový titulek") (to kvůli správnému datovému typu).

SetConsoleTitle(TEXT("Text coloring"));

Pozice kurzoru

Pozici v konzoli můžeme měnit pomocí funkce SetConsoleCur­sorPosition. Té předáme jako první parametr GetStdHandle(STD_O­UTPUT_HANDLE) (stejně jako u SetConsoleTex­tAttribute) a jako druhý parametr instanci struktury COORD. Do ní můžeme pozici uložit dvěma způsoby:

COORD pozice = { x, y };
//nebo
COORD pozice;
pozice.X = x;
pozice.Y = y;

Takže funkce pro přesunutí kurzoru by mohla vypadat takhle:

void move_cursor( int x, int y )
{
    COORD pozice = { x, y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pozice);
}

Skrytí kurzoru

Na závěr si ještě ukážeme, jak skrýt (nebo zobrazit) kurzor pomocí SetConsoleCur­sorInfo. Ta má stejně jako SetConsoleCur­sorPosition a SetConsoleTex­tAttribute dva parametry:

GetStdHandle(STD_O­UTPUT_HANDLE) a instanci struktury CONSOLE_CURSOR_IN­FO.

void cursor_visible(bool visible)
{
   CONSOLE_CURSOR_INFO info = {100, visible};
   /*nebo
   CONSOLE_CURSOR_INFO info;
   info.dwSize = 100;
   info.bVisible = visible;*/
   SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
}

A ještě pár rad na závěr:

  1. Není dobré používat funkci system(). Za prvé je pomalá a za druhé její používání není zrovna přehledné.
  2. Místo neustálého psaní GetStdHandle(STD_O­UTPUT_HANDLE) si můžeme vytvořit proměnnou se stejnými daty:
    HANDLE cHandle = GetStdHandle(STD_O­UTPUT_HANDLE);
    SetConsoleTex­tAttribute(cHan­dle, grey);

 

Stáhnout

Staženo 267x (19.43 MB)
Aplikace je včetně zdrojových kódů v jazyce C++

 

  Aktivity (1)

Článek pro vás napsal Zdeněk Pavlátka
Avatar
Autor se věnuje spoustě zajímavých věcí :)

Jak se ti líbí článek?
Celkem (3 hlasů) :
2.333332.33333 2.333332.333332.33333


 


Miniatura
Předchozí článek
Funkce a prototypy v C++
Miniatura
Všechny články v sekci
Základy C++

 

 

Komentáře

Avatar
Honza
Neregistrovaný
Avatar
Honza:

Díky moc. Hodně užitečný článek

 
Odpovědět 20.10.2013 11:56
Avatar
mkapinaj
Člen
Avatar
mkapinaj:

cav som tu novy takze zdravim :)

chalani hodte sem prosim funkcny cely kod, lebo tie farby su podla mna absolutne neprehladne a stale mi to nechce spustit :/

"system("color 12") funguje ako ma ale ostatne nie teda aspon neviem ako nanho"
vopred dakujem

Editováno 12.1.2015 5:44
 
Odpovědět 12.1.2015 5:41
Avatar
Odpovídá na mkapinaj
Libor Šimo (libcosenior):
#include <iostream>
#include <windows.h>

//barvu získáme jako hodnotu barvy textu přičtenou k šestnáctinásobku hodnoty barvy pozadí
#define NOVA_FARBA SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), background_color*16+foreground_color)
#define ZELENA_FARBA SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), zelena)

typedef enum { cierna, tmavo_modra, tmavo_zelena, tmavo_azurova, tmavo_cervena, tmavo_purpurova, tmavo_zlta, seda, tmavo_seda,
               modra, zelena, azurova, cervena, purpurova, zlta, biela
} FARBA;

void set_text_color(int background_color, int foreground_color);
void colored_cout(int background_color, int foreground_color, const char* text);
void colored_cout(int background_color, int foreground_color, bool value);
void colored_cout(int background_color, int foreground_color, short number);
void colored_cout(int background_color, int foreground_color, int number);
void colored_cout(int background_color, int foreground_color, float number);
void colored_cout(int background_color, int foreground_color, double number);

using namespace std;

int main()
{
    set_text_color(biela, tmavo_azurova);
    cout << "Tento text je tmavo azurovy na bielom podklade" << endl;
    set_text_color(biela, cervena);
    cout << "Tento text je cerveny na bielom podklade" << endl;
    set_text_color(biela, modra);
    cout << "Tento text je modry na bielom podklade" << endl;
    set_text_color(modra, biela);
    cout << "Tento text je biely na modrom podklade" << endl;

    colored_cout(biela, modra, "Popokatepetl");
    cout << endl;
    colored_cout(cervena, modra, true);
    cout << endl;
    colored_cout(zlta, azurova, 25);
    cout << endl;
    colored_cout(seda, zlta, 258.658);
    cout << endl;

    /*for(int i = 0; i<16; i++) {
        for(int j = 0; j<16; j++) {
            colored_cout(i, j, i*16+j);
            colored_cout(i, j, " Hello world\n");
        }
    }*/

    cin.get();
    return 0;
}

void set_text_color(int background_color, int foreground_color)
{
        NOVA_FARBA;
}
void colored_cout(int background_color, int foreground_color, const char* text)
{
        NOVA_FARBA;//nová barva
        cout << text;
        ZELENA_FARBA;//nastavení původní (základní) barvy
}
void colored_cout(int background_color, int foreground_color, bool value)
{
        NOVA_FARBA;//nová barva
        cout << value;
        ZELENA_FARBA;//původní barva
}
void colored_cout(int background_color, int foreground_color, short number)
{
        NOVA_FARBA;//nová barva
        cout << number;
        ZELENA_FARBA;//původní barva
}
void colored_cout(int background_color, int foreground_color, int number)
{
        NOVA_FARBA;//nová barva
        cout << number;
        ZELENA_FARBA;//původní barva
}
void colored_cout(int background_color, int foreground_color, float number)
{
        NOVA_FARBA;//nová barva
        cout << number;
        ZELENA_FARBA;//původní barva
}
void colored_cout(int background_color, int foreground_color, double number)
{
        NOVA_FARBA;//nová barva
        cout << number;
        ZELENA_FARBA;//původní barva
}

Chcem sa ale spýtať.
Je vhodné používať také makrá aké som použil?

Editováno 11.3.2015 14:15
Odpovědět 11.3.2015 14:13
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
nf fn
Člen
Avatar
nf fn:

Myslím že v C++ se dají makra ve většině případů obejít a neměla by se používat.

 
Odpovědět 14. července 12:10
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 4 zpráv z 4.