Resource icon

C++ Lib für Manipulationen am Windows-Consolefenster (v. 3.5)

Programmiersprache(n)
C++
Betriebssystem(e)
Windows
wincons.png

Wie das Betriebssystem sein Consolefenster handhabt, ist nicht Bestandteil des C++ Standards und somit plattformabhängig. Immer wieder trifft man deshalb auf die system() Funktion, um an eine spezifische Funktionalität der Shell zu kommen. Keine gute Idee, auch weil die system() Funktion bei jedem Aufruf den Shellprozess im Hintergrund lädt, was sicher hundertmal länger dauert, als gleich die API zu bedienen. Aus diesem Grund habe ich (mit -AB-'s Hilfe, siehe Thread1 und Thread2) ein paar windowsspezifische Funktionen in eine Lib gepackt. Ich weiß, dass insbesondere bei Sprachanfängern gern mal kleine Consolespielchen geschrieben werden, die man natürlich auch mit ein bisschen Styling versehen will, statt nur mit dem Standard-Grau-Auf-Schwarz Fenster zu arbeiten.
Natürlich ist und bleibt das Consolefenster textbasiert und man sollte nicht zu viel verlangen. Für Anregungen und Erweiterungswünsche bin ich aber offen (sofern es in meinen Möglichkeiten liegt, diese umzusetzen).

Anbei 4 Dateien, die in das jeweilige Projekt eingebunden werden. Dort wo die Klasse benötigt wird, einfach die wincons.h includieren, um Zugriff auf den Namespace winc, deren Klassen und Membervariablen und -funktionen zu bekommen.
Die Referenz auf die wincons Klasse bekommt man mittels get() Methode.
winc::wincons& myWincons = winc::wincons::get();

Membervariablen und -typen
  • winc::wincons::wDefaultCol Standardfarbe
    Zweistelliger Hexadezimaler Wert, wobei die erste Ziffer den Hintergrund und
    die zweite Ziffer die Schriftfarbe repräsentiert.
    Hex Werte:
    0 = Schwarz
    1 = Dunkelblau
    2 = Dunkelgrün
    3 = Blaugrün
    4 = Dunkelrot
    5 = Lila
    6 = Ocker
    7 = Hellgrau
    8 = Dunkelgrau
    9 = Blau
    A = Grün
    B = Zyan
    C = Rot
    D = Magenta
    E = Gelb
    F = Weiß

    Beispiel: 0xF1 für weißen Hintergrund und dunkelblaue Schrift​
  • winc::wincons::strDefaultMsg Standardmeldung für die wait() Funktion
Diese beiden Eigenschaften gelten global und werden synchronisiert.

  • winc::cell Typ repräsentiert die Koordinaten einer Character-Cell
  • winc::range Typ repräsentiert einen Bereich von Character-Cells
  • winc::rangevec_t Typ ist ein dynamischer Vector-Container für Bereiche vom Typ range

Eingebettete Klassen und ihre Memberfunktionen
- io Klasse
  • io::get() convertiert eine Benutzereingabe in einen numerischen oder string - Typ
  • io::wait() vereint das Verhalten von PAUSE und CHOICE der Windows Shell
  • io::printkeepcol() gibt einen String unter Beibehaltung der vorherigen Farbinformationen der Character-Cells aus
  • io::printfittorect() gibt einen String unter Beibehaltung der vorherigen Farbinformationen der Character-Cells in das angegebene Rechteck des Fensterpuffers aus
  • io::drawframechar() gibt ein Rahmenzeichen unter Beibehaltung der vorherigen Farbinformationen der Character-Cell aus
  • io::drawlineh() gibt eine horizontale Linie unter Beibehaltung der vorherigen Farbinformationen der Character-Cells aus
  • io::drawlinev() gibt eine vertikale Linie unter Beibehaltung der vorherigen Farbinformationen der Character-Cells aus
  • io::drawbox() gibt einen rechteckigen Rahmen unter Beibehaltung der vorherigen Farbinformationen der Character-Cells aus
  • io::getclick() ermittelt die Position eines Mausklicks in das Consolefenster
  • io::getmouseover() koloriert Bereiche des Consolefensters beim überstreichen mit dem Mauszeiger und ermittelt den Index des Bereichs bei einem Mausklick
- style Klasse
  • style::clearscreen() leert den Fensterpuffer (Farbwerte siehe oben)
  • style::clearrect() leert den Fensterpuffer im angegebenen Rechteck (Farbwerte siehe oben)
  • style::color() koloriert den gesamten Fensterpuffer (Farbwerte siehe oben)
  • style::colorrect() koloriert den Fensterpuffer im angegebenen Rechteck (Farbwerte siehe oben)
  • style::textcolor() legt die Farbe für die zukünftige Ausgabe fest (Farbwerte siehe oben)
  • style::setfont() verändert die Schriftart
  • style::setfontsize() verändert die Größe der Schrift
- cursor Klasse
  • cursor::get() ermittelt die derzeitige Position des Consolecursors
  • cursor::set() positioniert den Consolecursor
  • cursor::toggle() schaltet die Anzeige des Consolecursors ein bzw. aus
- window Klasse
  • window::title() ändert den Fenstertitel
  • window::resize() ändert die innere Fenstergröße und den Fensterpuffer auf die angegebene Größe
  • window::move() positioniert das Consolefenster auf dem Bildschirm

+++ Detailliertere Beschreibungen finden sich in den Kommentaren der wincons.h. +++

wincons.h
C++:
// wincons.h

#ifndef WINCONS_H
#define WINCONS_H

#include <string>
#include <vector>
#include <memory>

namespace winc
{
  /* winc::shade Enumeration für Schattierungen */
  enum class shades {light, medium, dark};

  /* winc::cell repräsentiert die Koordinaten einer Character-Cell */
  struct cell
  {
    short x, y;
    cell(const short x = 0, const short y = 0);
  };

  /* winc::range repräsentiert einen Bereich von Character-Cells */
  struct range
  {
    short left, top, right, bottom;
    range(const short left = 0, const short top = 0, const short right = 0, const short bottom = 0);
  };

  /* winc::rangevec_t ist ein dynamischer Container für Bereiche vom Typ range */
  typedef std::vector<range> rangevec_t;


  /* Vorwärtsdeklaration */
  class wincons;

  /* Detail Namensraum, nicht zur direkten Verwendung */
  namespace detail_wincons
  {
    /* io Klasse */
    struct io
    {
      friend class winc::wincons;

      /* io::get() convertiert eine Benutzereingabe in einen der unten angegebenen
          numerischen oder string - Typ
         Parameter sind die Referenz auf eine Variable, der der ermittelte Wert zugepiesen wird,
          sowie die maximal erlaubte Eingabelänge
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
      */
      bool get(short& rNum, const short maxlen) const;
      bool get(int& rNum, const short maxlen) const;
      bool get(long& rNum, const short maxlen) const;
      bool get(long long& rNum, const short maxlen) const;
      bool get(unsigned short& rNum, const short maxlen) const;
      bool get(unsigned int& rNum, const short maxlen) const;
      bool get(unsigned long& rNum, const short maxlen) const;
      bool get(unsigned long long& rNum, const short maxlen) const;
      bool get(float& rNum, const short maxlen) const;
      bool get(double& rNum, const short maxlen) const;
      bool get(long double& rNum, const short maxlen) const;
      bool get(std::string& rStr, const short maxlen) const;


      /* io::wait() vereint das Verhalten von PAUSE und CHOICE der Windows Shell
          Bei Rückgabe der Funktion, wird der Cursor an den Beginn der nächsten Zeile gesetzt
         mögliche Parameter sind die auszugebende Meldung und/oder das Timeout (in ms) für die Eingabe
         Rückgabewert ist entweder der ASCII Wert für die eingegebene Taste, ein eindeutiger Wert für bspw. Pfeil- und F-Tasten oder 0 bei Fehler
      */
      // Standardmeldung wird ausgegeben, es gibt kein Timeout
      int wait() const;
      // Angegebene Meldung wird ausgegeben, es gibt kein Timeout
      int wait(const std::string& rStrMessage) const;
      // Standardmeldung wird ausgegeben, es wird bis zum angegebenen Timeout auf Eingabe gewartet
      int wait(const unsigned timeout) const;
      // Angegebene Meldung wird ausgegeben, es wird bis zum angegebenen Timeout auf Eingabe gewartet
      int wait(const std::string& rStrMessage, const unsigned timeout) const;


      /* io::printkeepcol() gibt einen String unter Beibehaltung der vorherigen Farbinformationen der Character-Cells aus.
          Der Cursor wird hinter das letzte geschriebene Zeichen gesetzt.
         Parameter ist der auszugebende Textstring
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
         Zeilenumbrüche im Textstring werden nicht unterstützt.
      */
      bool printkeepcol(const std::string& rStr) const;


      /* io::printfittorect() gibt einen String unter Beibehaltung der vorherigen Farbinformationen der Character-Cells
          in das angegebene Rechteck des Fensterpuffers aus
         Parameter sind die 4 Seiten des Rechtecks in Character-Cells oder ein winc::range, sowie der auszugebende Textstring
         Rückgabewert ist die Anzahl geschriebener Zeichen aus dem String.
         Bemerkung:
          Ist der String länger als die Breite des Rechtecks, wird der String am letzten Leerzeichen vor Erreichen der
           Rechtecksbreite in die nächste Zeile umgebrochen. Das Leerzeichen wird dabei entfernt.
          Ist ein Wort länger als die Breite des Rechtecks, wird der Rest des Worts an der rechten Begrenzung des Rechtecks
           in die nächste Zeile umgebrochen.
          Enthält der String Zeilenumbrüche, wird der String an dieser Stelle in der nächsten Zeile fortgesetzt.
          Ist das untere rechte Ende des Rechtecks erreicht wird ggf. verbleibender Text im String nicht mehr ausgegeben.
          Die Cursorposition wird von dieser Funktion nicht verändert.
      */
      std::size_t printfittorect(const short left, const short top, const short right, const short bottom, const std::string& rStr) const;
      std::size_t printfittorect(const winc::range rng, const std::string& rStr) const;


      /* io::drawframechar() gibt ein Rahmenzeichen unter Beibehaltung der vorherigen Farbinformationen der Character-Cell aus
         Parameter sind die x und y Position in Character-Cells oder ein winc::cell, sowie ein Sting der die Richtung der Rahmenlinie(n) ausgehend von der Mitte der Character-Cell spezifiziert
          Folgende Buchstaben dürfen Verwendung finden:
          l - left   (nach links)
          t - top    (nach oben)
          r - right  (nach rechts)
          b - bottom (nach unten)
          Beispiele:
           drawframechar(0, 0, "tb");
            schreibt ein senkrechtes Rahmenzeichen in die obere linke Ecke des Fensterpuffers.
           drawframechar(4, 2, "tbl");
            schreibt ein senkrechtes Rahmenzeichen mit Abzweig nach links in die 5. Spalte der 3. Zeile des Fensterpuffers.
          Bei Verwendung von Großbuchstaben wird die jeweilige Richtung als Doppellinie ausgegeben
          Reihenfolge, sowie mehrfache Spezifikation einer Richtungsangabe werden ignoriert.
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
      */
      bool drawframechar(const short x, const short y, const std::string& rStrDirections) const;
      bool drawframechar(const winc::cell cc, const std::string& rStrDirections) const;


      /* io::drawlineh() gibt eine horizontale Linie unter Beibehaltung der vorherigen Farbinformationen der Character-Cells aus
         Parameter sind Start- und Endspalte, sowie Zeile in Character-Cells oder Start- und Endzelle als winc::cell
         Wird der optionale Parameter dbl mit true spezifiziert, wird eine Doppellinie ausgegeben
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
      */
      bool drawlineh(const short xStart, const short xStop, const short y, const bool dbl = false) const;
      bool drawlineh(const winc::cell ccStart, const winc::cell ccStop, const bool dbl = false) const;


      /* io::drawlinev() gibt eine vertikale Linie unter Beibehaltung der vorherigen Farbinformationen der Character-Cells aus
         Parameter sind Spalte, sowie Start- und Endzeile in Character-Cells oder Start- und Endzelle als winc::cell
         Wird der optionale Parameter dbl mit true spezifiziert, wird eine Doppellinie ausgegeben
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
      */
      bool drawlinev(const short x, const short yStart, const short yStop, const bool dbl = false) const;
      bool drawlinev(const winc::cell ccStart, const winc::cell ccStop, const bool dbl = false) const;


      /* io::drawbox() gibt einen rechteckigen Rahmen unter Beibehaltung der vorherigen Farbinformationen der Character-Cells aus
         Parameter sind die 4 Seiten des Rahmens in Character-Cells oder ein winc::range
         Wird der optionale Parameter dbl mit true spezifiziert, wird der Rahmen als Doppellinie ausgegeben
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
      */
      bool drawbox(const short left, const short top, const short right, const short bottom, const bool dbl = false) const;
      bool drawbox(const winc::range rng, const bool dbl = false) const;


      /* io::getclick() ermittelt die Position eines Mausklicks in das Consolefenster
         Parameter sind die zu verändernden Werte für x und y in Character-Cells bzw. ein winc::cell
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
      */
      bool getclick(short& rX, short& rY) const;
      bool getclick(winc::cell& rCc) const;


      /* io::getmouseover() koloriert Bereiche des Consolefensters beim überstreichen mit dem Mauszeiger
          und ermittelt den Index des Bereichs bei einem Mausklick
         Parameter sind ein Vector von zu überwachenden Fensterbereichen, sowie die zu verändernden Werte für Farbe und Index
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
         Bemerkung:
          Der Eingangswert von col wird verwendet, um den jeweiligen Bereich zu kolorieren.
          Nach Mausklick auf den Bereich behält dieser die neue Farbe bei, der ursprüngliche Farbwert
           der oberen linken Zelle des Bereichs wird col als neuer Wert zugewiesen.
          Der Eingangswert von index wird nicht verwendet. Nach Mausklick auf den Bereich wird dieser Variablen
           der Index des Bereichs im Vector rVecRanges zugewiesen.
      */
      bool getmouseover(const winc::rangevec_t& rVecRanges, unsigned& rCol, std::size_t& rIndex) const;

    private:
      wincons& rWc;

      io(wincons& refWc);
    };


    /* style Klasse */
    struct style
    {
      friend class winc::wincons;

      /* style::clearscreen() leert den Fensterpuffer (Farbwerte siehe COLOR Befehl der Windows Shell)
          Der Cursor wird in die erste Character-Cell des Fensterpuffers gesetz
         möglicher Parameter ist die zu verwendende Farbe
         Rückgabewert ist entweder die Größe des Fensterpuffers oder 0 bei Fehler
      */
      // die Standardfarbe wird verwendet
      unsigned clearscreen() const;
      // die angegebene Farbe wird verwendet und die Standardfarbe auf den neuen Wert geändert
      unsigned clearscreen(const unsigned col);


      /* style::clearrect() leert den Fensterpuffer im angegebenen Rechteck
          (Farbwerte siehe COLOR Befehl der Windows Shell)
         Parameter sind die 4 Seiten des Rechtecks in Character-Cells oder ein winc::range, optional die zu verwendende Farbe
         Rückgabewert ist entweder die Größe des Fensterpuffers oder 0 bei Fehler
      */
      // die Standardfarbe wird verwendet
      unsigned clearrect(const short left, const short top, const short right, const short bottom) const;
      unsigned clearrect(const winc::range rng) const;
      // die angegebene Farbe wird verwendet
      unsigned clearrect(const short left, const short top, const short right, const short bottom, const unsigned col) const;
      unsigned clearrect(const winc::range rng, const unsigned col) const;


      /* style::color() koloriert den gesamten Fensterpuffer (Farbwerte siehe COLOR Befehl der Windows Shell)
         möglicher Parameter ist die zu verwendende Farbe
         Rückgabewert ist entweder der vorherige Farbwert oder 0 bei Fehler
      */
      // die Standardfarbe wird verwendet
      unsigned color() const;
      // die angegebene Farbe wird verwendet und die Standardfarbe auf den neuen Wert geändert
      unsigned color(const unsigned col);


      /* style::colorrect() koloriert den Fensterpuffer im angegebenen Rechteck
          (Farbwerte siehe COLOR Befehl der Windows Shell)
         Parameter sind die 4 Seiten des Rechtecks in Character-Cells oder ein winc::range, optional die zu verwendende Farbe und Schattierung
         Rückgabewert ist entweder die Größe des Fensterpuffers oder 0 bei Fehler
      */
      // die Standardfarbe wird verwendet
      unsigned colorrect(const short left, const short top, const short right, const short bottom) const;
      unsigned colorrect(const winc::range rng) const;
      unsigned colorrect(const short left, const short top, const short right, const short bottom, const shades shade) const;
      unsigned colorrect(const winc::range rng, shades shade) const;
      // die angegebene Farbe wird verwendet
      unsigned colorrect(const short left, const short top, const short right, const short bottom, const unsigned col) const;
      unsigned colorrect(const winc::range rng, const unsigned col) const;
      unsigned colorrect(const short left, const short top, const short right, const short bottom, const unsigned col, shades shade) const;
      unsigned colorrect(const winc::range rng, const unsigned col, shades shade) const;


      /* style::textcolor() legt die Farbe für die zukünftige Ausgabe fest (Farbwerte siehe COLOR Befehl der Windows Shell)
         möglicher Parameter ist die zu verwendende Farbe
         Rückgabewert ist entweder der vorherige Farbwert oder 0 bei Fehler
      */
      // die Standardfarbe wird verwendet
      unsigned textcolor() const;
      // die angegebene Farbe wird verwendet
      unsigned textcolor(const unsigned col) const;


      /* style::setfont() legt die Schriftart fest
         Parameter ist die zu verwendende Schriftart
          Wird die Schriftart nicht unterstützt, wechselt die Console zur Standardschriftart
         Rückgabewert ist true wenn die Schriftart geändert wurde, anderenfalls false
      */
      bool setfont(const std::string& rStrName) const;

      /* style::setfontsize() verändert die Größe der Schrift
         Parameter sind die zu verwendenden Variablen für Breite und Höhe in Pixel
          Die Werte der Parametervariablen werden der neuen Schriftgröße angepasst
         Rückgabewert ist true wenn die Schriftgröße geändert wurde, anderenfalls false
         Bei nicht beschriebenen Fehlern werden die Parametervariablen auf 0 gesetzt
         Bemerkung:
          Nicht jede Größenangabe wird unterstützt. setfontsize() wird die Schriftgröße
           an die Breite und Höhe anpassen, die einer der unterstützten Schriftgrößen
           ähnlich ist. Sollte durch die Änderung die minimal oder maximal unterstützte
           Fenstergröße unter- bzw. überschritten werden, wird keine Änderung vorgenommen.
          Wenn in beiden Parametervariablen der Wert 0 übergeben wird, kann die aktuelle
           Schriftgröße ermittelt werden. (Der Rückgabewert ist aber false, da keine
           Änderung erfolgt.)
      */
      bool setfontsize(short& rWidth, short& rHight) const;

    private:
      wincons& rWc;

      style(wincons& refWc);
    };


    /* cursor Klasse */
    struct cursor
    {
      friend class winc::wincons;

      /* cursor::get() ermittelt die derzeitige Position des Consolecursors
         Parameter sind die zu verändernden Variablen für x und y in Character-Cells bzw. ein winc::cell
          Die Werte der Variablen werden der Position des Cursors angepasst
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
      */
      bool get(short& rX, short& rY) const;
      bool get(winc::cell& rCc) const;


      /* cursor::set() positioniert den Consolecursor
         Parameter sind die zu verwendenden Werte für x und y in Character-Cells bzw. ein winc::cell
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
      */
      bool set(const short x, const short y) const;
      bool set(const winc::cell cc) const;


      /* cursor::toggle() schaltet die Anzeige des Consolecursors ein bzw. aus
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
      */
      bool toggle() const;

    private:
      wincons& rWc;

      cursor(wincons& refWc);
    };


    /* window Klasse */
    struct window
    {
      friend class winc::wincons;

      /* window::title() ändert den Fenstertitel
         Parameter ist der neue Fenstertitel
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
      */
      bool title(const std::string& rStrTitle) const;


      /* window::resize() ändert die innere Fenstergröße und den Fensterpuffer auf die angegebene Größe
         Parameter sind die zu verwendenden Werte für Breite und Höhe in Character-Cells
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
      */
      bool resize(const short width, const short height) const;


      /* window::move() positioniert das Consolefenster auf dem Bildschirm
         Parameter sind die zu verwendenden Werte für Abstand von links und von oben in Pixel
         Rückgabewert ist entweder true bei Erfolg oder false bei Fehler
      */
      bool move(const int left, const int top) const;

    private:
      wincons& rWc;

      window(wincons& refWc);
    };

    /* Vorwärtsdeklaration */
    class winconshelper;
  }


  /* wincons Klasse mit den übergreifenden Membervariablen und eingebetteten Klassen */
  class wincons
  {
    static std::unique_ptr<wincons> pWcSingleton;
    const std::unique_ptr<detail_wincons::winconshelper> pWinconshelper;

    wincons();

  public:
    /* winc::wincons::wDefaultCol Standardfarbe (Werte siehe COLOR Befehl der Windows Shell) */
    unsigned wDefaultCol;

    /* winc::wincons::strDefaultMsg Standardmeldung für die wait() Funktion */
    std::string strDefaultMsg;

    /* eingebettete Klassen */
    winc::detail_wincons::io io;
    winc::detail_wincons::style style;
    winc::detail_wincons::cursor cursor;
    winc::detail_wincons::window window;

    /* winc::wincons::get() gibt eine Referenz auf die wincons Klasse zurück */
    static wincons& get();

    /* winc::wincons::retrieveUnderlyingPointer() gibt einen pointer auf die winconshelper Klasse zurück */
    detail_wincons::winconshelper* retrieveUnderlyingPointer();

    ~wincons();
  };

}

#endif // WINCONS_H
wincons.cpp
C++:
// wincons.cpp

#include "winconshelper.h"
#include "wincons.h"
#include <stdexcept>

std::unique_ptr<winc::wincons> winc::wincons::pWcSingleton;

winc::cell::cell(const short x, const short y)
  : x(x)
  , y(y)
{
}

winc::range::range(const short left, const short top, const short right, const short bottom)
  : left(left)
  , top(top)
  , right(right)
  , bottom(bottom)
{
}


winc::wincons::wincons()
try : pWinconshelper(new winc::detail_wincons::winconshelper)
    , wDefaultCol(pWinconshelper->getdefaultcolor())
    , strDefaultMsg("Press any key to continue . . . ")
    , io(*this)
    , style(*this)
    , cursor(*this)
    , window(*this)
{
}
catch(std::exception& e)
{
  throw e;
}
catch(...)
{
  throw std::runtime_error("Failed to construct wincons.");
}


winc::wincons::~wincons()
{
}

winc::wincons& winc::wincons::get()
{
  if (pWcSingleton.get() == NULL)
    pWcSingleton.reset(new wincons);

  return *pWcSingleton;
}

winc::detail_wincons::winconshelper* winc::wincons::retrieveUnderlyingPointer()
{
  return pWinconshelper.get();
}


/* io Klasse */
winc::detail_wincons::io::io(wincons& refWc)
  : rWc(refWc)
{
}

bool winc::detail_wincons::io::get(short& rNum, const short maxlen) const
{
  return rWc.retrieveUnderlyingPointer()->getinputinteger(rNum, maxlen);
}

bool winc::detail_wincons::io::get(int& rNum, const short maxlen) const
{
  return rWc.retrieveUnderlyingPointer()->getinputinteger(rNum, maxlen);
}

bool winc::detail_wincons::io::get(long& rNum, const short maxlen) const
{
  return rWc.retrieveUnderlyingPointer()->getinputinteger(rNum, maxlen);
}

bool winc::detail_wincons::io::get(long long& rNum, const short maxlen) const
{
  return rWc.retrieveUnderlyingPointer()->getinputinteger(rNum, maxlen);
}

bool winc::detail_wincons::io::get(unsigned short& rNum, const short maxlen) const
{
  return rWc.retrieveUnderlyingPointer()->getinputunsigned(rNum, maxlen);
}

bool winc::detail_wincons::io::get(unsigned int& rNum, const short maxlen) const
{
  return rWc.retrieveUnderlyingPointer()->getinputunsigned(rNum, maxlen);
}

bool winc::detail_wincons::io::get(unsigned long& rNum, const short maxlen) const
{
  return rWc.retrieveUnderlyingPointer()->getinputunsigned(rNum, maxlen);
}

bool winc::detail_wincons::io::get(unsigned long long& rNum, const short maxlen) const
{
  return rWc.retrieveUnderlyingPointer()->getinputunsigned(rNum, maxlen);
}

bool winc::detail_wincons::io::get(float& rNum, const short maxlen) const
{
  return rWc.retrieveUnderlyingPointer()->getinputfloatingpt(rNum, maxlen);
}

bool winc::detail_wincons::io::get(double& rNum, const short maxlen) const
{
  return rWc.retrieveUnderlyingPointer()->getinputfloatingpt(rNum, maxlen);
}

bool winc::detail_wincons::io::get(long double& rNum, const short maxlen) const
{
  return rWc.retrieveUnderlyingPointer()->getinputfloatingpt(rNum, maxlen);
}

bool winc::detail_wincons::io::get(std::string& rStr, const short maxlen) const
{
  return rWc.retrieveUnderlyingPointer()->getinputstr(rStr, maxlen);
}

int winc::detail_wincons::io::wait() const
{
  return rWc.retrieveUnderlyingPointer()->wait(rWc.strDefaultMsg, INFINITE);
}

int winc::detail_wincons::io::wait(const std::string& rStrMessage) const
{
  return rWc.retrieveUnderlyingPointer()->wait(rStrMessage, INFINITE);
}

int winc::detail_wincons::io::wait(const unsigned timeout) const
{
  return rWc.retrieveUnderlyingPointer()->wait(rWc.strDefaultMsg, timeout);
}

int winc::detail_wincons::io::wait(const std::string& rStrMessage, const unsigned timeout) const
{
  return rWc.retrieveUnderlyingPointer()->wait(rStrMessage, timeout);
}

bool winc::detail_wincons::io::printkeepcol(const std::string& rStr) const
{
  return rWc.retrieveUnderlyingPointer()->printkeepcol(rStr);
}

std::size_t winc::detail_wincons::io::printfittorect(const short left, const short top, const short right, const short bottom, const std::string& rStr) const
{
  return rWc.retrieveUnderlyingPointer()->printfittorect(left, top, right, bottom, rStr);
}

std::size_t winc::detail_wincons::io::printfittorect(const winc::range rng, const std::string& rStr) const
{
  return rWc.retrieveUnderlyingPointer()->printfittorect(rng.left, rng.top, rng.right, rng.bottom, rStr);
}

bool winc::detail_wincons::io::drawframechar(const short x, const short y, const std::string& rStrDirections) const
{
  return rWc.retrieveUnderlyingPointer()->drawframechar(x, y, rStrDirections);
}

bool winc::detail_wincons::io::drawframechar(const winc::cell cc, const std::string& rStrDirections) const
{
  return rWc.retrieveUnderlyingPointer()->drawframechar(cc.x, cc.y, rStrDirections);
}

bool winc::detail_wincons::io::drawlineh(const short xStart, const short xStop, const short y, const bool dbl) const
{
  return rWc.retrieveUnderlyingPointer()->drawlineh(xStart, xStop, y, dbl);
}

bool winc::detail_wincons::io::drawlineh(const winc::cell ccStart, const winc::cell ccStop, const bool dbl) const
{
  if (ccStart.y == ccStop.y)
    return rWc.retrieveUnderlyingPointer()->drawlineh(ccStart.x, ccStop.x, ccStart.y, dbl);
  return false;
}

bool winc::detail_wincons::io::drawlinev(const short x, const short yStart, const short yStop, const bool dbl) const
{
  return rWc.retrieveUnderlyingPointer()->drawlinev(x, yStart, yStop, dbl);
}

bool winc::detail_wincons::io::drawlinev(const winc::cell ccStart, const winc::cell ccStop, const bool dbl) const
{
  if (ccStart.x == ccStop.x)
    return rWc.retrieveUnderlyingPointer()->drawlineh(ccStart.x, ccStart.y, ccStop.y, dbl);
  return false;
}

bool winc::detail_wincons::io::drawbox(const short left, const short top, const short right, const short bottom, const bool dbl) const
{
  return rWc.retrieveUnderlyingPointer()->drawbox(left, top, right, bottom, dbl);
}

bool winc::detail_wincons::io::drawbox(const winc::range rng, const bool dbl) const
{
  return rWc.retrieveUnderlyingPointer()->drawbox(rng.left, rng.top, rng.right, rng.bottom, dbl);
}

bool winc::detail_wincons::io::getclick(short& rX, short& rY) const
{
  return rWc.retrieveUnderlyingPointer()->getclickxy(rX, rY);
}

bool winc::detail_wincons::io::getclick(winc::cell& rCc) const
{
  return rWc.retrieveUnderlyingPointer()->getclickxy(rCc.x, rCc.y);
}

bool winc::detail_wincons::io::getmouseover(const winc::rangevec_t& rVecRanges, unsigned& rCol, std::size_t& rIndex) const
{
  return rWc.retrieveUnderlyingPointer()->getmouseover(rVecRanges, rCol, rIndex);
}


/* style Klasse */
winc::detail_wincons::style::style(wincons& refWc)
  : rWc(refWc)
{
}

unsigned winc::detail_wincons::style::clearscreen() const
{
  return rWc.retrieveUnderlyingPointer()->clearscreen(rWc.wDefaultCol);
}

unsigned winc::detail_wincons::style::clearscreen(const unsigned col)
{
  unsigned ret = 0;
  if ((ret = rWc.retrieveUnderlyingPointer()->clearscreen(col)))
    rWc.wDefaultCol = col;
  return ret;
}

unsigned winc::detail_wincons::style::clearrect(const short left, const short top, const short right, const short bottom) const
{
  return rWc.retrieveUnderlyingPointer()->clearrect(left, top, right, bottom, rWc.wDefaultCol);
}

unsigned winc::detail_wincons::style::clearrect(const short left, const short top, const short right, const short bottom, const unsigned col) const
{
  return rWc.retrieveUnderlyingPointer()->clearrect(left, top, right, bottom, col);
}

unsigned winc::detail_wincons::style::clearrect(const winc::range rng) const
{
  return rWc.retrieveUnderlyingPointer()->clearrect(rng.left, rng.top, rng.right, rng.bottom, rWc.wDefaultCol);
}

unsigned winc::detail_wincons::style::clearrect(const winc::range rng, const unsigned col) const
{
  return rWc.retrieveUnderlyingPointer()->clearrect(rng.left, rng.top, rng.right, rng.bottom, col);
}

unsigned winc::detail_wincons::style::color() const
{
  return rWc.retrieveUnderlyingPointer()->color(rWc.wDefaultCol);
}

unsigned winc::detail_wincons::style::color(const unsigned col)
{
  unsigned ret = 0;
  if ((ret = rWc.retrieveUnderlyingPointer()->color(col)))
    rWc.wDefaultCol = col;
  return ret;
}

unsigned winc::detail_wincons::style::colorrect(const short left, const short top, const short right, const short bottom) const
{
  return rWc.retrieveUnderlyingPointer()->colorrect(left, top, right, bottom, rWc.wDefaultCol);
}

unsigned winc::detail_wincons::style::colorrect(const short left, const short top, const short right, const short bottom, const shades shade) const
{
  return rWc.retrieveUnderlyingPointer()->colorrect(left, top, right, bottom, rWc.wDefaultCol, static_cast<int>(shade));
}

unsigned winc::detail_wincons::style::colorrect(const short left, const short top, const short right, const short bottom, const unsigned col) const
{
  return rWc.retrieveUnderlyingPointer()->colorrect(left, top, right, bottom, col);
}

unsigned winc::detail_wincons::style::colorrect(const short left, const short top, const short right, const short bottom, const unsigned col, const shades shade) const
{
  return rWc.retrieveUnderlyingPointer()->colorrect(left, top, right, bottom, col, static_cast<int>(shade));
}

unsigned winc::detail_wincons::style::colorrect(const winc::range rng) const
{
  return rWc.retrieveUnderlyingPointer()->colorrect(rng.left, rng.top, rng.right, rng.bottom, rWc.wDefaultCol);
}

unsigned winc::detail_wincons::style::colorrect(const winc::range rng, const shades shade) const
{
  return rWc.retrieveUnderlyingPointer()->colorrect(rng.left, rng.top, rng.right, rng.bottom, rWc.wDefaultCol, static_cast<int>(shade));
}

unsigned winc::detail_wincons::style::colorrect(const winc::range rng, const unsigned col) const
{
  return rWc.retrieveUnderlyingPointer()->colorrect(rng.left, rng.top, rng.right, rng.bottom, col);
}

unsigned winc::detail_wincons::style::colorrect(const winc::range rng, const unsigned col, const shades shade) const
{
  return rWc.retrieveUnderlyingPointer()->colorrect(rng.left, rng.top, rng.right, rng.bottom, col, static_cast<int>(shade));
}

unsigned winc::detail_wincons::style::textcolor() const
{
  return rWc.retrieveUnderlyingPointer()->textcolor(rWc.wDefaultCol);
}

unsigned winc::detail_wincons::style::textcolor(const unsigned col) const
{
  return rWc.retrieveUnderlyingPointer()->textcolor(col);
}

bool winc::detail_wincons::style::setfont(const std::string& rStrName) const
{
  return rWc.retrieveUnderlyingPointer()->setfont(rStrName);
}

bool winc::detail_wincons::style::setfontsize(short& rWidth, short& rHeight) const
{
  return rWc.retrieveUnderlyingPointer()->setfontsize(rWidth, rHeight);
}


/* cursor Klasse */
winc::detail_wincons::cursor::cursor(wincons& refWc)
  : rWc(refWc)
{
}

bool winc::detail_wincons::cursor::get(short& rX, short& rY) const
{
  return rWc.retrieveUnderlyingPointer()->getcurxy(rX, rY);
}

bool winc::detail_wincons::cursor::get(winc::cell& rCc) const
{
  return rWc.retrieveUnderlyingPointer()->getcurxy(rCc.x, rCc.y);
}

bool winc::detail_wincons::cursor::set(const short x, const short y) const
{
  return rWc.retrieveUnderlyingPointer()->setcurxy(x, y);
}

bool winc::detail_wincons::cursor::set(const winc::cell cc) const
{
  return rWc.retrieveUnderlyingPointer()->setcurxy(cc.x, cc.y);
}

bool winc::detail_wincons::cursor::toggle() const
{
  return rWc.retrieveUnderlyingPointer()->togglecursor();
}


/* window Klasse */
winc::detail_wincons::window::window(wincons& refWc)
  : rWc(refWc)
{
}

bool winc::detail_wincons::window::title(const std::string& rStrTitle) const
{
  return rWc.retrieveUnderlyingPointer()->title(rStrTitle);
}

bool winc::detail_wincons::window::resize(const short width, const short height) const
{
  return rWc.retrieveUnderlyingPointer()->resize(width, height);
}

bool winc::detail_wincons::window::move(const int left, const int top) const
{
  return rWc.retrieveUnderlyingPointer()->move(left, top);
}
winconshelper.h
C++:
// winconshelper.h

#ifndef WINCONSHELPER_H
#define WINCONSHELPER_H

#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0601
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <conio.h>
#include <sstream>
#include "wincons.h"

namespace winc
{

  namespace detail_wincons
  {

    class winconshelper
    {
      friend class winc::wincons;

      const HWND hwndCon;
      const HANDLE hOut, hIn;
      const std::vector<wchar_t> frames;
      const std::vector<wchar_t> blocks;
      const DWORD dflt_mode;
      const CONSOLE_SCREEN_BUFFER_INFO dflt_csbi;
      const WINDOWPLACEMENT dflt_wplmt;
      const CONSOLE_CURSOR_INFO dflt_curinfo;
      CONSOLE_FONT_INFOEX dflt_cfix;

      struct rangeinfo
      {
        COORD coordBufSize;
        SMALL_RECT srctRect;
        std::vector<CHAR_INFO> chiVecOld;
        std::vector<CHAR_INFO> chiVecNew;
      };

      static unsigned __stdcall key(void *ch);
      DWORD getmode() const;
      CONSOLE_SCREEN_BUFFER_INFO getscreenbufferinfo() const;
      WINDOWPLACEMENT getplacement() const;
      CONSOLE_CURSOR_INFO getcurinfo() const;
      CONSOLE_FONT_INFOEX getfontinfo() const;
      void reset();
      winconshelper();

    public:
      ~winconshelper();

      template<typename T>
      bool getinputinteger(T& rNum, const short maxlen) const
      {
        short len = 0, i = 0;
        T numtmp = 0;
        int ch = 0;
        std::string str;
        CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
        COORD coordBufSize = {maxlen, 1};
        COORD coordBufCoord = {0, 0};

        if (maxlen < 1
            || !GetConsoleScreenBufferInfo(hOut, &csbi))
          return false;
        std::vector<CHAR_INFO> chiVec(maxlen);
        SMALL_RECT srctRect = {csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y, static_cast<short>(csbi.dwCursorPosition.X + maxlen), csbi.dwCursorPosition.Y};
        COORD crdCur = csbi.dwCursorPosition;
        if (!ReadConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
          return false;
        for (i = 0; i < maxlen; ++i)
          chiVec.at(i).Char.AsciiChar = ' ';
        if (!WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
          return false;
        while (ch != 13)
        {
          ch = _getch();
          if (ch == 0 || ch == 224)
            ch = 256 + _getch();
          if (len < maxlen)
          {
            if ( (ch == static_cast<int>('-') && len == 0)
                || (ch == static_cast<int>('+') && len == 0)
                || (ch >= static_cast<int>('0') && ch <= static_cast<int>('9')) )
            {
              str += static_cast<char>(ch);
              chiVec.at(len).Char.AsciiChar = ch;
              ++len;
              ++crdCur.X;
              if (!WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect)
                  || !SetConsoleCursorPosition(hOut, crdCur))
                return false;
            }
          }
          if (ch == static_cast<int>('\b') && len > 0)
          {
            str = str.substr(0, str.size() - 1);
            --len;
            --crdCur.X;
            chiVec.at(len).Char.AsciiChar = ' ';
            if (!WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect)
                || !SetConsoleCursorPosition(hOut, crdCur))
              return false;
          }
        }
        if (!(std::istringstream(str) >> numtmp).fail())
        {
          rNum = numtmp;
          return true;
        }
        return false;
      }

      template<typename T>
      bool getinputunsigned(T& rNum, const short maxlen) const
      {
        short len = 0, i = 0;
        T numtmp = 0;
        int ch = 0;
        std::string str;
        CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
        COORD coordBufSize = {maxlen, 1};
        COORD coordBufCoord = {0, 0};

        if (maxlen < 1
            || !GetConsoleScreenBufferInfo(hOut, &csbi))
          return false;
        std::vector<CHAR_INFO> chiVec(maxlen);
        SMALL_RECT srctRect = {csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y, static_cast<short>(csbi.dwCursorPosition.X + maxlen), csbi.dwCursorPosition.Y};
        COORD crdCur = csbi.dwCursorPosition;
        if (!ReadConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
          return false;
        for (i = 0; i < maxlen; ++i)
          chiVec.at(i).Char.AsciiChar = ' ';
        if (!WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
          return false;
        while (ch != 13)
        {
          ch = _getch();
          if (ch == 0 || ch == 224)
            ch = 256 + _getch();
          if (len < maxlen)
          {
            if ( (ch == static_cast<int>('+') && len == 0)
                || (ch >= static_cast<int>('0') && ch <= static_cast<int>('9')) )
            {
              str += static_cast<char>(ch);
              chiVec.at(len).Char.AsciiChar = ch;
              ++len;
              ++crdCur.X;
              if (!WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect)
                  || !SetConsoleCursorPosition(hOut, crdCur))
                return false;
            }
          }
          if (ch == static_cast<int>('\b') && len > 0)
          {
            str = str.substr(0, str.size() - 1);
            --len;
            --crdCur.X;
            chiVec.at(len).Char.AsciiChar = ' ';
            if (!WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect)
                || !SetConsoleCursorPosition(hOut, crdCur))
              return false;
          }
        }
        if (!(std::istringstream(str) >> numtmp).fail())
        {
          rNum = numtmp;
          return true;
        }
        return false;
      }

      template<typename T>
      bool getinputfloatingpt(T& rNum, const short maxlen) const
      {
        short len = 0, i = 0, sign = -1, fpoint = -1, exp = -1;
        T numtmp = 0;
        int ch = 0;
        std::string str;
        CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
        COORD coordBufSize = {maxlen, 1};
        COORD coordBufCoord = {0, 0};

        if (maxlen < 1
            || !GetConsoleScreenBufferInfo(hOut, &csbi))
          return false;
        std::vector<CHAR_INFO> chiVec(maxlen);
        SMALL_RECT srctRect = {csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y, static_cast<short>(csbi.dwCursorPosition.X + maxlen), csbi.dwCursorPosition.Y};
        COORD crdCur = csbi.dwCursorPosition;
        if (!ReadConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
          return false;
        for (i = 0; i < maxlen; ++i)
          chiVec.at(i).Char.AsciiChar = ' ';
        if (!WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
          return false;
        while (ch != 13)
        {
          ch = _getch();
          if (ch == 0 || ch == 224)
            ch = 256 + _getch();
          if (len < maxlen)
          {
            if ( (ch == static_cast<int>('-') && len - 1 == exp)
                || (ch == static_cast<int>('+') && len - 1 == exp)
                || (ch >= static_cast<int>('0') && ch <= static_cast<int>('9'))
                || (ch == static_cast<int>('.') && fpoint == -1 && exp == -1)
                || ( (ch == static_cast<int>('e') || ch == static_cast<int>('E')) && exp == -1 && len > 0 && !(len == 1 && !sign) ) )
            {
              str += static_cast<char>(ch);
              chiVec.at(len).Char.AsciiChar = ch;
              if (ch == static_cast<int>('-') && !len)
                sign = 0;
              else if (ch == static_cast<int>('+') && !len)
                sign = 0;
              else if (ch == static_cast<int>('.'))
                fpoint = len;
              else if (ch == static_cast<int>('e') || ch == static_cast<int>('E'))
                exp = len;
              ++len;
              ++crdCur.X;
              if (!WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect)
                  || !SetConsoleCursorPosition(hOut, crdCur))
                return false;
            }
          }
          if (ch == static_cast<int>('\b') && len > 0)
          {
            str = str.substr(0, str.size() - 1);
            --len;
            --crdCur.X;
            chiVec.at(len).Char.AsciiChar = ' ';
            if (len == sign)
              sign = -1;
            else if (len == fpoint)
              fpoint = -1;
            else if (len == exp)
              exp = -1;
            if (!WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect)
                || !SetConsoleCursorPosition(hOut, crdCur))
              return false;
          }
        }
        if (!(std::istringstream(str) >> numtmp).fail())
        {
          rNum = numtmp;
          return true;
        }
        return false;
      }

      bool getinputstr(std::string& rStr, const short maxlen) const;
      int wait(const std::string& rStrMessage, const unsigned timeout) const;
      bool printkeepcol(const std::string& rStr) const;
      std::size_t printfittorect(const short left, const short top, const short right, const short bottom, const std::string& rStr) const;
      bool drawframechar(const short x, const short y, const std::string& rStrDirections) const;
      bool drawlineh(const short xStart, const short xStop, const short y, const bool dbl) const;
      bool drawlinev(const short x, const short yStart, const short yStop, const bool dbl) const;
      bool drawbox(const short left, const short top, const short right, const short bottom, const bool dbl) const;
      bool getclickxy(short& rX, short& rY) const;
      bool getmouseover(const winc::rangevec_t& rVecRanges, unsigned& rCol, std::size_t& rIndex) const;

      unsigned clearscreen(const unsigned col) const;
      unsigned clearrect(const short left, const short top, const short right, const short bottom, const unsigned col) const;
      unsigned color(const unsigned col) const;
      unsigned colorrect(const short left, const short top, const short right, const short bottom, const unsigned col, const int blockidx = -1) const;
      unsigned textcolor(const unsigned col) const;
      bool setfont(const std::string& rStrName) const;
      bool setfontsize(short& rWidth, short& rHeight) const;

      bool getcurxy(short& rX, short& rY) const;
      bool setcurxy(const short x, const short y) const;
      bool togglecursor() const;

      bool title(const std::string& rStrTitle) const;
      bool resize(const short width, const short height) const;
      bool move(const int left, const int top) const;

      unsigned getdefaultcolor() const;
    };

  }

}

#endif // WINCONSHELPER_H
winconshelper.cpp
C++:
// winconshelper.cpp

#include "winconshelper.h"
#include <process.h>
#include <iostream>
#include <deque>
#include <stdexcept>
#include <cstdlib>

winc::detail_wincons::winconshelper::winconshelper()
  : hwndCon(GetConsoleWindow())
  , hOut(GetStdHandle(STD_OUTPUT_HANDLE))
  , hIn(GetStdHandle(STD_INPUT_HANDLE))
  , frames({0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524, 0x252C, 0x2534, 0x253C, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, 0x255F, 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C})
  , blocks({0x2591, 0x2592, 0x2593})
  , dflt_mode(getmode())
  , dflt_csbi(getscreenbufferinfo())
  , dflt_wplmt(getplacement())
  , dflt_curinfo(getcurinfo())
  , dflt_cfix(getfontinfo())
{
  if (!hwndCon
      || hOut == INVALID_HANDLE_VALUE
      || hIn == INVALID_HANDLE_VALUE
      || !frames.front()
      || !blocks.front())
    throw std::runtime_error("Failed to construct winconshelper.");
}

winc::detail_wincons::winconshelper::~winconshelper()
{
  reset();
}

bool winc::detail_wincons::winconshelper::getinputstr(std::string& rStr, const short maxlen) const
{
  short len = 0, i = 0;
  std::string strtmp;
  int ch = 0;
  CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
  COORD coordBufSize = {maxlen, 1};
  COORD coordBufCoord = {0, 0};

  if (maxlen < 1
      || !GetConsoleScreenBufferInfo(hOut, &csbi))
    return false;
  std::vector<CHAR_INFO> chiVec(maxlen);
  SMALL_RECT srctRect = {csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y, static_cast<short>(csbi.dwCursorPosition.X + maxlen), csbi.dwCursorPosition.Y};
  COORD crdCur = csbi.dwCursorPosition;
  if (!ReadConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
    return false;
  for (i = 0; i < maxlen; ++i)
    chiVec.at(i).Char.AsciiChar = ' ';
  if (!WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
    return false;
  while (ch != 13)
  {
    ch = _getch();
    if (ch == 0 || ch == 224)
      ch = 256 + _getch();
    if (len < maxlen)
    {
      if (ch > 31 && ch < 256)
      {
        strtmp += static_cast<char>(ch);
        chiVec.at(len).Char.AsciiChar = ch;
        ++len;
        ++crdCur.X;
        if (!WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect)
            || !SetConsoleCursorPosition(hOut, crdCur))
          return false;
      }
    }
    if (ch == static_cast<int>('\b') && len > 0)
    {
      strtmp = strtmp.substr(0, strtmp.size() - 1);
      --len;
      --crdCur.X;
      chiVec.at(len).Char.AsciiChar = ' ';
      if (!WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect)
          || !SetConsoleCursorPosition(hOut, crdCur))
        return false;
    }
  }
  if (!strtmp.empty())
  {
    rStr = strtmp;
    return true;
  }
  return false;
}

int winc::detail_wincons::winconshelper::wait(const std::string& rStrMessage, const unsigned timeout) const
{
  int ch = 0;
  HANDLE hThread = NULL;

  std::cout << rStrMessage;
  FlushConsoleInputBuffer(hIn);

  if ((hThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, key, static_cast<void*>(&ch), 0, NULL))))
  {
    if (WaitForSingleObject(hThread, timeout) == WAIT_TIMEOUT)
      TerminateThread(hThread, 0);
    CloseHandle(hThread);
  }
  std::cout << '\n';
  FlushConsoleInputBuffer(hIn);
  return ch;
}

