Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / Win32

JLib - A Windows Console Library

Rate me:
Please Sign up or sign in to vote.
4.64/5 (21 votes)
5 Aug 2011GPL315 min read 110.7K   2.3K   89   40
A console library capable of colored input and output. Includes user definable menus, ASCII character windows, save/restore a screen worth of characters, 256 console color combinations, and a smart coloring.
jlib_test_scn.jpg

Introduction

The JLib library encapsulates the Win32 API functions responsible for the console text formatting. These features include:

  • Output formatting
  • Horizontal & Vertical text wrapping
  • Memory of MRU cursor position and formatting
  • Getting input from the keyboard
  • User defined menus, including standard, windowed, scrolling, and windowed scrolling
  • 256 color palette (4 bits for background, 4 bits for foreground)
  • Character Boxes
  • Windowed Boxes with titles
  • Saving/Restoring a screens worth of characters & formatting
  • Saving/Restoring a portion of the screen's characters & formatting

Scope

This article covers the usage of the JLib library functions only. It is only intended to describe the features it provides and how to use them. It does not explain the fundamentals behind the Windows functions that this library uses.

Background

Five years ago, when I began studying software engineering, I was inspired by a classmate's ability to add color formatting to a text output in a console application in Windows XP. Eventually I learned how to manipulate it myself but it grew tedious having to deal with all the aspects of it. As a result, I created a library of functions that went beyond simply slapping an array of formatted text to the screen.

At the time, I was studying the use of C, C++ and MFC. I was very fond, and still am, of the MFC library, so I wrote some of the code to mimic the way MFC code is shown in the MSDN documents.

Four years later I took another look at the original JLib. I've grown as a developer since I originally wrote it and I was embarrased at how sloppy it was. I decided to give it an overhaul and finally fix the smart color formatting once and for all.

Why is it named JLib? Because I wrote the library, and, my first name begins with the letter J.

Using the Code

This version of JLib compiles with Microsoft Visual Studio .NET 2010. It is possible to compile it in any older version of Microsoft Visual Studio, as far back as 6.0. You'll have to substitute the secure functions, such as _itoa_s, _kbhit, and _getch, to their deprecated versions where needed.

The library is composed of the class ConsoleCore which wraps up console formatting calls in the windows.h header. ConsoleCore is a singleton which is accessed through the ConsoleCore::GetInstance method.

Note: the ConsoleCore is not thread safe!

The library also explicitly uses the Standard Template Library for color formatting, vector, and list containers.

The main points of using this library that this article will cover are:

  • How do I add it to my project?
  • Definitions and Classes
  • How do I print a string
  • How do I print numbers
  • How do I use ConsoleFormat
  • How do I format output
  • How do I read a string from the keyboard
  • How do I read a number from the keyboard
  • How do I draw a character box
  • How do I draw a window character box with/without a title
  • How do I create a menu
  • How do I use a menu
  • How do I save/load/clear portions, or all, of the screen

How do I Add it to My Project?

Place the source code in the appropriate folder within your project folder and include the header:

C++
#include "ConsoleCore.h"

Defintions and Classes

It all begins with the console definitions:

C++
#define MAXSCREENX			(80)						// Standard sized window dimensions
#define MAXSCREENY			(25)
#define SCREEN_BUFFER_SIZE	(MAXSCREENX * MAXSCREENY)
#define BADMENU				(60000)
#define USERESC				(60001)
#define UP_KEY				(72)
#define DOWN_KEY			(80)
#define RETURN				(13)
#define ESCAPE				(27)
#define KB_EXTENDED			(224)						// Returned from kbhit if an extended key is pressed

JLib is based on consoles that are 80x25 characters. Menu functionality operates on the arrow keys, return key, and escape key. JLib also use _kbhit to catch user input while menus or prompts are active.

ConsoleCore handles ouput to the screen and input from the keyboard. Alone it provides basic IO functionality with the keyboard and the screen but allows you control over the formatting and position of the cursor.

The JLib library comes with a handful of classes that use ConsoleCore to handle some more interesting and tedious tasks:

