cConsole class

Controls the console of a program: it writes text in colour, reads lines and keys, moves the cursor, changes the code pages and the virtual-terminal mode, and runs a full-screen mode that draws through a screen buffer and reports keyboard, mouse and window events.

A cConsole works on the standard input, output and error handles of the program, which it asks Windows for when it is created. Nearly every member is a thin layer over one or two functions of the Windows console API, and does not check whether the call worked. Each entry below names the functions it calls.

Dim con As New cConsole
con.EnableUTF8
con.EnableVirtualTerminal

con.Title = "Report"
con.WriteLineColored "Done", ConsoleColor.Green
con.WriteAtColored 0, 2, "caf" & ChrW$(233), ConsoleColor.Yellow
con.WriteLine
con.Restore

In the syntax lines of this page, object is a cConsole. The page uses these terms: the window is the part of the screen buffer that the console window shows, and the screen buffer is the whole grid of character cells that Windows keeps for the console, which can be taller than the window. Columns and rows are counted from 0, and a position is a column and a row, in that order.

Creating a cConsole

A cConsole is created with New. New reads the standard handles and records the state that Restore puts back: the input and output modes, the colour attributes and the two code pages.

The class is predeclared, so the name cConsole can also be used as an object, as in cConsole.WriteLine "Hello", without New.

A program should create one cConsole. Each object records the console state at the moment it is created, and puts that state back when it is restored. A second object created after the first one has changed the modes records the changed modes as the original ones.

The object restores the console when it is destroyed: its terminate event calls Restore. A program that must put the console back at once, for example before it starts another program, calls Restore itself.

Which project it needs

The package is meant for a console application: a project with Is Console Application set to Yes, as the Standard EXE (Console App) template does (see Console Applications). Such a program runs in the Command Prompt window it was started from, or in a console window of its own, and Windows gives it the three standard handles that cConsole uses.

A program with a window and no console can create a cConsole, but every call that reaches Windows fails; see Without a console. Such a program can call AllocConsole, which the module mConsoleAPI declares, before it creates the object: the program then has a console of its own, and the write members show their text in it.

Without a console

The members that read or draw on the console depend on Windows handing the program a console. A program built as a GUI program has no standard handles: GetStdHandle returns 0 for all three, and Windows refuses each console call that cConsole makes.

The class checks the result of two functions only. EnableVirtualTerminal returns False when SetConsoleMode fails for the output handle, and New, Clear, ClearLine, GetSize, GetBufferSize and GetCursorPosition look at the result of GetConsoleScreenBufferInfo. Every other call is unchecked: a failed call raises no error, changes nothing, and leaves the value it should have filled in at its starting value, which is 0, False or an empty string. The table lists what a program without a console sees.

Member Without a console
New Succeeds. The size is taken as 80 columns by 25 rows, and the original colours as Gray on Black.
WriteTo and the other write members Write nothing.
Width, Height, GetSize 80 and 25.
GetBufferSize 80 by 300.
GetCursorPosition Column 0, row 0.
CursorVisible, CursorSize False and 0.
Title An empty string.
WindowHandle 0.
InputCodePage, OutputCodePage 0.
EnableVirtualTerminal False.
ReadLine An empty string, at once.
KeyAvailable, PeekEvent False, and an empty ConsoleKeyInfo.
ReadKeyTimeout Returns the empty structure when the time is over.
ReadKey, ReadPassword Do not return; see Known problems.
EnterFullScreenMode Creates the 80 by 25 cConsoleBuffer; Refresh writes nothing.
IsKeyPressed Works, since it does not use the console.

A buffer made by EnterFullScreenMode is an ordinary in-memory grid, so a program without a console can still draw into it and read the cells back with GetChar.

Redirected input and output

A console application can also have its output sent to a file or a pipe (mytool > out.txt) or its input read from one. The members write and read with WriteConsoleW, ReadConsoleW and ReadConsoleInputW, which work only on a console handle. With the output redirected, the write members therefore write nothing: after WriteLine and WriteErrorLine the files are empty. They raise no error, since they do not check the result; the template’s Console.WriteLine raises error 5 in the same case (see Writing a command-line tool). The members that need a screen buffer fail as they do without a console: GetSize gives 80 by 25 and EnableVirtualTerminal returns False.

A program that must work with redirected output writes with WriteFile in that case, as the page cited above shows, and uses cConsole only when the handles are console handles.

With the input read from the null device or from a file, ReadLine returns an empty string at once and KeyAvailable is False. ReadKey does not return.

