Have you tried to print colored text in a console or put the text at a specific position? You know then that STL or CRT does not provide that functionality.
Windows API however, contains a set of functions for working with console windows. The list of these functions is available in MSDN.

However, to simplify the use of these functions I have created a template, wrapper class that provides methods and overloaded operators to:

  • change the color for text and background
  • set the cursor position
  • write to the console
  • read from the console

The class is called basic_console, and is a template class. There are two specializations, one for ANSI, called console, and one for UNICODE, called wconsole.

typedef basic_console< char, std::char_traits< char >> console;
typedef basic_console< wchar_t, std::char_traits< wchar_t >> wconsole;

You can change the position on both horizontal and vertical or on only one of the two:

   void GoTo(int x, int y)
   void GoToX(int x)
   void GoToY(int y)
   console_pos GetConsolePos()

There is also an overloaded operator for changing the position, specified with a console_pos structure.

	_Myt& operator<<(const console_pos& pos)

For the color, you can change the text and background color, using one of these functions:

   void SetForeColor(text_color::Color crText)
   void SetBackColor(bg_color::Color crBack)
   void SetColors(text_color::Color crText, bg_color::Color crBack)
   void SetColors(WORD colors)
   void SetColors(WORD crText, WORD crBack)
   void UseDefaultColors()

   _Myt& operator<<(const console_colors& col)

Number of colors are limited, but we can combine them to produce more. Windows defines separate flags for the text and background colors.
I have created two classes text_color and back_color to define mnemonics for colors based on these flags.

class text_color
{
public:
	enum Color
	{
		Black = 0,
		White = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED,
		Blue = FOREGROUND_BLUE,
		Green = FOREGROUND_GREEN,
		Red = FOREGROUND_RED,
		Yellow = FOREGROUND_RED | FOREGROUND_GREEN,
		Magenta = FOREGROUND_RED | FOREGROUND_BLUE,
		LightWhite = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY,
		LightBlue = FOREGROUND_BLUE | FOREGROUND_INTENSITY,
		LightGreen = FOREGROUND_GREEN | FOREGROUND_INTENSITY,
		LightRed = FOREGROUND_RED | FOREGROUND_INTENSITY,
		LightYellow = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
		LightMagenta = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
	};
};

class bg_color
{
public:
	enum Color
	{
		Black = 0,
		White = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED,
		Blue = BACKGROUND_BLUE,
		Green = BACKGROUND_GREEN,
		Red = BACKGROUND_RED,
		Yellow = BACKGROUND_RED | BACKGROUND_GREEN,
		Magenta = BACKGROUND_RED | BACKGROUND_BLUE,
		LightWhite = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY,
		LightBlue = BACKGROUND_BLUE | BACKGROUND_INTENSITY,
		LightGreen = BACKGROUND_GREEN | BACKGROUND_INTENSITY,
		LightRed = BACKGROUND_RED | BACKGROUND_INTENSITY,
		LightYellow = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY,
		LightMagenta = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY,
	};
};

Let's see several examples. The first one, shows how to print text with different colors. Moreover, the colored text is always displayed starting with column 40.

int main()
{
   console con;

   con.SetForeColor(text_color::White);
   con << "Processing with files";
   con.GoToX(40);
   con << "OK" << "n";

   con.SetForeColor(text_color::White);
   con << "Looking for templates";
   con.GoToX(40);
   con.SetForeColor(text_color::LightYellow);
   con << "Not found" << "n";

   con.SetForeColor(text_color::White);
   con << "Creating new account";
   con.GoToX(40);
   con.SetForeColor(text_color::LightRed);
   con << "Failed" << "n";

   return 0;
}

Here is the output for this program

A second example shows how to print numbers starting from 1 to N and back to 1 to form a rhomb.

int main()
{
   console con;

   int depth;
   con << "Depth (1-9)? ";
   con >> depth;

   int middle = 20;
   for(int i = 1; i <= depth; ++i)
   {
      con.GoToX(middle-i+1);
      for(int j = 1; j<=i; ++j)
      {
         con << i << " ";
      }
      con << "n";
   }
   for(int i = depth-1; i >=1; --i)
   {
      con.GoToX(middle-i+1);
      for(int j = 1; j<=i; ++j)
      {
         con << i << " ";
      }
      con << "n";
   }

   return 0;
}

And here is the output, when the selected depth is 9:

The same can be achived using the overloaded operator<< for console_pos.

int main()
{
   console con;

   int depth;
   con << "Depth (1-9)? ";
   con >> depth;

   int x = 20;
   int y = 2;
   for(int i = 1; i <= depth; ++i)
   {
      con << console_pos(x-i+1, y++);
      for(int j = 1; j<=i; ++j)
      {
         con << i << " ";
      }
   }
   for(int i = depth-1; i >=1; --i)
   {
      con << console_pos(x-i+1, y++);
      for(int j = 1; j<=i; ++j)
      {
         con << i << " ";
      }
   }

   return 0;
}

A third and last examples shows how to read a matrix on rows and columns.

int main()
{
   console con;

   int rows;
   int cols;

   con << "rows: "; con >> rows;
   con << "cols: "; con >> cols;

   std::vector< int > numbers;

   for(int i = 0; i < rows; ++i)
   {
      for(int j = 0; j < cols; ++j)
      {
         con.GoTo(j*4, i+2);
         con << "[_]";
      }
   }
   int val;
   for(int i = 0; i < rows; ++i)
   {
      for(int j = 0; j < cols; ++j)
      {
         con.GoTo(j*4+1, i+2);
         con >> val;
         numbers.push_back(val);
      }
   }

   return 0;
}

Of course, this basic_console class does not carry all the possible functionality you can imagine, but it should be good enough for basic operations.

Here is the file with the source code.

, Hits for this post: 9789 .