C++
//		ConsoleFormat
//	Contains a bitset of 8 bits that represents the coloring used
//	when writing to the screen.  The bits for coloring, and their
//	order, can be found in the Bit enumeration.  Also provides
//	some predefined colors that are common.
class ConsoleFormat;

//		CharacterBox
//	A class that uses the ConsoleCore to render an ASCII box to the screen.
//  You can specify what color formatting to use for the border and the client.
//  You can set the character that is used to draw the outline of the box.
class CharacterBox;

//		CharacterWindow
//	A CharacterBox with a title.  It has the same properties as CharacterBox
//	but it is drawn differently.  The title portion is encased in its own
//	box.  The title is formated with the client format.
//	You must make sure to make the dimensions of the box large enough
//	to encase the title or the title can overrun the box.
class CharacterWindow : public CharacterBox;

//		ConsoleMenuItem
//	This represents an item in a menu.  Menu items have a text label
// and a userdefined value.  The user defined value is of type DWORD
// so you could potentially store something more meaningful than a 
// number, like a function address.
class ConsoleMenuItem;

//		ConsoleMenu
//	A ConsoleMenu is a collection of items.  Menus can draw themselves
//	and use ConsoleCore.  To launch a menu call Show and then check
//	the return value.  To retreive information from a selected menu item
//	after calling show, call one of the Selected functions.
//	Use the up and down arrow keys to change your selection.  Press
//	enter to make a selection.  Press escape to dismiss the menu.
//	This menu also supports wrapping from top to bottom.
//	You can also set the coloring for menu items.  The regular format
//	is the color used to draw items that are not selected.  The
//	selection format is used on the item that is currently highlighted.
class ConsoleMenu;

//		ScrollingMenu
//	The scrollingMenu functions like the ConsoleMenu except
//	it has the ability to hide some of its items.  This makes the
//	ScrollingMenu ideal when screen real estate is limited.
//	As the user presses the up and down arrows the menu items
//  in "view" will shift automatically.
class ScrollingMenu : public ConsoleMenu;

//		WindowedMenu
//	The windowed menu combines the abilities of a CharacterWindow
//	and a ScrollingMenu.  It will automatically draw a CharacterWindow
//	around itself when shown.
//	WindowedMenus do not have to be scrollable.  You can enable or
//	disable this with the Scrollable function.  When Scrolling is disabled
//	the menu will act like a ConsoleMenu.  When SCrolling is enabled
//	the menu will act like a ScrollingMenu and the size of the CharacterWindow
//	will fit the maxToShow number of items.
//	WindowedMenus have two sets of color formatting.  Format and selectionFormat
//	apply to the items displayed.  WindowColor and clientColor apply to the
//	windowed box.  The title of the window is drawn using the clientColor.
class WindowedMenu : public ScrollingMenu;

How do I Print a String

To print a string, you use one of the ConsoleCore::Print methods.

The signatures look like this:

C++
//		Prints
//	Writes a string to the screen and updates the cursor position.
//	Arguments:
//		string text:	The string to write.  Can contain embedded color codes.
//		BOOL endline:	Whether to move the cursor down and all the way left after writing.
//		ConsoleFormat* color:	The color to use.
//		SHORT x:	Column to write to.
//		SHORT y:	Row to write to.
//	Notes:
//		If color is NULL, the default color is used.
//		If x or y are -1 the current x and/or y value is used.
//		Text can contain color codes to format portions of the screen.
//		Color codes are always in the format of a dollar sign followed by exactly 3 digits (i.e. $007)
//		All text after a color code will be written to the screen in that color until another color
//		code is encountered.
//		Color codes supersede the current default color but do not modify it.
void Prints(string text, BOOL endLine = FALSE, const ConsoleFormat* color = NULL, SHORT x = -1, SHORT y = -1);

Example usage:

C++
ConsoleCore::GetInstance()->Prints("Hello World!",TRUE,NULL,0,0);
ConsoleCore::GetInstance()->Prints("Console output is fun!");

The code above will output...

Hello World!
Console output is fun!

... and the console cursor would be left after the second exclamation mark.

How do I Print Numbers

Printing numbers is identical to printing strings except you pass a number.