Known problems in version 0.0.0.0

  • KeyAvailable and the key-up events. KeyAvailable is true while the input queue holds any event, including the event for a key that was released, so a loop that tests it and then calls ReadKey can block in ReadKey until the next key press.
  • The colours of the Write members. WriteColored, WriteLineColored and WriteAtColored use a black background unless one is given, and put back the colours that the object tracks, which are Gray on Black until a property sets others, and not the colours that the console had.
  • Full-screen drawing. Refresh writes the buffer at the top left of the screen buffer, not of the window; see EnterFullScreenMode. A negative column or row in the buffer’s dirty rectangle makes the next Refresh draw nothing; see The dirty rectangle.
  • The handlers. A handler set with OnCtrlEvent cannot be removed again, and the compiler refuses 0 and Nothing for the other three handler properties, so none can be cleared.
  • The resize sizes. OnResize is given the size of the screen buffer, and not of the window that Width and Height report.

Constructor

New

Creates a cConsole and records the state of the console.

Syntax: New cConsole [ ( inputBufferSize ) ]

inputBufferSize
optional A Long, the number of characters that ReadLine can read in one call. The default is 4096.

The constructor asks Windows for the three standard handles and for the console window, saves the input and output modes, the colour attributes, the width of the screen buffer and the height of the window, and the two code pages, and sets the tracked colours to Gray on Black. A negative inputBufferSize raises error 5, Invalid procedure call or argument, since the constructor makes the read buffer with String$.

Calls GetStdHandle (three times), GetConsoleWindow, GetConsoleMode (twice), GetConsoleScreenBufferInfo, GetConsoleCP and GetConsoleOutputCP. Without a console, the size is taken as 80 by 25 and the original colours as Gray on Black.

Properties

BackColor

The background colour that the object tracks, and that the write members use. A ConsoleColor.

Syntax: object.BackColor [ = value ]

value
A ConsoleColor.

Setting the property stores the value and applies the pair of ForeColor and BackColor to the console. Reading it returns the stored value, which is Black at the start, and not a colour read from the console.

Calls SetConsoleTextAttribute when it is set. Without a console, nothing is applied.

Buffer

The screen buffer of the full-screen mode. A cConsoleBuffer, read-only.

Syntax: object.Buffer

Returns the buffer that EnterFullScreenMode made, and Nothing when the object is not in full-screen mode. A component object of the ConsoleComponents package keeps the buffer that this property returned when it was created, so it must be created after EnterFullScreenMode.

CursorSize

The height of the cursor, as a percentage of the character cell. Long, read/write.

Syntax: object.CursorSize [ = value ]

value
A Long. A value below 1 is stored as 1, and a value above 100 as 100.

Calls GetConsoleCursorInfo, and SetConsoleCursorInfo when it is set. Without a console, reading it gives 0.

CursorVisible

Whether the cursor is shown. Boolean, read/write.

Syntax: object.CursorVisible [ = value ]

value
A Boolean.

Reading the property asks the console each time. EnterFullScreenMode hides the cursor and ExitFullScreenMode shows it, whatever it was before.

Calls GetConsoleCursorInfo, and SetConsoleCursorInfo when it is set. Without a console, reading it gives False.

ForeColor

The text colour that the object tracks, and that the write members use. A ConsoleColor.

Syntax: object.ForeColor [ = value ]

value
A ConsoleColor.

Works as BackColor. The stored value is Gray at the start. Calls SetConsoleTextAttribute when it is set.

FPS

An estimate of the frames drawn per second. Double, read-only.

Syntax: object.FPS

The value is the number of calls of Refresh and RefreshAll since the start of the current count, multiplied by 1000 and divided by the milliseconds since then. It is 0 before the first call. Refresh starts a new count when it finds that a second has passed since the start of the count, and RefreshAll only adds to the count, so a program that calls only RefreshAll gets the average since its first call. When the program stops drawing, the value falls, since the time keeps running. The clock is GetTickCount, whose steps are about 15 milliseconds.

FullScreenMode

Whether the object is in full-screen mode. Boolean, read-only.

Syntax: object.FullScreenMode

True between EnterFullScreenMode and ExitFullScreenMode.

Height

The number of rows of the console window. Long, read-only.

Syntax: object.Height

The height of the window, and not of the screen buffer; GetBufferSize returns that. Each read calls GetSize. Without a console it is 25.

InputCodePage

The code page that the console uses for input. Long, read/write.

Syntax: object.InputCodePage [ = value ]

value
A Long, a code page number such as 65001 for UTF-8.

Calls GetConsoleCP, and SetConsoleCP when it is set. A value that Windows refuses is ignored without an error. Restore and DisableUTF8 put back the code page that the console had when the object was created. Without a console, reading it gives 0.

LastRenderTime

The time that the last Refresh or RefreshAll took, in milliseconds. Long, read-only.

Syntax: object.LastRenderTime

The value is the difference of two GetTickCount readings, so it is a multiple of the clock step, about 15 milliseconds, and is often 0 for a small draw. It is 0 until the first draw.

