# [C++] Ansi-Escape Sequenzen in Visual.net oder VC 6.0



## nomike (21. Oktober 2002)

Hi!
Vielleicht kennen manche von euch den ICQ Client YSM. (http://ysmv7.sourceforge.net/).
Der funktioniert sowohl im Linux als auch im Windows auf der console und hat ein command-line-interface.

Ich hab mir jetzt mal die tvision library besorgt und versuch mich gerade ein wenig darin einzuarbeiten.

Mein Ziel ist die erschaffung einer GUI für das YSM.
Dazu möchte ich das YSM von meiner GUI aus starten und dann über PIPES mit dem YSM kommunizieren.

Mein Problem ist jetzt folgendes:

Im win32 Benutzt der Programmiere folgende Funktion zur Ausgabe von Text:


```
int
PRINTF(int verbose_level, char *fmt,...)
{
	static HANDLE handle;
	int written;
	char ibuf[4096], *p, *q;
	va_list argptr;

	if ( verbose_level > YSM_SETTING_VERBOSE ) 
			return -1;

	if (!handle)
		handle = GetStdHandle(STD_OUTPUT_HANDLE);

	va_start(argptr, fmt);
	vsprintf(ibuf, fmt, argptr);
	va_end(argptr);

	p = ibuf;
	while ((q = strchr(p, 0x1b)) != NULL) {
		WriteConsole(handle, p, q-p, &written, 0);
		p = q;
		while (*p && *p != ';')
			p++;
		if (*p) {
			short color;
			p++;
			color = atoi(p);
			while (*p && *p != 'm')
				p++;
			if (*p)
				p++;

			switch (color) {
			case 30:
				color = 0;
				break;
			case 31:
				color = FOREGROUND_RED | FOREGROUND_INTENSITY;
				break;
			case 32:
				color = FOREGROUND_GREEN;
				break;
			case 33:
				color = FOREGROUND_RED | FOREGROUND_GREEN;
				break;
			case 34:
				color = FOREGROUND_RED | FOREGROUND_GREEN;
				break;
			case 35:
				color = FOREGROUND_RED | FOREGROUND_BLUE;
				break;
			case 36:
				color = FOREGROUND_GREEN | FOREGROUND_BLUE |
				    FOREGROUND_INTENSITY;
				break;
			case 37:
			default:
				color = FOREGROUND_RED | FOREGROUND_GREEN |
				    FOREGROUND_BLUE | FOREGROUND_INTENSITY;
				break;
			}
			SetConsoleTextAttribute(handle, color);
		}
	}

	if (*p)
		WriteConsole(handle, p, strlen(p), &written, 0);

	return 0;
}
```

Hierbei wird die Funktion im Programm aufgerufen und dann werden die Escape-Sequenzen herausgefiltert und mit VisualC++ Funktionen so umgesetzt, daß auch ohne EscapeSequenzen eine vernünftige Farbdarstellung erfolgt.

Ich habe mal zum Testen versucht einfech mit nem printf escape-sequenzen auszugeben. Diese werden dann aber nur als Steuerzeichen am Bildschirm ausgegeben ==> Visual C oder Windows ist halt zu blöd dafür.

Soweit so gut, aber wenn ich jetzt die Console-Funktionen (WriteConsole,...) benutze, dann wird der Text zwar in die console geschrieben aber nicht auf stdout.
Ich kann also mit meiner PIPE baden gehen.

Wie krieg ich das jetzt so hin, daß ich die Applikation über ne Pipe benutzen kann (testen kann man das ja mit "ysm > test.txt" obs funktioniert) und das Programm trotzdem auf der command line starten kann und der gesamte Ouput samt allen Farben so wie jetzt erscheint?!?

Sollte hierbei jetzt ne lösung rauskommen, werde ich sie dem Autor vorschlagen und hoffen, daß er sie ins nächste release einbaut...

Ich danke euch schon mal im Vorraus für eure Hilfe!

mfg
Nomike aka Michael Postmann


----------



## goela (22. Oktober 2002)

Escapesequenzen funktionieren anscheinend nur auf Systemen mit dem Betriebssystem Windows 9x ( auch bei kombinierten Betriebssystemen, wie zum Beispiel Windows XP funktionieren sie nicht ). Zudem muss man einen Treiber geladen ( ansi.sys ) haben. Dies geschieht indem man folgende Zeile in die Datei config.sys einfügt:
DEVICE=C:\Windows\Command\ansi.sys

Natürlich muss man diesen Pfad durch den jeweiligen Windows-Pfad ersetzen .

Danach kann man folgende Funktionen benutzen um die Bildschirm-Steuersequenzen benutzen zu können:


```
// Zum Setzen des Cursors an eine bestimmte Position:
void gotoxy ( const unsigned short int Zeile , const unsigned short int Spalte )
{
    std::cerr << "\033[" << Zeile << ';' << Spalte << 'f';
}

// Zum Wechseln der Vor- und Hintergrundfarbe
void color ( const unsigned short int vFarbe , const unsigned short int hFarbe )
{
    if ( vFarbe > 7 || hFarbe > 7 )
    {
        std::cerr << "Ungültige Farbangabe";
    }

    std::cerr << "\033[3" << vFarbe << ";4" << hFarbe << "m";
}
```

Für C-Programmierer dürft die Übersetzung keine großen Probleme bereiten, also std::cerr durch printf() ersetzen und den Code einfügen, hier ein Beispiel für clrscr():


```
// C-Version von clrscr()
#include <stdio.h>

void clrscr ()
{
    printf ( "\033[2J" );
}
```

Man beachte das diese Funkionen kein ISO-Standard sind, sie sind zwar vom ANSI-Komitee standardisiert worden, das bedeutet aber nicht das sie deswegen zum Standard der Programmiersprachen C bzw. C++ gehören.


----------



## nomike (22. Oktober 2002)

Ganz kann ich dir da jetzt nicht zustimmen!

In deinem C-Example ist nämlich ein kleiner Fehler drinnen.
Wenn des wirklich so wie des C++-Teil aussehen soll, dann mußt du


```
fprintf (stderr, "\033[2J" );
```

schreiben, wobei ich jedoch meine daß stderr hier nicht viel Sinn macht.

Also liegt der Fehler eigentlich im C++ Example wo es heißen müßte:


```
cout <<
```

Aber das nur am Rande!

Mein Eigentliches Problem ist damit nämlich noch nicht gelöst...
Das ganze soll nämlich sowohl in Win9x als auch in WinMe, Win2K, WinNT, WinXP und auch Linux laufen, wobei letzteres bereits funktioniert...

Kann ich nicht irgendwie anders die Textfarbe setzen?
Des muß doch auch ohne diese blöden deppaten console-Befehle gehen...Dann krieg ich des auf stdout auch noch drauf...

mfg
Nomike


----------



## goela (22. Oktober 2002)

So geht's auch!!!


```
// ConsoleColor.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdlib.h>
#include <malloc.h>
#include "windows.h"

void DrawColorString(char *szText, int X, int Y, WORD color)
{
    COORD screenPos={X, Y};
    WORD *colorBuf=NULL;
    DWORD dwResult=0;
    HANDLE OutputH;
    int length=0;
    int i=0; 

    OutputH = GetStdHandle(STD_OUTPUT_HANDLE); 
    length = strlen(szText);
    colorBuf = (WORD*)malloc(sizeof(WORD) * length); 

    for (i=0; i < length; i++)
    {
        colorBuf[i] = color;
    } 

    WriteConsoleOutputAttribute(OutputH, colorBuf, length, screenPos, &dwResult); 
    WriteConsoleOutputCharacter(OutputH, szText, length, screenPos, &dwResult); 

    free(colorBuf); colorBuf = NULL; 

}

int main(int argc, char* argv[])
{
    DrawColorString("Cool", 40, 4, BACKGROUND_RED);
    DrawColorString("!!!!!",40, 5, BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
    DrawColorString("But... Color in c++?", 40, 6, BACKGROUND_BLUE);
    DrawColorString("Yes, Color Text!", 40, 8, FOREGROUND_RED | BACKGROUND_GREEN);

    getchar();
    return 0;
}
```


----------



## nomike (22. Oktober 2002)

Des funktioniert super...
Aeber nur solange ich es vom Windows aus starte...
wenn ich es direkt in einer DOS-Box aufrufe sehe ich gar nix...

mfg
Nomike

PS: Im borlandC gabs mal ein textbackground und ein textcolor...
gibts des nimma?!?


----------



## goela (22. Oktober 2002)

> Im borlandC gabs mal ein textbackground und ein textcolor...



Wenn Du BorlandC hast, wahrscheinlich schon noch!


----------



## nomike (22. Oktober 2002)

ich meinte halt nur daß ich diese funktionen irgendwie im Visual C++ vermisse...

Es muß doch irgendwie gehen ein Programm in einer Console im Windows zu starten, des

1) Sowohl in Win95 als auch im NT (und alles was ähnlich is) läuft
2) Text mit Farben ausgibt
3) der sich mit "progname > test.txt" in eine Datei umleiten lässt.

Microsoft kann doch nicht so blöd gewesen sein, daß des nimmer ginge...

mfg
Nomike


----------

