?
Hya!
Das unten stehende Programm demonstriert ein animiertes Fenster innerhalb
des Standard-Konsolenfensters.
Zur Vereinfachung und Demozwecken wurde die Abfrage der Mausposition weggelassen.
Bei einem 'richtigen' Fenster würde man die Mauskoordinaten abfragen und
entsprechend das Fenster zeichnen.
In dieser Demo wird das Fenster in der main-Funktion in einer
for-Schleife verschoben.
Happy coding,
B.B.
#include <stdio.h>
#include <windows.h> // Die Console Functions werden gebraucht.
// Fensterecken
#define LO 201
#define RO 187
#define RU 188
#define LU 200
// Waagerechte und senkrechte Fensterbegrenzung
#define SR 186
#define WR 205
// Close Button
#define CLOSE 'x'
// Konsolenhandle
HANDLE hOut;
// Die Breite und die Höhe der Konsole in Buchstabenzellen.
enum { ConsoleX = 80, ConsoleY = 25 };
// Konsolenpuffer
CHAR_INFO ciConsole [ ConsoleX * ConsoleY ];
// Fensterbreite, Fensterhöhe des animierten Fensters.
enum { width = 20, height = 10 };
// Fensterpuffer, bzw. -inhalt des animierten Fensters.
CHAR_INFO ciWindow [ width * height ];
// Sichert und restauriert einen Ausschnitt aus dem Konsolenpuffer ciCosole :)
CHAR_INFO ciConsoleRestore [ width * height ];
// Setzt den Konsolencursor an die Position x, y.
int GotoXY ( int x, int y )
{
COORD pos;
pos.X = x;
pos.Y = y;
if ( ! SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), pos ))
return Err( "Failed on SetConsoleCursorPosition." );
return 0;
}
// Konsolencursor verstecken.
int CursorHide ()
{
CONSOLE_CURSOR_INFO cci = {0};
if ( FALSE == GetConsoleCursorInfo ( hOut, &cci ))
return 1;
cci.bVisible = FALSE;
if ( FALSE == SetConsoleCursorInfo ( hOut, &cci ))
return 1;
return 0;
}
// Fehlermeldungen
int Err ( char* e )
{
CursorHide();
system( "CLS" );
while( !_kbhit() )
{
Sleep ( 400 );
GotoXY ( 0, 0 );
SetConsoleTextAttribute( hOut, FOREGROUND_RED );
printf( "%s\n%s", e, "Zum Beenden Taste druecken." );
Sleep ( 400 );
GotoXY ( 0, 0 );
SetConsoleTextAttribute( hOut, FOREGROUND_BLUE|FOREGROUND_GREEN
|FOREGROUND_RED|FOREGROUND_INTENSITY );
printf( "%s\n%s", e, "Zum Beenden Taste druecken." );
}
return 1;
}
// Initialisiert das Fenster und setzt Schrift- und Hintergrundfarbe.
void InitWindow ( WORD BColor, WORD FColor )
{
int x, y;
// Fensterecken und 'Close Button'
ciWindow[0].Char.AsciiChar = LO; // Ecke links oben;
ciWindow[width-2].Char.AsciiChar = CLOSE; // 'Close Button'
ciWindow[width-1].Char.AsciiChar = RO; // Ecke rechts oben;
ciWindow[width*height-1].Char.AsciiChar = RU; // Ecke rechts unten
ciWindow[width*(height-1)].Char.AsciiChar = LU; // Ecke links unten
// Hintergrundfarbe, Schriftfarbe
for ( y = 0; y < height; y++ )
for ( x = 0; x < width; x++ )
ciWindow[width*y+x].Attributes = BColor | FColor;
// Waagerechte Fensterbegrenzung oben
for ( x = 1; x < width -2; x++ )
ciWindow[x].Char.AsciiChar = WR;
// Waagerechte Fensterbegrenzung unten
for ( x = 1; x < width -1; x++ )
ciWindow[width*(height-1)+x].Char.AsciiChar = WR;
// Senkrechte Fensterbegrenzungen rechts und links
for ( y = 1; y < height-1; y++ )
{
ciWindow[width*y].Char.AsciiChar = SR;
ciWindow[width*y+width-1].Char.AsciiChar = SR;
}
}
// Konsolencursor maximieren.
int CursorMaximize()
{
CONSOLE_CURSOR_INFO cci = {0};
if ( FALSE == GetConsoleCursorInfo ( hOut, &cci ))
return 1;
cci.dwSize = 99;
if ( FALSE == SetConsoleCursorInfo ( hOut, &cci ))
return 1;
return 0;
}
// Konsolencursor anzeigen
int CursorShow ()
{
CONSOLE_CURSOR_INFO cci = {0};
if ( FALSE == GetConsoleCursorInfo ( hOut, &cci ))
return 1;
cci.bVisible = TRUE;
if ( FALSE == SetConsoleCursorInfo ( hOut, &cci ))
return 1;
return 0;
}
// Legt die Größe des Konsolenpuffers und die Größe des Konsolenfensters fest.
int SetConsoleDimension( short x, short y )
{
int xmin, ymin, xmax, ymax;
SMALL_RECT sr = {0,0,x-1,y-1};
COORD screenBufSize = {x,y};
if ( FALSE == ( SetConsoleScreenBufferSize( hOut, screenBufSize )) )
return Err( "Failed on SetConsoleScreenBufferSize." );
if ( FALSE == SetConsoleWindowInfo( hOut, TRUE, &sr ) )
return Err( "Failed on SetConsoleWindowInfo." );
return 0;
}
// Zeigt die Member der CONSOLE_SCREEN_BUFFER_INFO an.
int PrintConsoleScreenBufferInfo()
{
// Konsole Infos :)
CONSOLE_SCREEN_BUFFER_INFO CSBI;
COORD LargestConsoleWindowSize = {0};
COORD xy = { 0, ConsoleY-1 };
DWORD dummy;
if ( FALSE == GetConsoleScreenBufferInfo( hOut, &CSBI ))
return 1;
puts ( "Here is your console screen buffer information:\n" );
printf ( "Size x: %d\n", CSBI.dwSize.X );
printf ( "Size y: %d\n" , CSBI.dwSize.Y );
printf ( "Cursor position x: %d\n", CSBI.dwCursorPosition.X );
printf ( "Cursor position y: %d\n", CSBI.dwCursorPosition.Y );
printf ( "Attributes: %d\n", CSBI.wAttributes );
printf ( "Window position x-left: %d\n", CSBI.srWindow.Left );
printf ( "Window position x-top: %d\n", CSBI.srWindow.Top );
printf ( "Window position x-right: %d\n", CSBI.srWindow.Right );
printf ( "Window position x-bottom: %d\n", CSBI.srWindow.Bottom );
printf ( "Window size max x: %d\n", CSBI.dwMaximumWindowSize.X );
printf ( "Window size max y: %d\n", CSBI.dwMaximumWindowSize.Y );
// Größt mögliche Fenstergröße ( in Buchstabenzellen )
LargestConsoleWindowSize = GetLargestConsoleWindowSize( hOut );
if ( LargestConsoleWindowSize.X && LargestConsoleWindowSize.Y )
{
printf ( "Largest size x: %d\n", LargestConsoleWindowSize.X );
printf ( "Largest size y: %d\n", LargestConsoleWindowSize.Y );
}
FillConsoleOutputCharacter( hOut, 1, ConsoleX, xy, &dummy );
return 0;
}
// Kopiert den Inhalt der Konsole in den Puffer ciConsole.
int CopyConsoleContent()
{
COORD dwBufferSize = { ConsoleX, ConsoleY };
COORD dwBufferCoord = { 0, 0 };
SMALL_RECT ReadRegion = { 0, 0, ConsoleX-1, ConsoleY-1 };
if ( FALSE == ReadConsoleOutput( hOut, ciConsole, dwBufferSize,
dwBufferCoord, &ReadRegion ))
return Err ("ReadConsoleOutput failed.");
return 0;
}
// Liest aus dem Puffer ciConsole ab Position x, y einen rechteckigen Block
// der Höhe height und der Breite width und speichert diesen im Puffer
// ciConsoleRestore
int FillRestoreBuffer( int x, int y )
{
COORD dwBufferSize = { width, height };
COORD dwBufferCoord = { 0, 0 };
SMALL_RECT ReadRegion = { x, y, x+width-1, y+height-1 };
if ( FALSE == ReadConsoleOutput( hOut, ciConsoleRestore, dwBufferSize,
dwBufferCoord, &ReadRegion ))
return Err ("ReadConsoleOutput failed.");
return 0;
}
// Zeichnet den Inhalt von pci in die Konsole an der Position x, y.
// pci ist abwechselnd das animierte Fenster ciWindow
// und der gesicherte Ausschnitt des Konsolenpuffers ciConsoleRestore
int DrawWindow ( int x, int y, CHAR_INFO* pci )
{
COORD dwBufferSize;
COORD dwBufferCoord = { 0, 0 };
SMALL_RECT WriteRegion;
dwBufferSize.X = width;
dwBufferSize.Y = height;
WriteRegion.Left = x;
WriteRegion.Top = y;
if ( (width + x) > (ConsoleX -1) )
WriteRegion.Right = ConsoleX -1;
else
WriteRegion.Right = width + x;
if ( (height + y) > (ConsoleY -1) )
WriteRegion.Bottom = ConsoleY -1;
else
WriteRegion.Bottom = height + y;
if ( FALSE == WriteConsoleOutput ( hOut, pci, dwBufferSize,
dwBufferCoord, &WriteRegion ))
return Err ( "WriteConsoleOutput failed." );
return 0;
}
// Demo animiertes Fenster :)
int main( void )
{
int x, y, speed = 500;
SetConsoleTitle( "Big Brothers Animated Console Window" );
// Konsolen Output Handle holen.
if ( ( hOut = GetStdHandle( STD_OUTPUT_HANDLE ) ) == INVALID_HANDLE_VALUE )
return Err( "GetStdHandle failed." );
// Konsolencursor verstecken.
if ( CursorHide () )
return Err( "HideCursor failed." );
// Breite und Höhe der Konsole festlegen.
if ( SetConsoleDimension( ConsoleX, ConsoleY ) )
return Err( "SetConsoleDimension failed." );
// Konsoleninfos anzeigen.
if ( PrintConsoleScreenBufferInfo () )
return Err( "PrintConsoleScreenBufferInfo failed." );
// Den Inhalt der Konsole in den Puffer ciConsole kopieren.
if ( CopyConsoleContent () )
return Err( "CopyConsoleContent failed." );
// Das 'Animationsfenster' initialisieren. Das Aussehen des Fenster wird
// im Puffer ciWindow festgelegt.
InitWindow ( BACKGROUND_BLUE, // Blauer Hintergrund, weiße Schrift
FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY );
// Hier wird das Fenster verschoben und gezeichnet.
for ( x = 0, y = 0; y < ConsoleY; x++, y++ )
{
if ( FillRestoreBuffer ( x, y ) )
return Err( "FillRestoreBuffer failed." );
if ( DrawWindow ( x, y, ciWindow ) )
return Err( "DrawWindow failed." );
Sleep ( speed );
if ( DrawWindow ( x, y, ciConsoleRestore ) )
return Err( "DrawWindow failed." );
if ( y == ConsoleY-1 )
y = 0;
if ( x == ConsoleX-1 )
x = 0;
}
getchar();
return 0;
}