C++
//		Printn
//	Writes a number to the screen and updates the cursor position.
//	Arguments:
//		DWORD number:	The value to write.
//		BOOL endline:	Whether to move the cursor down and all the way left after writing.
//		ConsoleFormat* color:	The color to use.
//		SHORT x:	Column to write to.
//		SHORT y:	Row to write to.
//	Notes:
//		If color is NULL, the default color is used.
//		If x or y are -1 the current x and/or y value is used.
void Printn(DWORD number, BOOL endLine = FALSE, ConsoleFormat* color = NULL, SHORT x = -1, SHORT y = -1);

This library also provides a function for printing double precision numbers. Again, it is similar to printing strings and integers but you must take extra care when using it. It uses _gcvt_s to convert the double into a string. However, that function will also cause the exponential notation to be appended to the end of the string conversion if necessary. The signature is explained below, and the meaning of the digits parameter is further explained after.

C++
//		Printd
//	Writes a double to the screen.
//	Arguments:
//		DOUBLE number:	The value to write.
//		int characterLength:	The length of the output.
//		BOOL endline:	Whether to move the cursor down and all the way left after writing.
//		ConsoleFormat* color:	The color to use.
//		SHORT x:	Column to write to.
//		SHORT y:	Row to write to.
//	Notes:
//		If color is NULL, the default color is used.
//		If character length is shorter than what it would take to display the entire double 
//		then the value will be displayed in scientific notation. i.e 9e-004 (or 0.0009).
//		If x or y are -1 the current x and/or y value is used.
void Printd(DOUBLE number, int characterLength, BOOL endLine = FALSE, ConsoleFormat* color = NULL, SHORT x = -1, SHORT y = -1);

FPUs can be fickle. Sometimes you get more precision and sometimes you don't. The double to string conversion may or may not add exponents based on the value you give. Here are a few examples and their outputs, note how in the last example, digits is 4, but the actual length of the converted string is larger:

C++
ConsoleCore::GetInstance()->Printd(2.3449L,2); // "2.3"
ConsoleCore::GetInstance()->Printd(2.39L,2); // "2.4"
ConsoleCore::GetInstance()->Printd(1.001L,4); // "1.001"
ConsoleCore::GetInstance()->Printd(12000L,4); // "1.2e+4

If you plan on working with large numbers, plan on the possibility of the output taking up to 5 more characters in width than the number itself. The value of a double ranges from 2.2250738585072014 E – 308 to 1.7976931348623158 E + 308 according to MSDN 2005 documentation. To get one of those extremes to print, you'd need to specify digits to be atleast 20, but it would still take 25 characters to print it with the exponent appended... then again you could always convert the number to a string yourself and format it however you see fit before printing it with Prints().

How do I Use ConsoleFormat

The ConsoleFormat encapsulates the data in context of output. Technically, 4 bits are for the foreground color, which is the character being displayed, and 4 bits are for the background for a total of 8 bits. The last 3 bits for both represent the Red, Green and Blue components and 1st bit represents the Alpha or Intensity (brightness).

There are several different ways to manipulate a ConsoleFormat object:
The simplest way is to create a format based on the bitwise OR of predefined common colors from the ConsoleFormat::Colors enum. You can do this at construction or through the ConsoleFormat::Color() mutator:

C++
ConsoleFormat ccf = CONSOLECHARFORMAT::BRIGHTBLUE | CONSOLECHARFORMAT::ONYELLOW;
ConsoleFormat ccf2(CONSOLECHARFORMAT::BRIGHTBLUE | CONSOLECHARFORMAT::ONYELLOW);

This creates a format which uses bright blue for the text color, and yellow as the background color. You can also bitwise OR ConsoleFormat objects together, or invoke the unary invert method to get the logically opposite color:

Sometimes you want a color that can't be created out of the predefined colors in the enum. ConsoleFormat provides you with facilitators to help you set specific color bits in the bitset without having to know STL. The ConsoleFormat contains methods which allow you to get or set the value of each bit. The signature of the method which sets the bits is void ConsoleFormat::Set(Bit bit, bool value). The value is assigned to the corresponding bit unless you used some vlaue that doesn't exist in ConsoleFormat::Bit. The value of bit determines whether the value applies to the foreground or the background. Additionally, there is the signature bool ConsoleFormat::Get(Bit bit) for retrieving the value of any bit.