OnCtrlEvent

Sets the procedure that Windows calls when the user presses Ctrl+C or Ctrl+Break, closes the console window, logs off or shuts down. Write-only.

Syntax: object.OnCtrlEvent = handler

handler
A ConsoleCtrlHandler, the address of a procedure of a module with one Long parameter that returns a Long, as in con.OnCtrlEvent = AddressOf CtrlHandler.

The procedure receives the kind of event in ctrlType, one of the constants CTRL_C_EVENT (0), CTRL_BREAK_EVENT (1), CTRL_CLOSE_EVENT (2), CTRL_LOGOFF_EVENT (5) and CTRL_SHUTDOWN_EVENT (6) of the module mConsoleAPI. It returns a non-zero value to say that it handled the event, and 0 to pass the event to the next handler; the default handler of Windows ends the program.

Public Function CtrlHandler(ByVal ctrlType As Long) As Long
    If ctrlType = CTRL_C_EVENT Then
        CtrlHandler = 1        ' handled: the program goes on
    End If
End Function

Public Sub Setup(ByVal con As cConsole)
    con.OnCtrlEvent = AddressOf CtrlHandler
End Sub

Windows calls the procedure on a thread of its own, not on the thread that runs the program, so it should do little: set a flag that the main loop reads.

The property registers the address with SetConsoleCtrlHandler. The registration is not removed again: assigning another procedure adds a second registration and leaves the first, Restore does not remove it, and the code never calls SetConsoleCtrlHandler with the remove option. ProcessEvents does not call the procedure; only Windows does.

OnKeyPress

Sets the procedure that ProcessEvents calls for each key that is pressed. Write-only.

Syntax: object.OnKeyPress = handler

handler
A ConsoleKeyHandler, the address of a procedure of a module with the parameters ByRef keyInfo As ConsoleKeyInfo, ByRef handled As Boolean.

ProcessEvents calls the procedure once for each key-down event, with the key in keyInfo, including the keys that are only modifiers, such as Shift. The key-up events are not passed. The value that the procedure stores in handled is not read. While no handler is set, ProcessEvents leaves the key events in the queue, so that ReadKey and ReadLine can read them. Once a handler is set it cannot be removed: the compiler refuses 0 and Nothing for the property.

Public Sub OnKey(ByRef keyInfo As ConsoleKeyInfo, ByRef handled As Boolean)
    If keyInfo.IsCtrlPressed And keyInfo.KeyCode = vbKeyQ Then
        handled = True
    End If
End Sub

Public Sub Setup(ByVal con As cConsole)
    con.OnKeyPress = AddressOf OnKey
End Sub

OnMouseClick

Sets the procedure that ProcessEvents calls for each mouse event. Write-only.

Syntax: object.OnMouseClick = handler

handler
A ConsoleMouseHandler, the address of a procedure of a module with the parameters ByRef mouseInfo As ConsoleMouseInfo, ByRef handled As Boolean.

Setting a handler also changes the input mode of the console: it turns on mouse input, turns on the extended flags, and turns off quick-edit mode, so that the console passes mouse events to the program instead of selecting text with them. DisableVirtualTerminal and Restore put the original mode back, and so does ExitFullScreenMode while the full-screen mode is on.

Despite the name, the procedure is called for every mouse event: a move, a button press, a button release and a turn of the wheel, as well as a double click. mouseInfo holds the position in Col and Row, the buttons that are down in Button (a bit mask of the Windows dwButtonState field: 1 for the left button, 2 for the right button, and 0 when none is down), and IsDoubleClick, which is true when the event carries the double-click flag. The program has to compare Button with its previous value to find a click.

OnResize

Sets the procedure that ProcessEvents calls when the size of the console changes. Write-only.

Syntax: object.OnResize = handler

handler
A ConsoleResizeHandler, the address of a procedure of a module with the parameters ByVal newWidth As Long, ByVal newHeight As Long.

Windows reports a change of the size only while the input mode has the window-input flag, which EnterFullScreenMode turns on and nothing else in the class does. Outside full-screen mode the handler is not called. When an event arrives and the size differs from the one the object last saw, the object resizes its buffer to it, which discards the contents of the buffer, and then calls the handler; the program draws the buffer again.

The two numbers are copied from the event record, which holds the new size of the screen buffer. They are not read from the window, whose size Width and Height report, and the two can differ, since the screen buffer can be taller than the window.

OutputCodePage

The code page that the console uses for output. Long, read/write.

Syntax: object.OutputCodePage [ = value ]

value
A Long, a code page number such as 65001 for UTF-8.

Works as InputCodePage, with GetConsoleOutputCP and SetConsoleOutputCP.

Title

The title of the console window. String, read/write.

