Forum: PC-Programmierung Ausgabe eines blinkenden Pfeils im geschlossenen Rahmen


von Bartosz B. (bartosz)


Lesenswert?

Guten Abend, ich habe eine Frage und hoffe, dass ihr mir helfen könnt:

Ich möchte einen Rahmen erstellen und in der unteren, rechten Ecke einen 
Pfeil, der nach unten zeigt, printen. Dieser soll solange (≈2x pro 
Sekunde) blinken, bis der Benutzer Enter drückt. Der bisherige C++ Code 
sieht so aus:
[code]
#include "Windows.h"
#include <iostream>
using namespace std;

void DrawRectangle(int posX, int posY, int width, int height, char 
drawChar, char emptyChar)
{
  string first_Row(width, '\xCD');  //String mit 79 Zeichen anlegen, 
füllen mit dem Zeichen
  first_Row[0] = '\xC9';
  first_Row[width - 1] = '\xBB';
  string last_Row(width, '\xCD');
  last_Row[0] = '\xC8';
  last_Row[width - 1] = '\xBC';
  string posYString(posY, emptyChar);      //String mit (hier bspw. 0) 
Zeichen anlegen, füllen mit Leerzeichen
  string vorletzte_Zeile_mit_Pfeil(width, emptyChar);
  vorletzte_Zeile_mit_Pfeil[0] = '\xBA';
  vorletzte_Zeile_mit_Pfeil[width-1] = '\xBA';
  vorletzte_Zeile_mit_Pfeil[width - 2] = '\x19';
  char einZeichen; //letztes, eingegebenes Zeichen
  einZeichen = 'a';


  for (int row = 0; row < posX; row++) //so weit wie muss nach unten
  {
    cout << endl;
  }

  cout << posYString; //so weit wie muss nach rechts

  cout << first_Row << endl; //oberer Rahmen

  for (int row = 1; row < (height - 1); row++)
  {
    string betweenRow(width, emptyChar);  //String mit 79 Zeichen 
anlegen, füllen mit Leerzeichen
    betweenRow[0] = '\xBA';        //Das erste Zeichen ist aber der 
Rand,
    betweenRow[width - 1] = '\xBA';    //das letzte Zeichen auch!
    cout << posYString;            //so weit wie muss nach rechts
    cout << betweenRow << endl;        //String ausgeben

  }
  // last row
  cout << posYString;              //so weit wie muss nach rechts
  cout << last_Row << endl;      //unterer Rahmen
}

int main(void)
{
  ShowWindow(GetConsoleWindow(), SW_MAXIMIZE);
  system("color F0");

  DrawRectangle(0, 0, 79, 20, '\xFA', ' ');

  system("pause");
  return 0;
}
[\code]

Mein Problem ist, dass ich den Rahmen unten bereits schließen will, der 
Pfeil drüber jedoch kommen muss, weg sein muss, kommen muss, weg sein 
muss, bis der Benutzer Enter eingibt. Ich habe mir überlegt, mit [c] 
printf("\r");[\c] diese vorletzte Zeile zu überschreiben, diese mit 
Pfeil ausgeben zu lassen, wieder zu löschen und ohne Pfeil auszugeben 
usw.
Ggf. mit ein wenig Wartezeit dazwischen und alle paar Aktualisierungen 
muss der Benutzer etwas eingeben. Das ist nicht optimal.

Danke im Voraus

Visual Studio Professional 2019 (V 16.3.2)
Windows 8.1

von c-hater (Gast)


Lesenswert?

Bartosz B. schrieb:

> Mein Problem ist, dass ich den Rahmen unten bereits schließen will, der
> Pfeil drüber jedoch kommen muss, weg sein muss, kommen muss, weg sein
> muss, bis der Benutzer Enter eingibt. Ich habe mir überlegt, mit [c]
> printf("\r");[\c] diese vorletzte Zeile zu überschreiben, diese mit
> Pfeil ausgeben zu lassen, wieder zu löschen und ohne Pfeil auszugeben
> usw.

Du brauchst bloß ein einziges Zeichen zu überschreiben, nämlich 
abwechselnd
Pfeil oder Leerzeichen.

Dein erstes Problem ist, dass du keine Technik kennst, die Position für 
diese Zeichenausgabe anzusteuern. Mache dich bezüglich 
ASCII-Steuerzeichen schlau. Google/Wikipedia helfen dir dabei.

Dein zweites Problem ist, dass du nur in der Lage bist, blockierend auf 
eine Benutzereingabe zu warten (was du obendrein sehr umständlich tust). 
Aber egal, sobald du diese blockierende Funktion aufgerufen hast, kannst 
du nix anderes mehr tun, bis sie zurückkehrt. Deine Aufabe ist also: 
finde eine Möglichkeit, nichtblockierend Usereingaben in das 
Konsolenfenster zu lesen. Dazu musst du unter Windows natürlich das 
WinAPI benutzen. Das bietet für Konsolenfenster einige Funktionen, die 
über die stupide Logik der IO-Streams nicht verfügbar sind. Was du hier 
brauchst, ist die Funktion PeekConsoleInput (und ggf. ReadConsoleInput).

von Bernd K. (prof7bit)


Lesenswert?

Gibts da nicht ein Blink-Bit das man setzen kann oder eine entsprechende 
ANSI-sequenz die das Blinken einschaltet so daß es von selbst blinkt 
oder verwechsel ich das jetzt? Und gabs nicht auch mal sowas wie ne 
ncurses Portierung für Windows oder sowas ähnliches?

Nach sowas würd ich als erstes suchen wenn man mich zwingen würde sowas 
zu machen.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Bernd K. schrieb:

> Gibts da nicht ein Blink-Bit das man setzen kann

Das war früher(tm), als man noch direkt in den Graka-Speicher schrieb. 
VGA und Vorgänger kannte zum Textbuffer auch noch einen Attributbuffer, 
in dem die Farben und halt auch ein Blink-Attribut lagen.

> oder eine entsprechende
> ANSI-sequenz die das Blinken einschaltet

Ja, dazu muss aber die Konsole auch die entsprechenden Escape-Sequenzen 
unterstützen. Die Windows-Console tut das wohl nicht. Ganz sicher bin 
ich mir da aber aber nicht.

von Bartosz B. (bartosz)


Lesenswert?

c-hater schrieb:
Was du hier
> brauchst, ist die Funktion PeekConsoleInput (und ggf. ReadConsoleInput).

Danke, das hat funktioniert!

Ich komme nur gerade nicht darauf, wie ich mit einem ASCII-Steuerzeichen 
an die richtige Position komme.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.