Here are two ways of creating the same color:

C++
ConsoleFormat cf = ConsoleFormat::SYSTEM; // default console color.
ConsoleFormat cf2;
cf2.Set(ConsoleFormat::FRONT_RED,TRUE);
cf2.Set(ConsoleFormat::FRONT_GREEN,TRUE);
cf2.Set(ConsoleFormat::FRONT_BLUE,TRUE);

ConsoleFormat also contains several conversion constructors as well as a conversion from a unsigned char.

How do I Format Output

Here's how to write a string or number to the screen using your custom ConsoleFormat:

C++
ConsoleFormat cfString, cfNumber;
... // set the bits to your liking
ConsoleCore::GetInstance()->Prints("Hello World!",TRUE,&cfString);
ConsoleCore::GetInstance()->Printn(1024,TRUE,&cfNumber);

Sometimes you may want to print a string, but have some portions colored differently from others. One way to do that is to create multiple ConsoleFormats and print each section explicitly like this:

C++
ConsoleFormat red, green, blue;
... // set them accordingly
ConsoleCore::GetInstance()->Prints("Red ",FALSE,&red);
ConsoleCore::GetInstance()->Prints("Green ",FALSE,&green);
ConsoleCore::GetInstance()->Prints("Blue",FALSE,&blue);

That can quickly become a pain. I gave the ConsoleCore the ability to parse text passed to Prints for just that reason. Instead of writing the code above, you can do this...

C++
cConsoleCore::GetInstance()->Prints("$004Red $002Green $001Blue");

... and get the same result.

Facilitators of ConsoleCore scan your string and pick up all of the $### portions. The format that was retrieved is used to color all text up until the next $### format code. Unfortunately this does not work with Printn(), as it takes a DWORD and not a string. Codes must be exactly 3 digits in length and begin with '$'.

You should also be careful when including numbers within your string while trying to take advantage of this feature:

C++
ConsoleCore::GetInstance()->Prints("I have $$002000 dollars!")

... displays "I have $000 dollars!" with "000 dollars!" in green on black format. The following might be unexpected as well:

C++
console.Prints("I have $$2000 dollars!")

... which displays "I have $0 dollars!" with "$000 dollars!" in grey on red format.

If the intent were to write "I have $2000 dollars!" to the screen with "$2000" in green on black format, and everything after that in standard white on black, the effective way to do this would be:

C++
ConsoleCore::GetInstance()->Prints("I have$002 $$0022000 $007dollars!",TRUE);

How do I Read a String from the Keyboard

The ScanString() method does just that, and its signature looks like this:

C++
//		ScanString
//	Reads input as a string from the keyboard.
//	Arguments:
//		COORD origin:	Where the prompt is placed.
//		char* buffer:	Out parameter to collect the input.
//		UINT maxLength:	Maximum amount of characters to be entered.
//	Notes:
//		maxLength should be 1 less than the maximum capacity of
//	buffer.
void ScanString(COORD origin, char* buffer, UINT maxLength);

How do I Read a Number from the Keyboard

The ScanNumber() method does just that. It does not allow the user to enter any characters other than a digit or the minus sign, and the minus sign can only be entered as the first character. It optionally allows you to specify the maximum number of digits allowed. You can specify more than 10 digits but a DWORD only needs 10 digits to represent its maximum or minimum value:

C++
//		ScanNumber
//	Reads input as a number from the keyboard.
//	Arguments:
//		COORD origin:	Where the prompt is placed.
//		LPDOWRD lpNumber:	Out parameter to collect the input.
//		int digitCount:	Maximum number of digits allowed.
//	Notes:
//		The minus sign can be used as the first character and does not count toward the limit
//		set by digitCount.
//		The range value of a DWORD is [-2147483648,2147483647]. If you enter a digit above 
//		or below that value, say 99999999999 to -9999999999, it will be clamped 
//		automatically before given back through lpNumber.
void ScanNumber(COORD origin, LPDWORD lpNumber, int digitCount = 10);

You can also read doubles from the keyboard with this library using ScanDouble() which is explained below:

