Chiarimento sull'uso degli ESCAPE CODES

di il
15 risposte

Chiarimento sull'uso degli ESCAPE CODES

Ciao Ragazzi, sono un nuovo coder attempato alle prime armi

Prima di tutto saluto tutta la comunità e vi auguro una buona giornata.

Adesso vengo al dunque e mi scuso per la lungaggine

Mi sto cimentando da poco con il C++, ho comprato alcuni libri che sto leggendo assiduamente e facendo un po di
esercizi e test vari, mi sono reso conto di alcune limitazioni nel visualizzare dei valori a video, praticamente non
riuscivo a ritornare sulle righe precedenti per poter visualizzare un valore in un determinato punto nella finestra terminale, tipo in alto a destra o al centro dello schermo per fare un esempio.

Cosi mi sono armato di google e bing e ho scoperto un piccolo mondo :

i VT100 ESCAPE CODES

grazie ad essi ho risolto il problema di poter visualizzare una stringa ovunque nella finestra del terminale e moltissime altre cose,
come il cambio colore, sfondo, formattazione del testo e cosi via.

ma ieri per un puro caso mi sono reso conto che tutto il lavoro che ho fatto in un piccolo programmino di prova, ricopiato in un altro, non funzionava piu.

Andando ad esclusione ho scoperto che se non uso il comando :

system ("cls");

prima degli escape codes, questi ultimi non funzionano.

Adesso, per reperire le informazioni sugli escape codes ho fatto riferimento a diversi siti, alcuni riguardavano C altri ADA, poi con varie prove sono riuscito ad utilizzarli sul C++, ma su nessuno di questi siti ho trovato informazioni riguardanti l'utilizzo del comando CLS prima dei codici ESCAPE.

Ora la mia domanda e' la seguente, qualcuno di voi ha qualche sito o qualche informazione su questa cosa ?

Il comando CLS sicuramente cancella lo schermo e riporta il cursore in alto a destra nella finestra del terminale.
Ma quasi sicuramente in questo caso attiva qualche altra cosa, non so una modalità particolare o effettua un reset su
qualche altro parametro.

In parole povere mi piacerebbe saperne di piu', magari con il vostro aiuto riesco a togliermi questa pulce dall'orecchio.

Vi ringrazio e vi auguro una buona giornata.

P.S.

questo e' il piccolo codice che sto usando per fare dei test :


#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include <windows.h>


int main()
{
        system("cls");          // SE ELIMINO QUESTA RIGA I CODICI ESCAPE NON FUNZIONANO :(

        printf ("\033[15;50H"); // Coordinate riga-colonna della finestra terminale.
        printf ("\033[2K");     // Cancellazione della sola riga corrente.
        printf ("\033[94m");    // Colore carattere blu chiaro.

        cout << "TEST VT100 ESCAPE CODES";

        Sleep(3000);            // Attesa di 3 secondi

        printf ("\033[0m");     // Reset dei valori colori allo stato originale.

    return (0);
}