bool winc::detail_wincons::winconshelper::printkeepcol(const std::string& rStr) const
{
  std::string::size_type i = 0, len = rStr.size();
  CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
  COORD coordBufSize = {static_cast<short>(len), 1};
  COORD coordBufCoord = {0, 0};
  COORD crdCur = {0, 0};
  if (GetConsoleScreenBufferInfo(hOut, &csbi))
  {
    std::vector<CHAR_INFO> chiVec(len);
    SMALL_RECT srctRect = {csbi.dwCursorPosition.X, csbi.dwCursorPosition.Y, static_cast<short>(csbi.dwCursorPosition.X + len), csbi.dwCursorPosition.Y};
    if (ReadConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
    {
      for (i = 0; i < len; ++i)
        chiVec.at(i).Char.AsciiChar = rStr.at(i);
      if (WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
      {
        if (static_cast<short>(csbi.dwCursorPosition.X + len) < csbi.dwSize.X)
        {
          crdCur.X = static_cast<short>(csbi.dwCursorPosition.X + len);
          crdCur.Y = csbi.dwCursorPosition.Y;
        }
        else
          crdCur.Y = csbi.dwCursorPosition.Y + 1;
        if (SetConsoleCursorPosition(hOut, crdCur))
          return true;
      }
    }
  }
  return false;
}

std::size_t winc::detail_wincons::winconshelper::printfittorect(const short left, const short top, const short right, const short bottom, const std::string& rStr) const
{
  short width = right - left + 1, height = bottom - top + 1;
  long rectsize = width * height, currpos = 0;
  std::string::size_type lenStr = rStr.size(), lenSub = 0, i = 0, cnt = 0;
  COORD coordBufSize = {width, height};
  COORD coordBufCoord = {0, 0};
  SMALL_RECT srctRect = {left, top, right, bottom};
  std::string s;

  if (!lenStr
      || rectsize < 1)
    return 0;
  std::vector<CHAR_INFO> chiVec(rectsize);
  if (!ReadConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
    return 0;
  while (cnt < lenStr && currpos < rectsize)
  {
    s = rStr.substr(cnt, width + 1);
    s = s.substr(0, s.find_first_of('\n'));
    if (s.size() > static_cast<unsigned>(width))
      s = s.substr(0, s.find_last_of(' '));
    lenSub = s.size();
    if (lenSub > static_cast<unsigned>(width))
    {
      s = s.substr(0, width);
      cnt += width;
    }
    else
    {
      for (i = lenSub; i < static_cast<unsigned>(width); ++i)
        s += ' ';
      cnt += lenSub + 1;
    }
    for (i = currpos; i < static_cast<unsigned long>(currpos + width); ++i)
      chiVec.at(i).Char.AsciiChar = s.at(i - currpos);
    currpos += width;
  }
  for (; i < static_cast<unsigned long>(rectsize); ++i)
    chiVec.at(i).Char.AsciiChar = ' ';
  if (WriteConsoleOutputA(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
    return (cnt < lenStr && lenSub > static_cast<unsigned>(width)) ? cnt : cnt - 1;
  return 0;
}

bool winc::detail_wincons::winconshelper::drawframechar(const short x, const short y, const std::string& rStrDirections) const
{
  std::string::size_type i = 0, len = rStrDirections.size();
  unsigned char id = 0;
  wchar_t chFrame = 0;
  CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
  COORD coordBufSize = {1, 1};
  COORD coordBufCoord = {0, 0};
  CHAR_INFO chi = {0};
  SMALL_RECT srctRect = {x, y, x, y};
  if (len < 2
      || x < 0
      || y < 0
      || !GetConsoleScreenBufferInfo(hOut, &csbi)
      || x > csbi.dwSize.X
      || y > csbi.dwSize.Y)
    return false;
  for (i = 0; i < len; ++i)
  {
    switch (rStrDirections.at(i))
    {
      case 'B':
        id |= 128;
        break;
      case 'L':
        id |= 16;
        break;
      case 'R':
        id |= 64;
        break;
      case 'T':
        id |= 32;
        break;
      case 'b':
        id |= 8;
        break;
      case 'l':
        id |= 1;
        break;
      case 'r':
        id |= 4;
        break;
      case 't':
        id |= 2;
        break;
      default:
        return false;
    }
  }
  switch (id)
  {
    case 3:
      chFrame = frames.at(5);
      break;
    case 5:
      chFrame = frames.at(0);
      break;
    case 6:
      chFrame = frames.at(4);
      break;
    case 7:
      chFrame = frames.at(9);
      break;
    case 9:
      chFrame = frames.at(3);
      break;
    case 10:
      chFrame = frames.at(1);
      break;
    case 11:
      chFrame = frames.at(7);
      break;
    case 12:
      chFrame = frames.at(2);
      break;
    case 13:
      chFrame = frames.at(8);
      break;
    case 14:
      chFrame = frames.at(6);
      break;
    case 15:
      chFrame = frames.at(10);
      break;
    case 18:
      chFrame = frames.at(22);
      break;
    case 24:
      chFrame = frames.at(16);
      break;
    case 26:
      chFrame = frames.at(28);
      break;
    case 33:
      chFrame = frames.at(23);
      break;
    case 36:
      chFrame = frames.at(20);
      break;
    case 37:
      chFrame = frames.at(35);
      break;
    case 48:
      chFrame = frames.at(24);
      break;
    case 66:
      chFrame = frames.at(19);
      break;
    case 72:
      chFrame = frames.at(13);
      break;
    case 74:
      chFrame = frames.at(25);
      break;
    case 80:
      chFrame = frames.at(11);
      break;
    case 82:
      chFrame = frames.at(34);
      break;
    case 88:
      chFrame = frames.at(31);
      break;
    case 90:
      chFrame = frames.at(37);
      break;
    case 96:
      chFrame = frames.at(21);
      break;
    case 112:
      chFrame = frames.at(36);
      break;
    case 129:
      chFrame = frames.at(17);
      break;
    case 132:
      chFrame = frames.at(14);
      break;
    case 133:
      chFrame = frames.at(32);
      break;
    case 144:
      chFrame = frames.at(18);
      break;
    case 160:
      chFrame = frames.at(12);
      break;
    case 161:
      chFrame = frames.at(29);
      break;
    case 164:
      chFrame = frames.at(26);
      break;
    case 165:
      chFrame = frames.at(38);
      break;
    case 176:
      chFrame = frames.at(30);
      break;
    case 192:
      chFrame = frames.at(15);
      break;
    case 208:
      chFrame = frames.at(33);
      break;
    case 224:
      chFrame = frames.at(27);
      break;
    case 240:
      chFrame = frames.at(39);
      break;
    default:
      return false;
  }
  if (ReadConsoleOutputW(hOut, &chi, coordBufSize, coordBufCoord, &srctRect))
  {
    chi.Char.UnicodeChar = chFrame;
    if (WriteConsoleOutputW(hOut, &chi, coordBufSize, coordBufCoord, &srctRect))
      return true;
  }
  return false;
}

bool winc::detail_wincons::winconshelper::drawlineh(const short xStart, const short xStop, const short y, const bool dbl) const
{
  short i = 0, c = xStop - xStart + 1;
  wchar_t chFrame = (dbl) ? frames.at(11) : frames.at(0);
  COORD coordBufSize = {c, 1};
  COORD coordBufCoord = {0, 0};
  SMALL_RECT srctRect = {xStart, y, xStop, y};
  if (c < 1)
    return false;
  std::vector<CHAR_INFO> chiVec(c);
  if (ReadConsoleOutputW(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
  {
    for (i = 0; i < c; ++i)
      chiVec.at(i).Char.UnicodeChar = chFrame;
    if (WriteConsoleOutputW(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
      return true;
  }
  return false;
}

bool winc::detail_wincons::winconshelper::drawlinev(const short x, const short yStart, const short yStop, const bool dbl) const
{
  short i = 0, c = yStop - yStart + 1;
  wchar_t chFrame = (dbl) ? frames.at(12) : frames.at(1);
  COORD coordBufSize = {1, c};
  COORD coordBufCoord = {0, 0};
  SMALL_RECT srctRect = {x, yStart, x, yStop};
  if (c < 1)
    return false;
  std::vector<CHAR_INFO> chiVec(c);
  if (ReadConsoleOutputW(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
  {
    for (i = 0; i < c; ++i)
      chiVec.at(i).Char.UnicodeChar = chFrame;
    if (WriteConsoleOutputW(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
      return true;
  }
  return false;
}

bool winc::detail_wincons::winconshelper::drawbox(const short left, const short top, const short right, const short bottom, const bool dbl) const
{
  short i = 0, cCols = right - left + 1, cRows = bottom - top + 1;
  long boxsize = cCols * cRows;
  COORD coordBufSize = {cCols, cRows};
  COORD coordBufCoord = {0, 0};
  SMALL_RECT srctRect = {left, top, right, bottom};
  if (cCols < 2
      || cRows < 2)
    return false;
  std::vector<CHAR_INFO> chiVec(boxsize);
  if (ReadConsoleOutputW(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
  {
    chiVec.at(0).Char.UnicodeChar = (dbl) ? frames.at(15) : frames.at(2);
    chiVec.at(cCols - 1).Char.UnicodeChar = (dbl) ? frames.at(18) : frames.at(3);
    chiVec.at(cCols * (cRows - 1)).Char.UnicodeChar = (dbl) ? frames.at(21) : frames.at(4);
    chiVec.at(boxsize - 1).Char.UnicodeChar = (dbl) ? frames.at(24) : frames.at(5);
    for (i = 1; i < cCols - 1; ++i)
      chiVec.at(i).Char.UnicodeChar = (dbl) ? frames.at(11) : frames.at(0);
    for (i = 1; i < cRows - 1; ++i)
    {
      chiVec.at(i * cCols).Char.UnicodeChar = (dbl) ? frames.at(12) : frames.at(1);
      chiVec.at(i * cCols + cCols - 1).Char.UnicodeChar = (dbl) ? frames.at(12) : frames.at(1);
    }
    for (i = cCols * (cRows - 1) + 1; i < boxsize - 1; ++i)
      chiVec.at(i).Char.UnicodeChar = (dbl) ? frames.at(11) : frames.at(0);
    if (WriteConsoleOutputW(hOut, chiVec.data(), coordBufSize, coordBufCoord, &srctRect))
      return true;
  }
  return false;
}

bool winc::detail_wincons::winconshelper::getclickxy(short& rX, short& rY) const
{
  INPUT_RECORD irec = {0};
  DWORD dwMode = 0, c = 0;

  if (!GetConsoleMode(hIn, &dwMode))
    return false;

  if (SetConsoleMode(hIn, (ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS) & ~ENABLE_QUICK_EDIT_MODE))
  {
    do
    {
      if (ReadConsoleInput(hIn, &irec, 1, &c)
          && irec.EventType == MOUSE_EVENT
          && irec.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
      {
        rX = irec.Event.MouseEvent.dwMousePosition.X;
        rY = irec.Event.MouseEvent.dwMousePosition.Y;
        return true;
      }
    } while (c);
  }
  FlushConsoleInputBuffer(hIn);
  SetConsoleMode(hIn, dwMode | ENABLE_EXTENDED_FLAGS);
  return false;
}

bool winc::detail_wincons::winconshelper::getmouseover(const winc::rangevec_t& rVecRanges, unsigned& rCol, std::size_t& rIndex) const
{
  short x = 0, y = 0;
  long i = 0, boxsize = 0;
  DWORD dwMode = 0, c = 0;
  std::deque<rangeinfo>::size_type len = 0, k = 0, found = -1;
  COORD coordBufCoord = {0, 0};
  INPUT_RECORD irec = {0};
  rangeinfo ri = {0};
  std::deque<rangeinfo> deqrangeinfo;
  winc::rangevec_t::const_iterator it;

  if (rVecRanges.empty()
      || !GetConsoleMode(hIn, &dwMode)
      || !SetConsoleMode(hIn, (ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS) & ~ENABLE_QUICK_EDIT_MODE))
    return false;
  for (it = rVecRanges.begin(); it != rVecRanges.end(); ++it)
  {
    ri.coordBufSize.X = it->right - it->left + 1;
    ri.coordBufSize.Y = it->bottom - it->top + 1;
    ri.srctRect.Left = it->left;
    ri.srctRect.Top = it->top;
    ri.srctRect.Right = it->right;
    ri.srctRect.Bottom = it->bottom;
    boxsize = ri.coordBufSize.X * ri.coordBufSize.Y;
    if (boxsize < 1)
    {
      SetConsoleMode(hIn, dwMode | ENABLE_EXTENDED_FLAGS);
      return false;
    }
    ri.chiVecOld.resize(boxsize);
    ri.chiVecNew.resize(boxsize);
    if (!ReadConsoleOutputA(hOut, ri.chiVecOld.data(), ri.coordBufSize, coordBufCoord, &ri.srctRect))
    {
      SetConsoleMode(hIn, dwMode);
      return false;
    }
    ri.chiVecNew = ri.chiVecOld;
    for (i = 0; i < boxsize; ++i)
      ri.chiVecNew.at(i).Attributes = rCol;
    deqrangeinfo.push_back(ri);
  }
  len = deqrangeinfo.size();
  do
  {
    if (ReadConsoleInputA(hIn, &irec, 1, &c)
        && irec.EventType == MOUSE_EVENT)
    {
      x = irec.Event.MouseEvent.dwMousePosition.X;
      y = irec.Event.MouseEvent.dwMousePosition.Y;
      if (irec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
      {
        for (k = 0; k < len; k++)
        {
          if (x < deqrangeinfo.at(k).srctRect.Left
              || x > deqrangeinfo.at(k).srctRect.Right
              || y < deqrangeinfo.at(k).srctRect.Top
              || y > deqrangeinfo.at(k).srctRect.Bottom)
          {
            if (k == found)
            {
              WriteConsoleOutputA(hOut, deqrangeinfo.at(k).chiVecOld.data(), deqrangeinfo.at(k).coordBufSize, coordBufCoord, &deqrangeinfo.at(k).srctRect);
              found = -1;
            }
          }
          else
          {
            if (k != found)
            {
              WriteConsoleOutputA(hOut, deqrangeinfo.at(k).chiVecNew.data(), deqrangeinfo.at(k).coordBufSize, coordBufCoord, &deqrangeinfo.at(k).srctRect);
              found = k;
            }
          }
        }
      }
      else if (irec.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
      {
        for (k = 0; k < len; k++)
        {
          if (x >= deqrangeinfo.at(k).srctRect.Left
              && x <= deqrangeinfo.at(k).srctRect.Right
              && y >= deqrangeinfo.at(k).srctRect.Top
              && y <= deqrangeinfo.at(k).srctRect.Bottom)
          {
            do
            {
              if (!ReadConsoleInput(hIn, &irec, 1, &c))
                break;
            } while (irec.EventType != MOUSE_EVENT || irec.Event.MouseEvent.dwEventFlags);
            FlushConsoleInputBuffer(hIn);
            SetConsoleMode(hIn, dwMode);
            rCol = deqrangeinfo.at(k).chiVecOld.front().Attributes;
            rIndex = k;
            return true;
          }
        }
      }
    }
  } while (c);
  SetConsoleMode(hIn, dwMode);
  return false;
}

unsigned winc::detail_wincons::winconshelper::clearscreen(const unsigned col) const
{
  DWORD written = 0;
  CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
  COORD coord = {0, 0};

  if (GetConsoleScreenBufferInfo(hOut, &csbi)
      && SetConsoleCursorPosition(hOut, coord)
      && FillConsoleOutputAttribute(hOut, col, csbi.dwSize.X * csbi.dwSize.Y, coord, &written)
      && FillConsoleOutputCharacterA(hOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, coord, &written))
    return written;
  return 0;
}

unsigned winc::detail_wincons::winconshelper::clearrect(const short left, const short top, const short right, const short bottom, const unsigned col) const
{
  DWORD c = 0, written = 0;
  short width = right - left + 1, height = bottom - top + 1, i = 0;
  COORD coord = {left, top};

  if (width < 0 || height < 0)
    return 0;
  for (i = 0; i < height; ++i)
  {
    if (!FillConsoleOutputAttribute(hOut, col, width, coord, &c)
        || !FillConsoleOutputCharacterA(hOut, ' ', width, coord, &c))
      return 0;
    coord.Y++;
    written += c;
  }
  return written;
}

unsigned winc::detail_wincons::winconshelper::color(const unsigned col) const
{
  DWORD written = 0;
  CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
  COORD coord = {0, 0};

  if (GetConsoleScreenBufferInfo(hOut, &csbi)
      && SetConsoleTextAttribute(hOut, col)
      && FillConsoleOutputAttribute(hOut, col, csbi.dwSize.X * csbi.dwSize.Y, coord, &written))
    return csbi.wAttributes;
  return 0;
}

unsigned winc::detail_wincons::winconshelper::colorrect(const short left, const short top, const short right, const short bottom, const unsigned col, const int blockidx) const
{
  DWORD c = 0, written = 0;
  short width = right - left + 1, height = bottom - top + 1, i = 0;
  COORD coord = {left, top};

  if (width < 0 || height < 0)
    return 0;
  for (i = 0; i < height; ++i)
  {
    if (!FillConsoleOutputAttribute(hOut, col, width, coord, &c))
      return 0;
    if (blockidx > -1 && !FillConsoleOutputCharacterW(hOut, blocks.at(blockidx), width, coord, &c))
      return 0;
    coord.Y++;
    written += c;
  }
  return written;
}

unsigned winc::detail_wincons::winconshelper::textcolor(const unsigned col) const
{
  CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
  if (GetConsoleScreenBufferInfo(hOut, &csbi)
      && SetConsoleTextAttribute(hOut, col))
    return csbi.wAttributes;
  return 0;
}

bool winc::detail_wincons::winconshelper::setfont(const std::string& rStrName) const
{
  CONSOLE_FONT_INFOEX cfix = {sizeof(CONSOLE_FONT_INFOEX)};
  if (GetCurrentConsoleFontEx(hOut, FALSE, &cfix))
  {
    cfix.nFont = 0;
    cfix.FontFamily = FF_DONTCARE;
    cfix.FontWeight = FW_NORMAL;
    if (MultiByteToWideChar(CP_OEMCP, 0, rStrName.c_str(), -1, cfix.FaceName, LF_FACESIZE * sizeof(wchar_t)))
    {
      return SetCurrentConsoleFontEx(hOut, FALSE, &cfix) != 0;
    }
  }
  return false;
}

bool winc::detail_wincons::winconshelper::setfontsize(short& rWidth, short& rHeight) const
{
  CONSOLE_FONT_INFOEX cfix = {sizeof(CONSOLE_FONT_INFOEX)};
  COORD cfs1 = {0, 0}, cfs2 = {0, 0};
  short w = rWidth, h = rHeight;
  rWidth = 0;
  rHeight = 0;
  if (GetCurrentConsoleFontEx(hOut, FALSE, &cfix))
  {
    cfs1 = GetConsoleFontSize(hOut, cfix.nFont);
    if (cfs1.X && cfs1.Y)
    {
      cfix.dwFontSize.X = w;
      cfix.dwFontSize.Y = h;
      if (SetCurrentConsoleFontEx(hOut, FALSE, &cfix)
          && GetCurrentConsoleFontEx(hOut, FALSE, &cfix))
      {
        cfs2 = GetConsoleFontSize(hOut, cfix.nFont);
        if (cfs2.X && cfs2.Y)
        {
          rWidth = cfs2.X;
          rHeight = cfs2.Y;
          if (cfs1.X != cfs2.X || cfs1.Y != cfs2.Y)
            return true;
        }
      }
    }
  }

  return false;
}

bool winc::detail_wincons::winconshelper::getcurxy(short& rX, short& rY) const
{
  CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
  if (GetConsoleScreenBufferInfo(hOut, &csbi))
  {
    rX = csbi.dwCursorPosition.X;
    rY = csbi.dwCursorPosition.Y;
    return true;
  }
  return false;
}

bool winc::detail_wincons::winconshelper::setcurxy(const short x, const short y) const
{
  COORD coord = {x, y};
  return SetConsoleCursorPosition(hOut, coord) != 0;
}

bool winc::detail_wincons::winconshelper::togglecursor() const
{
  CONSOLE_CURSOR_INFO cci = {0};
  if (GetConsoleCursorInfo(hOut, &cci))
  {
    cci.bVisible = !cci.bVisible;
    if (SetConsoleCursorInfo(hOut, &cci))
      return true;
  }
  return false;
}

bool winc::detail_wincons::winconshelper::title(const std::string& rStrTitle) const
{
  if (SetConsoleTitleA(rStrTitle.c_str()))
    return true;
  return false;
}

bool winc::detail_wincons::winconshelper::resize(const short width, const short height) const
{
  COORD crdsize = GetLargestConsoleWindowSize(hOut);
  CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
  if (width > crdsize.X || height > crdsize.Y || !GetConsoleScreenBufferInfo(hOut, &csbi))
    return false;

  crdsize = {static_cast<short>(csbi.srWindow.Right - csbi.srWindow.Left + 1), static_cast<short>(csbi.srWindow.Bottom - csbi.srWindow.Top + 1)};
  csbi.srWindow = {0, 0, static_cast<short>((width < crdsize.X) ? width - 1 : crdsize.X - 1), static_cast<short>((height < crdsize.Y) ? height - 1 : crdsize.Y - 1)};
  if (!SetConsoleWindowInfo(hOut, TRUE, &csbi.srWindow))
    return false;

  crdsize = {width, height};
  csbi.srWindow = {0, 0, static_cast<short>(width - 1), static_cast<short>(height - 1)};
  if (!SetConsoleScreenBufferSize(hOut, crdsize) || !SetConsoleWindowInfo(hOut, TRUE, &csbi.srWindow))
    return false;

  return true;
}

bool winc::detail_wincons::winconshelper::move(const int left, const int top) const
{
  if (SetWindowPos(hwndCon, NULL, left, top, 0, 0, SWP_NOZORDER | SWP_NOSIZE))
    return true;
  return false;
}

unsigned winc::detail_wincons::winconshelper::getdefaultcolor() const
{
  CONSOLE_SCREEN_BUFFER_INFO csbi = {0};
  if (GetConsoleScreenBufferInfo(hOut, &csbi))
    return csbi.wAttributes;
  return 0x07;
}


unsigned __stdcall winc::detail_wincons::winconshelper::key(void *pch)
{
  int ch = 0;
  ch = _getch();
  if (ch == 0 || ch == 224)
    ch = 256 + _getch();
  *(static_cast<int*>(pch)) = ch;
  _endthreadex(0);
  return 0;
}

DWORD winc::detail_wincons::winconshelper::getmode() const
{
  DWORD tmpmode = 0;
  if (GetConsoleMode(hIn, &tmpmode))
    return tmpmode;
  return -1; // check condition
}

CONSOLE_SCREEN_BUFFER_INFO winc::detail_wincons::winconshelper::getscreenbufferinfo() const
{
  CONSOLE_SCREEN_BUFFER_INFO tmpcsbi = {0};
  if (GetConsoleScreenBufferInfo(hOut, &tmpcsbi))
    return tmpcsbi;

  tmpcsbi.dwMaximumWindowSize.X = 0; // check condition
  return tmpcsbi;
}

WINDOWPLACEMENT winc::detail_wincons::winconshelper::getplacement() const
{
  WINDOWPLACEMENT tmpwplm = {0};
  tmpwplm.length = sizeof(WINDOWPLACEMENT);
  if (GetWindowPlacement(hwndCon, &tmpwplm))
    return tmpwplm;

  tmpwplm.length = 0; // check condition
  return tmpwplm;
}

CONSOLE_CURSOR_INFO winc::detail_wincons::winconshelper::getcurinfo() const
{
  CONSOLE_CURSOR_INFO curinfo = {0};
  GetConsoleCursorInfo(hOut, &curinfo);
  return curinfo;
}

CONSOLE_FONT_INFOEX winc::detail_wincons::winconshelper::getfontinfo() const
{
  CONSOLE_FONT_INFOEX cfix = {sizeof(CONSOLE_FONT_INFOEX)};
  if (GetCurrentConsoleFontEx(hOut, FALSE, &cfix))
    cfix.dwFontSize = GetConsoleFontSize(hOut, cfix.nFont);
  return cfix;
}

void winc::detail_wincons::winconshelper::reset()
{
  if (dflt_mode != static_cast<DWORD>(-1)
      && dflt_csbi.dwMaximumWindowSize.X
      && dflt_cfix.dwFontSize.X
      && dflt_cfix.dwFontSize.Y
      && dflt_wplmt.length)
  {
    SetConsoleMode(hIn, dflt_mode | ENABLE_EXTENDED_FLAGS);
    textcolor(dflt_csbi.wAttributes);
    clearscreen(dflt_csbi.wAttributes);
    MoveWindow(hwndCon, dflt_wplmt.rcNormalPosition.left, dflt_wplmt.rcNormalPosition.top, dflt_wplmt.rcNormalPosition.left + 1, dflt_wplmt.rcNormalPosition.top + 1, TRUE);
    SetCurrentConsoleFontEx(hOut, FALSE, &dflt_cfix);
    SetConsoleScreenBufferSize(hOut, dflt_csbi.dwSize);
    SetConsoleWindowInfo(hOut, FALSE, &dflt_csbi.srWindow);
    SetWindowPlacement(hwndCon, &dflt_wplmt);
    SetConsoleCursorInfo(hOut, &dflt_curinfo);
    COORD coord = {0, 0};
    SetConsoleCursorPosition(hOut, coord);
  }
}
Getestet unter Windows 7 x86 und x64 mit den Compilern VC 2015 und MinGW-w64 5.0.0

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Hier noch ein kleines Beispiel, passend zur Abbildung oben:

main.cpp
C++:
// main.cpp

#include "wincons.h"
#include <iostream>
#include <iomanip>
#include <stdexcept>

int main()
{
  try
  {
    // Referenz der wincons Klasse
    winc::wincons& rWc = winc::wincons::get();


    // Formatflags des cout Streams speichern, um sie bei Bedarf zurücksetzen zu können
    std::ios::fmtflags iosf(std::cout.flags());

    // Variablen für Funktionsparameter
    short x = 0, y = 0;
    winc::cell charcell;
    unsigned col = 0xb0;
    winc::rangevec_t rgv;
    std::size_t index = 0;
    float f = 0.;
    std::size_t len = 0;
    const std::string txt =
      "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy"
      " eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam"
      " voluptua.\nAt vero eos et accusam et justo duo dolores et ea rebum.\nStet"
      " clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.";

    // Fenster in die obere linke Ecke des Bildschirms setzen
    rWc.window.move(0, 0);
    // Fenstertitel ändern
    rWc.window.title("Test");

    // Farbe zu Grün auf schwarz ändern
    rWc.style.color(0x0a);

    // Schriftart auf Lucida Console setzen
    rWc.style.setfont("Consolas");

    // Schriftgröße auf 6 x 12 Pixel setzen
    x = 6;
    y = 12;
    rWc.style.setfontsize(x, y);

    // Fenstergröße auf eine Breite von 100 und eine Höhe von 30 Character-Cells setzen
    rWc.window.resize(100, 30);

    // Cursor in die 11. Spalte in der 4. Zeile setzen
    rWc.cursor.set(10, 3);
    // Ausgabe
    std::cout << "Test\n\n";

    std::cout << "Schriftgroesse: " << x << " x " << y << "\n\n";

    // Schriftfarbe ändern
    std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex
              << rWc.style.textcolor(0x09) << " war die vorherige Farbe.\n\n";
    std::cout.flags(iosf);

    // Auf Tastendruck warten
    std::cout << rWc.io.wait("Taste druecken ... ") << " repraesentiert die gedrueckte Taste.\n\n";

    // Rechteck Schwarz auf Rot
    std::cout << rWc.style.colorrect(80, 8, 89, 12, 0xc0, winc::shades::light) << " ist die Groesse des roten Rechtecks.\n\n";

    // Text über die Grenze des Rechtecks hinweg ausgeben, wobei die Farbinformationen der Character-Cells erhalten bleiben
    rWc.cursor.set(82, 10);
    rWc.io.printkeepcol("Hello World!");

    // kleines Quadrat in die linke obere Ecke des roten Rechtecks überlappend ausgeben
    rWc.io.drawbox(78, 7, 80, 8, true);

    // vertikale Linie
    rWc.io.drawlinev(65, 0, 29, true);
    // horizontale Linie
    rWc.io.drawlineh(65, 99, 20);
    // Rahmenzeichen zum Verbinden der Linien
    rWc.io.drawframechar(65, 20, "TrB");

    // *** Buttons ***
    // Aufforderung einen der Buttons anzuklicken
    rWc.cursor.set(0, 15);
    rWc.cursor.toggle();
    std::cout << "Einen der beiden blauen Buttons druecken ...";

    // Bereiche der Buttons im Vectorcontainer festlegen
    rgv.push_back(winc::range(69, 23, 80, 25));
    rgv.push_back(winc::range(85, 23, 96, 25));

    // Schatten des ersten Buttons
    rWc.style.colorrect(rgv.at(0).left + 1, rgv.at(0).top + 1, rgv.at(0).right + 1, rgv.at(0).bottom + 1, 0x80);
    // Rechteck als Button darüber legen
    rWc.style.colorrect(rgv.at(0), 0x90);
    // Beschriftung des Buttons
    rWc.cursor.set(70, 24);
    rWc.io.printkeepcol("Click here");

    // Das gleiche für den 2. Button
    rWc.style.colorrect(rgv.at(1).left + 1, rgv.at(1).top + 1, rgv.at(1).right + 1, rgv.at(1).bottom + 1, 0x80);
    rWc.style.colorrect(rgv.at(1), 0x90);
    rWc.cursor.set(88, 24);
    rWc.io.printkeepcol("Or here");

    // Mit Mouse-Over-Effekt auf Anklicken eines der beiden Buttons warten
    rWc.io.getmouseover(rgv, col, index);

    // Ausgabe
    rWc.cursor.toggle();
    rWc.cursor.set(0, 20);
    std::cout << "Index des Buttons im Vector ist " << index
              << ",\n0x" << std::setfill('0') << std::setw(2) << std::hex
              << col << " war die vorherige Farbe der linken oberen Ecke.\n\n";
    std::cout.flags(iosf);
    // *** Buttons Ende ***

    // Fensterinhalt löschen
    rWc.io.wait("Fensterinhalt loeschen ... ");
    std::cout << rWc.style.clearscreen() << " ist die Groesse des Fensterpuffers.\n\n";

    // Textfarbe auf Standard (Grün auf Schwarz) zurück setzen
    std::cout << "0x" << std::setfill('0') << std::setw(2) << std::hex
              << rWc.style.textcolor() << " war die vorherige Farbe.\n\n";
    std::cout.flags(iosf);

    // Dummytext passend in ein Rechteck 30 x 20 schreiben
    rWc.style.colorrect(65, 5, 94, 24, 0x4e);
    len = rWc.io.printfittorect(65, 5, 94, 24, txt);
    std::cout << len << " von " << txt.size() << " Zeichen Dummytext wurden\nin das Rechteck geschrieben.\n\n";

    // Eingabe
    std::cout << "Zahl eingeben: ";
    rWc.style.colorrect(14, 7, 20, 7, 0xe1);
    rWc.io.get(f, 5);
    std::cout << "\nEingabe war " << f << "\n\n";

    // Cursoranzeige ausschalten
    rWc.cursor.toggle();
    // Auf Mausklick warten
    std::cout << "Mausklick in das Fenster ... ";
    rWc.io.getclick(charcell);
    // Cursor auf die ermittelte Position setzen
    rWc.cursor.set(charcell);
    // Cursoranzeige einschalten
    rWc.cursor.toggle();
    // 3 Sekunden auf Tastendruck warten
    rWc.io.wait(3000);

    return 0;
  }
  catch(std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }
  catch(...)
  {
    std::cerr << "An error occured." << std::endl;
  }
  return 1;
}
Autor
German
First release
Last update
Bewertung
0,00 Stern(e) 0 Bewertungen

Latest updates

  1. C++ Lib für Manipulationen am Windows-Consolefenster (v. 3.5)

    Change Log: v. 3.5 / 2017-01-14 Bugfix resize() auf Win10, setfont() hinzu, Doppelrahmen hinzu...
  2. C++ Lib für Manipulationen am Windows-Consolefenster (v. 3.4)

    Change Log: v. 3.4 / 2017-01-01 Shades hinzu, kleinere Änderungen v. 3.3 / 2014-08-24 Exception...
  3. C++ Lib für Manipulationen am Windows-Consolefenster (v. 3.3)

    Change Log: v. 3.3 / 2014-08-24 Exception Handling erweitert v. 3.2 / 2014-08-02 Exception bei...
Oben