Syntax: object.Title [ = value ]

value
A String.

Reading it returns up to 259 characters. Calls GetConsoleTitleW, and SetConsoleTitleW when it is set. Without a console, reading it gives an empty string and setting it does nothing.

VirtualTerminalEnabled

Whether EnableVirtualTerminal turned the virtual-terminal mode on. Boolean, read-only.

Syntax: object.VirtualTerminalEnabled

The value comes from the object and not from the console. It is False when the console had the mode on already, until the program calls EnableVirtualTerminal.

Width

The number of columns of the console window. Long, read-only.

Syntax: object.Width

The width of the window, and not of the screen buffer. Each read calls GetSize. Without a console it is 80.

WindowHandle

The window handle of the console, as GetConsoleWindow returned it when the object was created. LongPtr, read-only.

Syntax: object.WindowHandle

It is 0 when the program had no console window at that time.

Methods

Beep

Writes the bell character, code 7.

Syntax: object.Beep

The method calls WriteTo with Chr$(7). Whether the console makes a sound, and which, is the console’s choice; the method does not call the Windows Beep function.

CenterRect

Returns a rectangle of a given size, centred in the window.

Syntax: object.CenterRect ( contentWidth , contentHeight ) As ConsoleRect

contentWidth
required A Long, the width in columns.
contentHeight
required A Long, the height in rows.

Returns a ConsoleRect whose Left is CenterX of the width and Top is CenterY of the height, with Right and Bottom set so that it has the given size. A rectangle larger than the window has negative Left and Top. Uses the size of the window, 80 by 25 without a console.

CenterX

Returns the column at which text of a given width is centred in the window.

Syntax: object.CenterX ( textWidth )

textWidth
required A Long, the width in columns.

Returns (Width - textWidth) \ 2, a Long; it is negative when the text is wider than the window.

CenterY

Returns the row at which content of a given height is centred in the window.

Syntax: object.CenterY ( textHeight )

textHeight
required A Long, the height in rows.

Returns (Height - textHeight) \ 2, a Long.

Clear

Fills the screen buffer with spaces in the tracked colours and moves the cursor to the top left.

Syntax: object.Clear

The method fills the whole screen buffer, not only the part that the window shows, with a space in the colours of ForeColor and BackColor, and then moves the cursor to column 0, row 0 of the screen buffer. When the window shows another part of the buffer, the cursor moves out of sight. In full-screen mode it does not clear the Buffer; Clear of the buffer does that.

Calls GetConsoleScreenBufferInfo, FillConsoleOutputCharacterW, FillConsoleOutputAttribute and SetConsoleCursorPosition. Without a console, the first call fails and the method returns at once.

ClearLine

Fills the current line, from the cursor to the end of the line, with spaces in the tracked colours.

Syntax: object.ClearLine

The cursor does not move. Calls GetConsoleScreenBufferInfo, FillConsoleOutputCharacterW and FillConsoleOutputAttribute. Without a console, the method returns at once.

DisableUTF8

Puts back the code pages that the console had when the object was created.

Syntax: object.DisableUTF8

Despite its name, the method does not switch to a particular code page: it sets the input and the output code page to the saved values, whatever they are now. Calls SetConsoleCP and SetConsoleOutputCP.

DisableVirtualTerminal

Puts back the input and output modes that the console had when the object was created.

Syntax: object.DisableVirtualTerminal

The method restores both modes as they were, so it also undoes other changes of the input mode, such as the window input that EnterFullScreenMode turns on and the mouse input that OnMouseClick turns on. It sets VirtualTerminalEnabled to False. Calls SetConsoleMode twice.

DrawBox

Draws a rectangle of line-drawing characters directly on the console.

Syntax: object.DrawBox ( left , top , right , bottom [ , doubleLine ] )

left, top
required Long values, the column and the row of the upper left corner.
right, bottom
required Long values, the column and the row of the lower right corner.
doubleLine
optional A Boolean. True draws with the double-line characters (U+2554, U+2557, U+255A, U+255D, U+2550, U+2551), and False, the default, with the single-line ones (U+250C, U+2510, U+2514, U+2518, U+2500, U+2502).

The box is drawn with WriteAt, in the current colour attributes of the console; the inside is left as it is. right has to be greater than left: for right equal to or less than left the method raises error 5, Invalid procedure call or argument, since the length of the horizontal line is negative, and it raises it after it has written the four corners.

The method draws on the console, not on the full-screen Buffer. To draw a box on the buffer use DrawBox of the buffer, which takes the colours as parameters.

Calls SetConsoleCursorPosition and WriteConsoleW, through WriteAt. A position that is not in the screen buffer is ignored by Windows. Without a console, nothing is drawn.

DrawProgressBar

