Color your console output using VB.NET!
By Cory Smith
Note: This sample has been replaced by the ‘Control Your Console’ ConsoleEx sample available from the Samples listing. In addition to being able to specify the color, you can control cursor position, window title, determine size of the console and much more.
Download source code - 2.28kb
Introduction
Back in the days before Windows (yes, even Windows 3.x) we used to have applications that took advantage of the DOS prompts ability to change the foreground and background colors to present data in a more meaningful manner. As we’ve move forward with a Windows interface, developers creating console applications have all but forgotten that they too have this ability. Sure, most of the time, these applications are for testing purposes, but it would still be nice to have the output presented in a manner that allows the user to quickly identify important portions of the data that is being presented. For example, you could have a console application that shows you the output of some task; presenting you with successful, questionable, and failed/error events. Each of these could be marked using green, yellow, and red foreground colors to allow the user to quickly identify one type of event over the others based on color alone.
Now, for the problem. .NET console applications do not give you the ability to modify the foreground and background colors of what you output to the screen. However, since .NET console application are true Windows console applications, we can leverage a few Windows API’s to assist us with this problem.
We we’re going to do is wrap up the necessary API calls into a re-usable component class. We’re going to expand upon the flag values by creating all of the variations of the colors; instead of relying on OR
‘ing all of the values to create the various combinations. This will give us more of a .NET feel. In the end, this re-usable component will have three overloaded shared methods that allows us to modify the output colors. We will also mark this class so that we can’t create an instance of the class; only allowing for the shared access methods.
ConsoleColor.vb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
Option Explicit On
Option Strict On
Imports System.Runtime.InteropServices
Imports Win32.Kernel32.ConsoleColor
Namespace Win32.Kernel32
Class ConsoleColor
<Flags()>
Public Enum ForegroundColors
Black = 0
Blue = 1
Green = 2
Cyan = Blue Or Green
Red = 4
Magenta = Blue Or Red
Yellow = Green Or Red
White = Blue Or Green Or Red
Gray = 8
LightBlue = Gray Or Blue
LightGreen = Gray Or Green
LightCyan = Gray Or Cyan
LightRed = Gray Or Red
LightMagenta = Gray Or Magenta
LightYellow = Gray Or Yellow
BrightWhite = Gray Or White
End Enum
<Flags()>
Public Enum BackgroundColors
Black = 0
Blue = 16
Green = 32
Cyan = Blue Or Green
Red = 64
Magenta = Blue Or Red
Yellow = Green Or Red
White = Blue Or Green Or Red
Gray = 128
LightBlue = Gray Or Blue
LightGreen = Gray Or Green
LightCyan = Gray Or Cyan
LightRed = Gray Or Red
LightMagenta = Gray Or Magenta
LightYellow = Gray Or Yellow
BrightWhite = Gray Or White
End Enum
<Flags()>
Public Enum Attributes
None = &H0
GridHorizontal = &H400
GridLVertical = &H800
GridRVertical = &H1000
ReverseVideo = &H4000
Underscore = &H8000
End Enum
Private Const STD_OUTPUT_HANDLE As Integer = -11
Private Shared InvalidHandleValue As New IntPtr(-1)
Private Sub New ()
' This class can not be instantiated.
End Sub
' Our wrapper implementations.
Public Overloads Shared Sub SetConsoleColor(ByVal foreground As ForegroundColors)
SetConsoleColor(foreground, BackgroundColors.Black, Attributes.None)
End Sub
Public Overloads Shared Sub SetConsoleColor(ByVal foreground As ForegroundColors, _
ByVal background As BackgroundColors)
SetConsoleColor(foreground, background, Attributes.None)
End Sub
Public Overloads Shared Sub SetConsoleColor(ByVal foreground As ForegroundColors, _
ByVal background As BackgroundColors, _
ByVal attribute As Attributes)
Dim handle As IntPtr = GetStdHandle(STD_OUTPUT_HANDLE)
If handle.Equals(InvalidHandleValue) Then
Throw New System.ComponentModel.Win32Exception()
End If
' We have to convert the integer flag values into a Unsigned Short (UInt16) to pass to the
' SetConsoleTextAttribute API call.
Dim value As UInt16 = System.Convert.ToUInt16(foreground Or background Or attribute)
If Not SetConsoleTextAttribute(handle, value) Then
Throw New System.ComponentModel.Win32Exception()
End If
End Sub
' DLLImport's (Win32 functions)
<DLLIMPORT("KERNEL32.DLL", setlasterror:=True )> _
Private Shared Function GetStdHandle(ByVal stdHandle As Integer) As IntPtr
End Function
<DLLIMPORT("KERNEL32.DLL", setlasterror:= True )> _
Private Shared Function SetConsoleTextAttribute(ByVal consoleOutput As IntPtr, _
<MARSHALAS(UNMANAGEDTYPE.U2)> ByVal Attributes As UInt16) As Boolean
End Function
End Class
End Namespace
Now that we have our re-usable class, let’s create a test application to try out our new capabilities we’ve added to the console. NOTE: I’ve added the Attributes portion for completeness; however, it doesn’t appear to work using Windows XP.
ConsoleColorTest.vb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Option Explicit On
Option Strict On
Imports Win32.Kernel32.ConsoleColor
Module ConsoleColorTest
Sub Main()
Dim bgcolor As BackgroundColors
Dim fgcolor As ForegroundColors
' Show every variation of the color combinations.
For Each bgcolor In [Enum].GetValues(GetType(BackgroundColors))
For Each fgcolor In [Enum].GetValues(GetType(ForegroundColors))
SetConsoleColor(fgcolor, bgcolor)
Console.WriteLine(bgcolor.ToString.PadRight(15) & fgcolor.ToString.PadRight(64))
Next
Next
' Set the color back to the default.
SetConsoleColor(ForegroundColors.White, BackgroundColors.Black)
' Wait for input, so we can view the results.
Console.ReadLine()
End Sub
End Module
This demo is pretty straight forward. It simply loops through all of the foreground and background values to display every combination of the values. As you can see, it’s now very simple to add the capability to modify the foreground and background color of your console applications output.
I have to point out one of the cool parts of this sample. You can iterate through an enumeration pretty much like any other “collection”. You have to use the Enum.GetValues method to do this. Notice, since Enum is a reserved word in VB, you have to place the square brackets around it.
Conclusion
There is a lot more that you can do with the console output. This includes moving the cursor position, set font size, and change the window title. The code provided will give you a head start on implementing any additional functionality that the Platform SDK offers concerning console applications. As you can see, VB.NET’s not having unsigned values does not hinder us from implementing this functionality. The System.Convert class comes in very handy, as does the MarshalAs attribute for these sticky situations.
UPDATE: If there is any interest, I’ve expanded on this quite a bit. The version that I’m working on allows you to clear the screen, move the cursor around, etc. allowing you work with a command prompt similar to back in the good ol’ QB4.5 days ;-) If enough comments are left, I’ll consider created a part two to this article… so start commenting ;-)
Resources
- [SetConsoleTextAttribute (Platform SDK / MSDN)](http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/setconsoletextattribute.asp
- Console Apps: Colour Text
- Writing colored text to the console (C#) by Shawn A. Van Ness
- Putting colour/color to work on the console by Philip Fitzsimons (C#)