C++
//		ScanDouble
//	Reads input as a double from the keyboard
//	Arguments:
//		COORD origin: Where the prompt is placed.
//		DOUBLE* pDouble:	Out parameter to collect the input.
//	Notes:
//		Can be entered as a typical floating point number (12.345)
//	or as scientic notation (3.2e-4).
//  The range of a double, according to MSDN 2005 documentation, 
//     is 2.2250738585072014 E – 308 to 1.7976931348623158 E + 308.
// If you enter a digit outside of the range you may not get the desired result.  
// Additionally, because FPUs are fickle
// the number you enter may not always be the precisely the one 
// that is returned through the out parameter.
void ScanDouble(COORD origin, DOUBLE* pDouble);

You can enter a double in various formats, e.g. "1.01", "0.1", ".1", even "1243.2e+001" and "23.09e-203". If you are going to use E during input, it must be followed by + or -, or you will not be permitted to input the exponential portion. And the function is case insensitive.

How do I Draw a Character Box

CharacterBox and CharacterWindow are objects that represent ASCII boxes.

CharacterBox has two COORD structures which define the upper left (also the origin) and the lower right corners. It also has two ConsoleFormat members which are used to define the coloring of the border and client (inside) portions. You can also specify the character that is used to draw the outline. This character is the fill character. A box can draw itself using the Draw method. The CharacterBox also contains a static Draw method that will make a temporary box and draw it. The only difference is that the static version will always have a ConsoleFormat::BLACK client area and uses the ConsoleFormat::SYSTEM color for the border. Instances of CharacterBox will automatically normalize their corners. This normalization ensures that the corners are within the 80x25 character dimensions of a console window. However, this method does not ensure that the upper left corner truely is above and to the left of the bottom right corner.

The CharacterWindow class is a child of CharacterBox. It has an extra string member for the title and it varies in how it draws. It creates two instances of the parent class when drawn. One is used to draw the top box which is 1 line tall and will have the title drawn in it. The second box is the client area. The color formatting is essentially the same, except the window's title is drawn using the client format. If you create your own CharacterWindow object you should take care that its width is at least the title string's length + 2. If you don't, the title may draw outside of the box.

Here is how you draw a box that encompasses the entire screen using the static method:

C++
COORD upperLeft,
      lowerRight;
char fill = '*';
upperLeft.X = upperLeft.Y = 0;
lowerRight.X = MAXSCREENX - 1;
lowerRight.Y = MAXSCREENY - 1;
CharacterBox::Draw(upperLeft,lowerRight,fill);

Of course, you may find yourself wanting to draw a box with a specific formatting for both the border and client area, and reuse it in:

C++
//Include code above
CharacterBox box(upperLeft,lowerRight,ConsoleFormat::BRIGHTWHITE,~ConsoleFormat::BRIGHTWHITE);
box.Draw();

How do I Draw a Window Character Box with/without a Title

Here's an example of using a CharacterWindow object. Notice how the dimensions specified apply to the ENTIRE area of the box, not just the client area.

C++
ConsoleCore* pCore = ConsoleCore::GetInstance();
char* title = "example";
COORD ul = {31,0}
	  ,br = {37,6};
ConsoleFormat client = ConsoleFormat::BRIGHTYELLOW
	,old = pCore->Color();
CharacterWindow window(ul,br,title);
window.ClientColor(client);
window.Draw();	// The first box is too skinny for the title!

ul.X = 39;
br.X = ul.X + strlen(title) + 2;
window.UpperLeft(ul);
window.LowerRight(br);
// +1 for the left side of the box
// +1 for the right side of the box
window.Draw();

And the output looks something like this:

......   .........
.example .example.
......   .........
.    .   .       .
.    .   .       .
......   .........

CharacterWindow will not try to center the title text. If you desire that, you may find drawing two boxes and then the title, each manually, will work.

How do I Create a Menu

One of the most annoying things about console programming is menus. Without direct contact with the screen, your options are rather limited. Here is one example of what we might do to create a console menu:

C++
char ch;
do
{
    printf("Choose an option\n");
    printf("(C)reate\n");
    printf("(M)odify\n");
    printf("(Q)uit\n");
    scanf("%c",&ch);
    ch = tolower(ch);
    switch(ch)
    {
        case 'c':
        {...}break;
        case 'm':
        {...}break;
        default: break;
    }
}
while(ch != 'q');

Also, whether you choose to use stdio or STL iostream you have to "baby sit" the user in case they give you screwy data. We all know what happens when you don't check your streams... excess data falls through to the next input and the whole application decides to go bananas.

JLib makes console menus an intelligent, elegant (as elegant as a console app can be) experience and using them is a breeze. They start with user defined ConsoleMenuItems. A ConsoleMenuItem is a text label with a value. When creating your menus you specify the origin, the color format for the currently selected item, and the color format for all other items. All of the menus in JLib offer several methods for inserting and appending menu items. Menus also provide the ability to remove all items.

For the most part, menus in JLib are idiot proof from the user's perspective. Because only arrow, enter, and escape keys are used to make a selection, it is impossible to get bad data back unless your menu was created with no items. The user presses up or down to move to a different menu item and presses enter to make a selection. Also, if the user presses the escape key, a value defined as USERESC is returned. It's provided to you as an alternative method to detect whether a user wanted to "cancel" making a selection or that wanted to dismiss the menu.

There are three types of menus: ConsoleMenu, ScrollingMenu, and WindowedMenu. The last type has two modes which are scrollable and non-scrollable. Here are examples of creating each type:

C++
COORD origin = {31,0};
ConsoleFormat ccfRed = ConsoleFormat::BRIGHTRED
	,ccfOld;
// Create a ConsoleMenu
ConsoleMenu menu(origin);
// There are 2 other methods for appending items.
// These other methods exist for all menu types.
menu.Append("Menu Item 1",0);
menu.Append("Menu Item 2",0);
menu.Append("Menu Item 3",0);

// Create a Scrollable Menu
ScrollingMenu menu(origin,4,ccfRed,~ccfRed);
menu.Append("Menu Item 1",0);
menu.Append("Menu Item 2",1);
menu.Append("Menu Item 3",2);
menu.Append("Menu Item 4",3);
menu.Append("Menu Item 5",4);
menu.Append("Menu Item 6",5);
menu.Append("Menu Item 7",6);
menu.Append("Menu Item 8",7);

// Create a Windowed Menu that doesn't support scrolling
COORD origin = {31,0};	
WindowedMenu menu(origin,4,"Wnd Menu"); 
// The construct allows the setting of the window color and client color
// but this is to demonstrate that you can change the formatting of menus
// after creation.
menu.WindowColor(ConsoleFormat::BRIGHTBLUE);
menu.ClientColor(ConsoleFormat::ONYELLOW);
menu.Append("Menu Item 1",0);
menu.Append("Menu Item 2",1);
menu.Append("Menu Item 3",2);
menu.Append("Menu Item 4",3);
menu.Append("Menu Item 5",4);
menu.Append("Menu Item 6",5);
menu.Append("Menu Item 7",6);
menu.Append("Menu Item 8",7);
menu.Scrollable(FALSE);

// Create a Windowed Menu that supports scrolling
// ... same as Creating a windowed menu but...
menu.Scrollable(TRUE);

How do I Use a Menu

All menus have a method called Show(). Here is an example of generic usage:

C++
// Assuming you've made some menu properly and it is called menu.
switch(menu.Show())
{
	case USERESC:
		//When escape is pressed...
	break;
	case BADMENU:
		//When the menu has no items...
	break;
	default:
		ConsoleMenuItem selection = menu.SelectedItem();
		// You can access the Text() and Value() members of selection now.
	break;
}

You must take care when working with scrollable menus. One of the members of these types of menus is the amount of items that are visible at one time. If you set this value greater than or equal to the number of items in the menu then the behavior of Show() is undefined. In the case of a WindowedMenu, if you have set Scrollable(FALSE) then you don't have to worry about this problem.

That's all there is to it. Each type of menu draws and behaves slightly different but implemented basic polymoprhism in the Show() method. Also, take advantage of the fact that ConsoleMenuItems have user defined values associated with them that are the size of a DWORD. You could design a system where you treat those values as addresses!