15 Risposte

  • Re: Chiarimento sull'uso degli ESCAPE CODES

    C'è scritto nella documentazione perché
    https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
    
    bool EnableVTMode()
    {
        // Set output mode to handle virtual terminal sequences
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        if (hOut == INVALID_HANDLE_VALUE)
        {
            return false;
        }
    
        DWORD dwMode = 0;
        if (!GetConsoleMode(hOut, &dwMode))
        {
            return false;
        }
    
        dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
        if (!SetConsoleMode(hOut, dwMode))
        {
            return false;
        }
        return true;
    }
    
    int main()
    {
        //system("cls");            // SE ELIMINO QUESTA RIGA I CODICI ESCAPE NON FUNZIONANO :(
        EnableVTMode(); 		// chiamato implicitamente da cls o in modalita' debug
    
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    Ciao Weierstrass,

    Grazie per il link, purtroppo queste informazioni non sono alla mia portata, anche dopo aver letto l'articolo, non riesco a capire
    come funziona il tutto.

    Gli esempi sono in c e non in c++ e CodeBlocks non lo digerisce e non sono riuscito a modificare il listato in modo da adattarlo al c++.

    Nell'articolo suggerisce di usare GetConsoleMode e SetConsoleMode ma non ho capito come.

    e comunque non ho trovato un riferimento preciso sul comando CLS, anche se ho capito da quello che hai scritto che richiamando il comando, viene effettuata una chiamata, anche se non ho capito di preciso a che cosa, che abilita la modalità terminale vt100.
    Queste mie incomprensioni sono dovute con molta probabilità alla mia inesperienza, anzi certamente.

    Se tu o qualche altra persona avreste degli esempi un po più alla mia portata, beh!! sarebbero molto graditi.
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    L'esempio di GetConsoleMode() e SetConsoleMode() te l'ho scritto prima. Ti riscrivo il programma completo con Visual Studio in C++ allora
    
    #include <iostream>
    #include <windows.h>
    
    bool EnableVTMode()
    {
        // Set output mode to handle virtual terminal sequences
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        if (hOut == INVALID_HANDLE_VALUE)
        {
            return false;
        }
    
        DWORD dwMode = 0;
        if (!GetConsoleMode(hOut, &dwMode))
        {
            return false;
        }
    
        dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
        if (!SetConsoleMode(hOut, dwMode))
        {
            return false;
        }
        return true;
    }
    
    int main()
    {
        //system("cls");          // SE ELIMINO QUESTA RIGA I CODICI ESCAPE NON FUNZIONANO :(
        EnableVTMode(); // chiamato implicitamente da cls o in modalita' debug
    
        printf("\033[15;50H"); // Coordinate riga-colonna della finestra terminale.
        printf("\033[2K");     // Cancellazione della sola riga corrente.
        printf("\033[94m");    // Colore carattere blu chiaro.
    
        std::cout << "TEST VT100 ESCAPE CODES";
    
        Sleep(3000);            // Attesa di 3 secondi
    
        printf("\033[0m");     // Reset dei valori colori allo stato originale.
    
        return (0);
    }
    
    Essendo un programma in Windows che usa il terminale di Windows, mi sembra che la soluzione più sensata sia usare Visual Studio.

    Se vuoi usare Code::Blocks, comunque, la soluzione più pulita l'hai già trovata con system("cls"); cls tra le varie operazioni fa anche quanto indicato EnableVTMode().

    Onestamente non so come si integrino le API di Windows fuori da Visual Studio e il codice mi sembra già minimale, potresti giusto semplificare così
    
    void EnableVTMode()
    {
        // Set output mode to handle virtual terminal sequences
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        DWORD dwMode = 0;
        GetConsoleMode(hOut, &dwMode);
        SetConsoleMode(hOut, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
    }
    
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    Grazie Weierstrass,

    ti stai prendendo tanto disturbo e ti ringrazio,

    con il tuo codice ho il seguente errore, che poi e' lo stesso che ho con il codice originale, sulla seguente linea :

    dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;

    L'errore e' il seguente :

    error: 'ENABLE_VIRTUAL_TERMINAL_PROCESSING' was not declared in this scope|

    ||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 2 second(s)) ===|
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    Prova così
    
    #define MY_ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
    
    void EnableVTMode()
    {
        // Set output mode to handle virtual terminal sequences
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        DWORD dwMode = 0;
        GetConsoleMode(hOut, &dwMode);
        SetConsoleMode(hOut, dwMode | MY_ENABLE_VIRTUAL_TERMINAL_PROCESSING);
    }
    
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    SI adesso funziona perfettamente

    Una curiosita come mai hai usato :

    #define MY_ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004

    e poi riportato la variabile qui in SetConsoleMode :

    SetConsoleMode(hOut, dwMode | MY_ENABLE_VIRTUAL_TERMINAL_PROCESSING);

    invece di scrivere il tutto cosi ?

    SetConsoleMode(hOut, dwMode | 0x0004);


    Adesso comincio a capire dove vanno inseriti una serie di parametri.
    ma ancora altri non mi sono chiari, tipo :

    HANDLE e DWORD
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    P.S.

    domanda un po stupida, io al momento uso Code::Blocks, solo perche ho iniziato con questo e mi sto trovando decentemente,

    Tu mi consigli di passare a Visual Studio ?

    domanda da ignorante Visual Studio e' a pagamento ?
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    TonyF ha scritto:


    SI adesso funziona perfettamente

    Una curiosita come mai hai usato :

    #define MY_ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004

    e poi riportato la variabile qui in SetConsoleMode :

    SetConsoleMode(hOut, dwMode | MY_ENABLE_VIRTUAL_TERMINAL_PROCESSING);

    invece di scrivere il tutto cosi ?

    SetConsoleMode(hOut, dwMode | 0x0004);
    Va bene scrivere | 0x0004. Non penso che cambierà mai quella #define
    Semplicemente avevo fatto copia e incolla di quella definizione dall'header dove si trovava in Visual Studio e ho aggiunto MY_ per differenziarla.
    Quindi, semplicemente, in Code::Blocks mancava una definizione - un problema classico dei progetti open source
    Adesso comincio a capire dove vanno inseriti una serie di parametri.
    ma ancora altri non mi sono chiari, tipo :

    HANDLE e DWORD
    Sempre da Visual Studio
    
    typedef void *HANDLE;
    
    typedef unsigned long DWORD;
    
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    TonyF ha scritto:


    P.S.

    domanda un po stupida, io al momento uso Code::Blocks, solo perche ho iniziato con questo e mi sto trovando decentemente,

    Tu mi consigli di passare a Visual Studio ?

    domanda da ignorante Visual Studio e' a pagamento ?
    Se devi fare cose strettamente collegate a Windows è meglio Visual Studio, altrimenti va bene qualsiasi cosa. La versione Community è gratuita
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    Weierstrass" post_id="8679671" time="1633612874 ha scritto:


    Se devi fare cose strettamente collegate a Windows è meglio Visual Studio, altrimenti va bene qualsiasi cosa. La versione Community è gratuita
    Al momento sto lavorando solo con windows, a questo punto visto che e' gratuito installerò anche Visual Studio insieme a Code::Blocks, vediamo se riesco a fare il tutto per questo fine settimana.

    Ma prima mi toccherà rismontare il mio vetusto laptop e ricambiare la pasta termica e dare una pulita alla ventola, al momento di riscalda un po troppo e ogni tanto va in freez, ma questa e' un'altra storia
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    [/quote]

    Sempre da Visual Studio
    
    typedef void *HANDLE;
    
    typedef unsigned long DWORD;
    
    [/quote]

    Sapevo che una DWORD e' un valore a 32 bit, ma non sapevo che le API di windows da tempo immemore le usano come valore standard a 32 bit, praticamente dall'avvento delle cpu a 32 bit se non ho capito male.

    Ricapitolando ho capito che, una DWORD e' una variabile a 32 bit e che se un parametro richiede una DWORD e' meglio usare quella.

    Ma con HANDLE ci sto sbattendo il muso,

    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    ( questo parametro GetStdHandle(STD_OUTPUT_HANDLE) che va a leggere un qualche valore che rappresenta uno standard output, può essere sostituito con qualche altro parametro ? ma soprattutto che setta di preciso ? )

    DWORD dwMode = 0; ( Variabile 32 bit settata a 0 e qui ci siamo, spero...)

    Ora prendiamo queste due linee, che poi sono le sole che in teoria dovrei usare con i parametri giusti :

    GetConsoleMode(hOut, &dwMode);
    SetConsoleMode(hOut, dwMode | 0x0004);


    Andando al link che mi hai dato in precedenza, la sintassi che riporta per SetConsoleMode per esempio e' la seguente :

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

    Ora in teoria ci sono un sacco di parametri esadecimali che si possono usare sia per hConsoleHandle che per dwMode, ma nessuno funziona, tranne quello che ho messo per sostituire la variabile :

    #define MY_ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004

    con appunto 0x0004 in SetConsoleMode, perche ?


    Mi sa tanto che questa notte non dormiro, sono sicuro
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    HANDLE è un puntatore a void: puoi studiare direttamente come funzionano i puntatori a void, tanto sono uguali in ogni sistema operativo. Nelle API hanno definito HANDLE e DWORD (double word) perché non si sa mai che un giorno debbano cambiare (non succederà)

    GetStdHandle() è documentato qui
    https://docs.microsoft.com/en-us/windows/console/getstdhandle

    Per le altre flag di SetConsoleMode(), sono opzioni particolari che si usano solo in contesti molto speciali
    
    #include <iostream>
    #include <windows.h>
    
    void DisableEscCrLfBackspaceTab()
    {
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
        DWORD dwMode = 0;
        GetConsoleMode(hOut, &dwMode);
        dwMode &=~ ENABLE_PROCESSED_OUTPUT;
        SetConsoleMode(hOut, dwMode);
    }
    
    int main()
    {
        std::cout << "Ciao\n\nCiao\n\n";
        DisableEscCrLfBackspaceTab();
        std::cout << "Ciao\n\nCiao\n\n";
        Sleep(3000);            // Attesa di 3 secondi
        return (0);
    }
    
    Non so se ne valga davvero la pena approfondire.
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    Grazie per le tue ulteriori informazioni,

    effettivamente hai ragione ci sto perdendo troppo tempo, andrò avanti con i miei libri e riprenderò l'argomento più avanti,
    quando sarò più preparato e riuscirò a muovermi meglio nei meandri di Windows.

    Comunque ho imparato un po di cose grazie al tuo aiuto e per questo ti ringrazio.

    Ti auguro una buona serata, ciao
  • Re: Chiarimento sull'uso degli ESCAPE CODES

    @TonyF
    domanda di rito: PERCHE' stai studiando C++?
    Nel senso: C++ e' un linguaggio MOOOLTO COMPLESSO.
    Se lo devi fare per lavoro/necessita',ok

    MA

    se lo stai facendo per hobby, ci sono linguagi DECIAMENTE piu' abordabili, che ti permettono di fare UN MILIONE di cose in piu'.
    NON SONO piu' potenti di C++, MA sopperiscono con un'infinita' di librerie esterne gia' pronte per fare il milione di cose di cui sopra.

    Ad esempio, Python.

    Il second punto e': SE vuoi continuare con C++, evita di ""impegolarti"" con altri argomenti, quali il sistema operativo e la sua gestione a finestre (che e' un incubo). Concentrati su argomenti ""piu' semplici"", ma non per qesto meno ""complessi"", come lo studio di ""algoritmi e strutture dati"", i mattoni ""fondamentali"" per poter programmare.

    Il linguaggio di programmazione NON E' la programmazione (srivere programmi), cosi' come l'italiano NON E' scrivere racconti di fantascienza. E' SOLO UNO STRUMENTO, cosi' come la forchetta per gli spaghetti!
Devi accedere o registrarti per scrivere nel forum
15 risposte