Draws a bar with a percentage directly on the console.

Syntax: object.DrawProgressBar ( col , row , width , percent [ , usedColor [ , freeColor ] ] )

col, row
required Long values, the column and the row of the left bracket.
width
required A Long, the number of cells between the brackets.
percent
required A Double. A value below 0 is taken as 0, and a value above 100 as 100.
usedColor
optional A ConsoleColor, the colour of the filled part. The default is Green.
freeColor
optional A ConsoleColor, the colour of the empty part. The default is DarkGray.

Writes [, then CLng(percent / 100 * width) full blocks (U+2588) in usedColor, then the rest as light-shade blocks (U+2591) in freeColor, and then ] and the percentage rounded to a whole number with a percent sign. The brackets and the percentage are in the current colour attributes of the console; the blocks have a black background. The whole line is width + 4 cells plus the digits of the percentage. A negative width raises error 5. The cursor is left after the text. The conversion rounds half to even: a width of 10 and 25 percent gives 2 blocks.

Calls SetConsoleCursorPosition and WriteConsoleW. Without a console, nothing is drawn.

EnableUTF8

Sets the input and the output code page of the console to UTF-8, code page 65001.

Syntax: object.EnableUTF8

Calls SetConsoleCP and SetConsoleOutputCP. The write and read members of this class use the wide-character functions of Windows, which do not depend on the code page, so the setting does not change what they put in the screen buffer: a euro sign written with WriteTo is stored as U+20AC with the output code page 437 and with 65001. The setting matters for text that reaches the console in another way, such as the output of a program that this program starts.

The code pages are put back by DisableUTF8 and Restore. Without a console, the calls fail without an error.

EnableVirtualTerminal

Turns on the processing of escape sequences, so that the strings of mConsoleStyle change colours and move the cursor.

Syntax: object.EnableVirtualTerminal As Boolean

Adds ENABLE_VIRTUAL_TERMINAL_PROCESSING to the output mode. When Windows refuses, for example on a system or a console that does not have the mode, or when there is no console, the method returns False and changes nothing else. Otherwise it adds ENABLE_VIRTUAL_TERMINAL_INPUT to the input mode, ignoring whether that call worked, sets VirtualTerminalEnabled and returns True.

ReadKey is not affected by the input flag, since it turns the input mode off while it waits.

The mode is put back by DisableVirtualTerminal and Restore. Calls GetConsoleMode and SetConsoleMode for both handles.

EnterFullScreenMode

Starts the full-screen mode: it makes an in-memory screen buffer of the size of the window, hides the cursor and turns on window input.

Syntax: object.EnterFullScreenMode

The method does nothing when the mode is already on. It creates a cConsoleBuffer with the width and height of the window, which Buffer returns; sets CursorVisible to False; and adds ENABLE_WINDOW_INPUT to the input mode, so that Windows reports a change of size.

Despite the name, the window is not enlarged, the console does not switch to an alternate screen buffer, and the text that is on the screen is neither saved nor cleared. The program draws into the buffer with its methods, and Refresh copies the changed cells to the console. ExitFullScreenMode ends the mode and leaves the last picture on the screen.

Refresh writes the cells of the buffer to the rows 0 to Height - 1 of the screen buffer, from column 0. When the screen buffer is taller than the window and the window shows another part of it, as it does in a classic console window that has scrolled, the picture is drawn out of sight.

Calls GetConsoleScreenBufferInfo, GetConsoleCursorInfo, SetConsoleCursorInfo, GetConsoleMode and SetConsoleMode. Without a console, the buffer is 80 by 25.

Private m_Running As Boolean

Public Sub OnKey(ByRef keyInfo As ConsoleKeyInfo, ByRef handled As Boolean)
    If keyInfo.KeyCode = ConsoleKey.KeyEscape Then m_Running = False
End Sub

Public Sub RunDemo()
    Dim con As New cConsole
    Dim n As Long

    con.OnKeyPress = AddressOf OnKey
    con.EnterFullScreenMode
    m_Running = True

    Do While m_Running
        con.ProcessEvents
        n += 1
        con.Buffer.Clear
        con.Buffer.WriteAt 2, 1, "Press Escape to quit. Frame " & n, ConsoleColor.Yellow, ConsoleColor.Black
        con.Refresh
        mConsoleAPI.Sleep 30
    Loop

    con.ExitFullScreenMode
    con.Restore
End Sub

ExitFullScreenMode

Ends the full-screen mode.

Syntax: object.ExitFullScreenMode

The method does nothing when the mode is off. It releases the buffer, so that Buffer returns Nothing again, shows the cursor, and sets the input mode to the one saved when the object was created, which also turns off the mouse input that OnMouseClick turned on. An object that was made with the old buffer, such as a component of the ConsoleComponents package, still holds it, and the console no longer shows it. The screen is not cleared. Calls SetConsoleMode and SetConsoleCursorInfo.