How do I Save/Load/Clear Portions or All of the Screen

ConsoleCore has a couple of handy methods for these situations. You can clear the entire screen by using ClearScreen(), which wipes out all text and formatting. This also puts the cursor back in the upper left corner.

From time to time, you may find it useful to save some or all of the screen in order to use it later. The function SaveScreen() does this and it has two overloads. Their signatures look like this:

C++
//		SaveScreen
//	Copies the contents of the entire screen into an internal buffer.
//  The dimensions of the buffer are defined by SCREEN_BUFFER_SIZE.
void SaveScreen();

//		SaveScreen
//	Copies a rectangular area of the screen into a user defined buffer.
//	Saving portions of the screen outside of MAX_SCREEN_X and MAX_SCREEN_Y
//	is undefined.
//	Arguments:
//		PCHAR_INFO buffer:	User defined CHAR_INFO buffer.
//		COORD bufferSize:	Dimensions of the buffer.
//		COORD saveOrigin:	The upper left corner of the area to copy from the screen.
void SaveScreen(PCHAR_INFO buffer, COORD bufferSize, COORD saveOrigin);

Here are some important things to note about the second signature. You are responsible for allocating the appropriate memory for buffer as well as destroying it. Allocate it as a single dimension array with enough elements to encompass the width and height of the area you want to capture. The low level functions treat it as a 2D array and you must provide the height and width. If you wonder why bufferSize is a COORD, rather than a SIZE, structure, well that's what the low level API function wanted for the argument and I'm not going to fight it.

Once you've saved your screen, or portions, you can load them back on to the screen using LoadScreen() which also has two overloads similar to the related save functions:

C++
//		LoadScreen
//	Copies the internal buffer to the screen.
void LoadScreen();

//		LoadScreen
//	Copies a user defined buffer to the screen
//	Arguments:
//		PCHAR_INFO buffer:	User defined CHAR_INFO buffer.
//		COORD bufferSize:	Dimensions of the buffer.
//		COORD loadOrigin:	The upper left corner of the screen to begin the copy.
void LoadScreen(PCHAR_INFO buffer, COORD bufferSize, COORD loadOrigin);

Saving and loading the screen are used internally by the provided menus to prevent some of the flicker that occurs when scrolling a menu. They may or may not be useful but they are provided for those who can think of other reasons to use them. For an example of saving and loading portions of the screen, refer to the CustomBuffer() function in the testharness.cpp of the source.

History

  • 1st April, 2008
    • Initial release
  • 3rd April, 2008
    • Fixed screen position problems with the demo app
  • 4th April, 2008
    • Menus
      • Using menus no longer modifies the internal buffer that is used by the parameterless versions of SaveScreen() and LoadScreen()
      • Implemented saving/loading of portions of the screen which has greatly reduced flickering during menu selection
      • Removed redundancies in WindowedMenuBox and WindowedScrollMenuBox
    • Input
      • Improved ScanNumber. It no longer accepts invalid characters and can be restricted to only allowing a specified number of digits to be entered.
      • Doubles can now be read from the keyboard using ScanDouble()
    • Output
      • Doubles can now be written to the screen using Printd()
  • 14th April, 2008
    • Output
      • Prints() now functions correctly while containing $### smart coloring regardless of whether the string is const
  • 5th August, 2011
    • Output
      • Fixed the $### formatting once and for all. Now it should work 100% of the time.
    • Library
      • Destroyed JLib. Broke it up into smaller parts and distributed the work load to other objects.
      • ConsoleCore is now responsible for writing simple data and reading input from the keyboard.
      • ConsoleFormat replaced CONSOLECHARFORMAT.
      • Added ConsoleMenuItem, ConsoleMenu, ScrollingMenu, and WindowedMenu.
      • Added CharacterBox and CharacterWindow.
      • ConsoleCore is no longer responsible for the creation or destruction of these new objects.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer
United States United States
Graduated from Benson Polytechnic High School with honors in 2001 majored in Computer Software Engineering Technology. Bachelor degree in Software Engineering Technology at Oregon Institute of Technology (2011). 6-12 years of experience in all languages with the letter C (excluding Cobalt, Visual Basic, and Cocoa).