FlushInput

Discards the events that are waiting in the input queue.

Syntax: object.FlushInput

All events are discarded: keys, mouse events and size events. Calls FlushConsoleInputBuffer.

GetBufferSize

Returns the size of the screen buffer.

Syntax: object.GetBufferSize As ConsoleSize

Returns a ConsoleSize with the columns and rows of the whole screen buffer, which can be larger than the window. Calls GetConsoleScreenBufferInfo. Without a console, it is 80 by 300.

GetCursorPosition

Returns the position of the cursor.

Syntax: object.GetCursorPosition As ConsolePosition

Returns a ConsolePosition. The column and the row are counted from the top left of the screen buffer, not of the window. Calls GetConsoleScreenBufferInfo. Without a console, it is column 0, row 0.

GetSize

Returns the size of the console window.

Syntax: object.GetSize As ConsoleSize

Returns a ConsoleSize with the columns and rows of the window, from the window rectangle that Windows reports. Width and Height return its two fields. Calls GetConsoleScreenBufferInfo. Without a console, it is 80 by 25.

IsKeyPressed

Tells whether a key is down at this moment.

Syntax: object.IsKeyPressed ( keyCode ) As Boolean

keyCode
required A Long, a Windows virtual-key code, such as 27 for Escape or 38 for the Up Arrow.

Returns True when the most significant bit of the result of GetAsyncKeyState is set. The function asks Windows for the state of the keyboard, so it does not read the console’s input queue, does not remove any event from it, and does not depend on which window has the focus. It works without a console.

KeyAvailable

Tells whether the input queue holds an event.

Syntax: object.KeyAvailable As Boolean

Returns True when the queue holds one or more events. The queue holds every kind of input: key presses and key releases, mouse events, focus events and size events, so a True result does not mean that a key is waiting. After a key is read, the event for its release is still in the queue, and KeyAvailable is true until a following ReadKey or FlushInput removes it.

Calls GetNumberOfConsoleInputEvents. Without a console, it returns False.

PeekEvent

Returns the first event in the queue, when it is a key press, without removing it.

Syntax: object.PeekEvent As ConsoleKeyInfo

Returns the ConsoleKeyInfo of the first event when that event is a key-down event. For any other first event, a key release, a mouse event or an empty queue, it returns an empty structure: KeyCode 0 and an empty KeyChar. It does not look past the first event. Calls PeekConsoleInputW.

PercentX

Returns the column that lies a given percentage across the window.

Syntax: object.PercentX ( percent )

percent
required A Double. A value below 0 is taken as 0, and a value above 100 as 100.

Returns CLng(Width * percent / 100), a Long, rounded half to even.

PercentY

Returns the row that lies a given percentage down the window.

Syntax: object.PercentY ( percent )

percent
required A Double. A value below 0 is taken as 0, and a value above 100 as 100.

Returns CLng(Height * percent / 100), a Long.

ProcessEvents

Reads the events in the input queue and calls the handlers.

Syntax: object.ProcessEvents

A full-screen program calls this method once in each pass of its main loop. It takes the events from the queue in order, while the queue is not empty, and treats each by its kind.

Event Handling
Size change Always taken from the queue. It resizes the full-screen buffer and calls OnResize, as described there.
Key Taken from the queue and passed to OnKeyPress when a key handler is set. Without a handler the method stops at once and leaves this event and everything behind it in the queue.
Mouse Taken from the queue, and passed to OnMouseClick when a mouse handler is set.
Any other Taken from the queue and dropped.

A program that wants to read keys with ReadKey or ReadLine therefore sets no key handler. A queue that holds a key event for which nobody asks stops the processing of the size and mouse events behind it.

The method calls GetNumberOfConsoleInputEvents (through KeyAvailable), PeekConsoleInputW and ReadConsoleInputW. Without a console, KeyAvailable is False and nothing happens.

ReadKey

Waits for a key press and returns it.

Syntax: object.ReadKey [ ( intercept ) ] As ConsoleKeyInfo

intercept
optional A Boolean. When it is False, the default, the character of the key is also written to the console. True writes nothing.

Returns a ConsoleKeyInfo for the first key-down event. KeyCode is the Windows virtual-key code, and KeyChar the character of the key, or the character with code 0 when the key has none, such as an arrow key. The three flags say whether Alt, Ctrl and Shift were down. Any key-down event counts, including the keys that are only modifiers, so a press of Shift is returned as KeyCode 16. Other events are taken from the queue and dropped while the method waits, and the release of a key is ignored. A key that is held down gives one result for each repeat.

While it waits, the method sets the input mode to 0 and puts the old mode back before it returns. With no mode flags the console does not echo the key, does not edit a line, and does not turn Ctrl+C into an interruption. When intercept is False the method writes KeyChar itself with WriteTo, even when it is the character with code 0.

Calls GetConsoleMode, SetConsoleMode (twice) and ReadConsoleInputW. Without a console, or with the input redirected, ReadConsoleInputW fails at once and the method never returns; see Known problems.

Dim con As New cConsole
Dim key As ConsoleKeyInfo

con.WriteTo "Press a key: "
key = con.ReadKey(True)
con.WriteLine
con.WriteLine "Key code " & key.KeyCode & ", character " & AscW(key.KeyChar)

ReadKeyTimeout

Waits for a key press for a given time.

Syntax: object.ReadKeyTimeout ( timeoutMs [ , intercept ] ) As ConsoleKeyInfo

timeoutMs
required A Long, the time to wait in milliseconds.
intercept
optional A Boolean, as for ReadKey.

The method asks KeyAvailable every millisecond (it calls Sleep between the asks) until the time is over. As soon as the queue holds any event it returns ReadKey. When the time is over it returns an empty structure, with KeyCode 0.

Since KeyAvailable is true for any event, a pending event that is not a key press, such as a key release, makes ReadKey wait for the next key press with no time limit. Calls GetNumberOfConsoleInputEvents, Sleep, GetTickCount and the functions of ReadKey. Without a console, it returns the empty structure after the time.

ReadLine

Reads a line of text.

Syntax: object.ReadLine [ ( prompt ) ] As String

prompt
optional A String, written with WriteTo before the console reads. The default is an empty string.

Waits in the console’s line mode, with its echo and editing, until the user presses Enter, and returns the text without the carriage return and the line feed (all of them are removed). At most the number of characters of the read buffer (see New) is read in one call. Calls ReadConsoleW. When the console is not in line mode, the result is that of the current mode. Without a console, or with the input redirected, ReadConsoleW fails and the method returns an empty string at once.

Dim con As New cConsole
Dim userName As String

userName = con.ReadLine("Name: ")
con.WriteLineF "Hello, {0}.", userName

ReadPassword

Reads a line of text and shows a mask character for each key.

Syntax: object.ReadPassword ( [ prompt [ , maskChar ] ] ) As String

prompt
optional A String, written before the input. The default is an empty string.
maskChar
optional A String, written once for each character typed. The default is *. An empty string shows nothing.

Reads with ReadKey, with the echo off. Enter ends the input and writes a line break. Backspace takes off the last character of the result and writes a backspace, a space and a backspace, which erases one cell. That is one cell even when maskChar has more than one character, and when maskChar is empty it is a cell of the prompt, since no mask was written. Escape cancels: the method returns an empty string. A key whose character has a code of 32 or more is added to the result and the mask is written. Keys with other characters, such as Tab, and keys without a character are ignored. Without a console it does not return, as ReadKey does not.

Dim con As New cConsole
Dim secret As String

secret = con.ReadPassword("Password: ", "*")
con.WriteLine "Read " & Len(secret) & " characters."

Refresh

Writes the changed part of the full-screen buffer to the console.

Syntax: object.Refresh

In full-screen mode the method calls Flush of the buffer, which writes only the rectangle that has changed since the last write, measures the time for LastRenderTime and updates FPS. Outside full-screen mode it does nothing. Calls WriteConsoleOutputW, with the standard output handle. Without a console, the call fails and nothing is shown.

RefreshAll

Writes the whole full-screen buffer to the console.

Syntax: object.RefreshAll

Like Refresh, but the whole buffer is written, whether or not it has changed. A program uses it after something else has drawn on the screen, for example after an error message, to restore the picture. Outside full-screen mode it does nothing.

ResetColors

Puts back the colour attributes that the console had when the object was created.

Syntax: object.ResetColors

Sets the attributes with SetConsoleTextAttribute and sets ForeColor and BackColor to the colours in the saved attributes (the low four bits, and the next four). Without a console, the saved attributes are Gray on Black.

Restore

Puts the console back as it was when the object was created.

Syntax: object.Restore

The method leaves the full-screen mode if it is on, sets the input mode and the output mode to the saved ones, sets the saved colour attributes, and sets the two saved code pages. It does not clear the screen, and does not put back the cursor size. The object stays usable, and the method can be called again. Calls SetConsoleMode (twice), SetConsoleTextAttribute, SetConsoleCP and SetConsoleOutputCP. The terminate event of the object calls it.

SetBufferSize

Sets the size of the screen buffer of the console.

Syntax: object.SetBufferSize ( width , height )

width, height
required Long values, the columns and rows of the buffer.