Other hobbies are acoustic guitar, electronic gaming, biking, and teaching.

Comments and Discussions

 
QuestionWhere is the demo project? Pin
John Dovey26-Dec-20 6:24
John Dovey26-Dec-20 6:24 
QuestionMissing file Pin
John Dovey26-Dec-20 6:22
John Dovey26-Dec-20 6:22 
GeneralNice! Pin
x0n2-Jul-13 16:52
x0n2-Jul-13 16:52 
GeneralRe: Nice! Pin
Pepsibot3-Jul-13 14:35
Pepsibot3-Jul-13 14:35 
Thanks I appreciate it. Looking back at this and comparing it to how it is so much more easily done in C# makes me laugh, too. At the time it was nice to have. Now it's really just a silly old relic. But I hope it helps folks who don't have the luxury or option to use current technology.
Knowing what not to do is important, too. Eventually, you'll be left solely with solutions.

GeneralMy vote of 5 Pin
i7cppDave6-Mar-13 4:45
i7cppDave6-Mar-13 4:45 
GeneralMy vote of 5 Pin
Sharjith18-Mar-12 4:17
professionalSharjith18-Mar-12 4:17 
GeneralMy vote of 5 Pin
Jamming15-Aug-11 18:26
Jamming15-Aug-11 18:26 
QuestionFeature Request:: cut and paste through the clipboard Pin
Jamming15-Aug-11 17:13
Jamming15-Aug-11 17:13 
AnswerRe: Feature Request:: cut and paste through the clipboard Pin
Pepsibot5-Aug-11 17:47
Pepsibot5-Aug-11 17:47 
GeneralRe: Feature Request:: cut and paste through the clipboard Pin
Jamming15-Aug-11 18:24
Jamming15-Aug-11 18:24 
GeneralRe: Feature Request:: cut and paste through the clipboard Pin
Pepsibot6-Aug-11 19:15
Pepsibot6-Aug-11 19:15 
GeneralRe: Feature Request:: cut and paste through the clipboard Pin
Jamming17-Aug-11 10:54
Jamming17-Aug-11 10:54 
GeneralRe: Feature Request:: cut and paste through the clipboard Pin
Pepsibot7-Aug-11 19:03
Pepsibot7-Aug-11 19:03 
GeneralRe: Feature Request:: cut and paste through the clipboard Pin
Jamming17-Aug-11 19:55
Jamming17-Aug-11 19:55 
GeneralRe: Feature Request:: cut and paste through the clipboard [modified] Pin
Pepsibot8-Aug-11 17:32
Pepsibot8-Aug-11 17:32 
NewsPre compiled Headers (stdafx.h) [modified] Pin
Pepsibot16-Aug-08 12:47
Pepsibot16-Aug-08 12:47 
NewsIMPORTANT - Unicode and MBCS Character set work arounds Pin
Pepsibot4-Jul-08 13:37
Pepsibot4-Jul-08 13:37 
GeneralSuggestions (If you have any) Pin
Pepsibot11-Apr-08 12:46
Pepsibot11-Apr-08 12:46 
GeneralRe: Suggestions (If you have any) Pin
NGS 54967215-Apr-08 12:56
NGS 54967215-Apr-08 12:56 
GeneralRe: Suggestions (If you have any) Pin
Pepsibot15-Apr-08 15:12
Pepsibot15-Apr-08 15:12 
GeneralRe: Suggestions (If you have any) Pin
NGS 54967216-Apr-08 4:08
NGS 54967216-Apr-08 4:08 
GeneralRe: Suggestions (If you have any) Pin
NGS 54967217-Apr-08 4:58
NGS 54967217-Apr-08 4:58 
GeneralMore updates on the way Pin
Pepsibot8-Apr-08 14:53
Pepsibot8-Apr-08 14:53 
GeneralRe: More updates on the way Pin
Jeff.Crawford10-Apr-08 7:26
Jeff.Crawford10-Apr-08 7:26 
GeneralRe: More updates on the way Pin
Pepsibot10-Apr-08 10:14
Pepsibot10-Apr-08 10:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.