A value outside the range of an Integer raises error 6, Overflow. Windows refuses a buffer smaller than the window, and the method does not check. The buffer of full-screen mode is not changed here: it is resized when the size event arrives, which ProcessEvents reads. Calls SetConsoleScreenBufferSize.

SetColors

Sets the text and background colours.

Syntax: object.SetColors ( fore [ , back ] )

fore
required A ConsoleColor, the text colour.
back
optional A ConsoleColor, the background colour. The default is Black, and not the current background.

Stores both values in ForeColor and BackColor, and applies them with SetConsoleTextAttribute.

SetCursorPosition

Moves the cursor.

Syntax: object.SetCursorPosition ( col , row )

col, row
required Long values, the column and the row, counted from the top left of the screen buffer.

A value outside the range of an Integer raises error 6, Overflow. A position outside the screen buffer is refused by Windows, and the method does not check. Calls SetConsoleCursorPosition.

WriteAt

Writes text at a position.

Syntax: object.WriteAt ( col , row , text )

col, row
required Long values, the column and the row.
text
required A String.

Moves the cursor with SetCursorPosition and writes the text with WriteTo, in the current colour attributes of the console. The cursor stays after the text.

WriteAtColored

Writes text at a position in given colours.

Syntax: object.WriteAtColored ( col , row , text , fore [ , back ] )

col, row
required Long values, the column and the row.
text
required A String.
fore
required A ConsoleColor.
back
optional A ConsoleColor. The default is Black.

Moves the cursor and calls WriteColored, so the colours that were tracked before are put back after the text.

WriteColored

Writes text in given colours.

Syntax: object.WriteColored ( text , fore [ , back ] )

text
required A String.
fore
required A ConsoleColor, the text colour.
back
optional A ConsoleColor, the background colour. The default is Black, whatever the current background is.

Sets the colours with SetColors, writes the text with WriteTo, and sets ForeColor and BackColor back to the values they had before the call. Those are the values that the object tracks: Gray on Black until a property or SetColors changes them. They are not read from the console, so a console that started in other colours ends up in Gray on Black after the first call, and not in its own colours. ResetColors puts back the original ones.

Dim con As New cConsole

con.WriteTo "Status: "
con.WriteColored "OK", ConsoleColor.Black, ConsoleColor.Green
con.WriteLine

WriteError

Writes text to the standard error handle.

Syntax: object.WriteError ( text )

text
required A String.

Calls WriteConsoleW on the standard error handle, so the text is written when that handle is a console and is lost when the error output is redirected to a file or a pipe. No line break is added.

WriteErrorLine

Writes text and a line feed to the standard error handle.

Syntax: object.WriteErrorLine ( text )

text
required A String.

Calls WriteError with the text and a line feed (code 10).

WriteF

Writes text with numbered placeholders.

Syntax: object.WriteF ( format , args … )

format
required A String with the placeholders {0}, {1} and so on.
args
optional A list of values, one for each placeholder, with {0} for the first.

Replaces {0} with the first value, {1} with the second, and so on, in that order, each converted with CStr, and writes the result with WriteTo. The only form of a placeholder is a number in braces; a format such as {0:N2} is not understood and stays as it is. The replacements are made one after the other on the whole text, so a value that contains {1} has that text replaced by the second value. A value that CStr cannot convert raises the error that CStr raises. A placeholder with no value stays in the text.

Dim con As New cConsole

con.WriteLineF "{0} + {1} = {2}", 2, 3, 2 + 3

WriteLine

Writes text and a line feed.

Syntax: object.WriteLine [ ( text ) ]

text
optional A String. The default is an empty string, which writes only the line feed.

Calls WriteTo with the text and vbLf, the line feed (code 10) alone. The console moves to the start of the next line when it processes output, which it does by default.

WriteLineColored

Writes text in given colours, and a line feed.

Syntax: object.WriteLineColored ( text , fore [ , back ] )

text
required A String.
fore
required A ConsoleColor.
back
optional A ConsoleColor. The default is Black.

Calls WriteColored with the text and a line feed, so the line feed is written in the given colours too.

WriteLineF

Writes text with numbered placeholders, and a line feed.

Syntax: object.WriteLineF ( format , args … )

Replaces the placeholders as WriteF does and writes the result with WriteLine.

WriteTo

Writes text, without a line break.

Syntax: object.WriteTo ( text )

text
required A String. Every UTF-16 code unit of the string is written, in the current colour attributes of the console.

Calls WriteConsoleW on the standard output handle with the characters of the string, and ignores the result. The text is not converted, so any Unicode character that the console font can draw appears as it is. Control characters are handled by the console: a carriage return, a line feed, a backspace and the bell take effect, and escape sequences take effect only when the virtual-terminal mode is on; see EnableVirtualTerminal. When the output is redirected, or the program has no console, nothing is written.

See Also