Manipulating the Console Screen Buffer

What precisely is a screen buffer? It's the area of memory set aside to represent the contents of the screen. Windows applications don't write directly to video memory, so they require some area of regular memory in which to place their data. When Windows updates that actual video memory, it considers the content of the screen buffer for each application. Consequently, knowing something about the console screen buffer can help you create a better user environment for your application.

Sometimes you need to move some text around on screen. The easiest way to do this is to use the ScrollConsoleScreenBuffer() function to move the text. You can move any part of the screen buffer to any other part of the screen buffer, making this function exceptionally useful when displaying text on screen. Of course, the movement of text is limited by the clipping rectangle for the window. If part of the text will appear in an off-screen area as a result of the move, then the function merely clips the text to fit. You need to validate that any text movement you perform will stay on screen (unless you actually want to clip the text to fit within certain confines).

An application isn't limited to one screen buffer, but it must have at least one screen buffer to write any text to the console. You create a new screen buffer using the CreateConsoleScreenBuffer() function. The interesting part about creating a new screen buffer is that you can select a level of sharing for the buffer, which means two processes could potentially work with the same buffer. Use the SetConsoleActiveScreenBuffer() function to set the screen buffer that Windows uses for display purposes. This function also enables you to draw the content of the console screen in the background, and then display it in the foreground— creating a type of animation for the console.

Finally, you can use the SetConsoleScreenBufferSize() function to change the number of rows and columns displayed by the console. This function is especially handy when the default console window is too small or large for the task at hand. Listing 6.9 demonstrates some of the functions described in this section. You can find the source code in the \Chapter 06\C#\ScreenBuffer and \Chapter 06\VB\ScreenBuffer folders on the CD. (The source listing in Listing 6.9 is incomplete—check the source code on the CD for functions and structures discussed in previous sections of the chapter.)

Listing 6.9: Methods for Working with the Console Screen Buffer

// This function enables you to move part of the screen buffer // to another location.

[DllImportCkernel32.dll", SetLastError=true)] public static extern bool ScrollConsoleScreenBuffer( IntPtr hConsoleOutput, ref SMALL_RECT lpScrollRectangle, ref SMALL_RECT lpClipRectangle, COORD dwDestinationOrigin, ref CHAR_INFO lpFill);

// This function enables you to move part of the screen buffer // to another location.

[DllImportCkernel32.dll", SetLastError=true)] public static extern bool ScrollConsoleScreenBuffer( IntPtr hConsoleOutput, ref SMALL_RECT lpScrollRectangle, IntPtr NoClipRectangle, COORD dwDestinationOrigin, ref CHAR_INFO lpFill);

// This structure defines a rectangular area on the screen // consisting of an upper left and a lower right corner. [StructLayout(LayoutKind.Sequential)]

public struct SMALL_RECT {

public Int16 Left;

public Int16 Top;

public Int16 Right;

public Int16 Bottom;

[StructLayout(LayoutKind.Sequential)]

public struct CHAR_INFO {

public Char Character;

public CharacterAttributes Attributes;

[STAThread]

static void Main(string[] {

IntPtr hOut;

SMALL_RECT ScrollRect;

COORD Dest;

CHAR INFO FillData;

args)

// Handle to the output device. // The area to scroll on screen. // The scrolled area destination. // The data to put in the scrolled area.

// Obtain a handle to the console screen.

hOut = GetStdHandle(StdHandleEnum.STD OUTPUT HANDLE)

// Display some data on screen.

Console.WriteLine("This is some data to scroll.") Console.Write("Press any key to scroll..."); Console.ReadLine();

// Initialize the variables. ScrollRect.Top = 0; ScrollRect.Left = 0; ScrollRect.Right = 15; ScrollRect.Bottom = 5;

FillData.Attributes = CharacterAttributes.FOREGROUND_BLUE |

CharacterAttributes.FOREGROUND_RED | CharacterAttributes.FOREGROUND_INTENSITY; FillData.Character = 'A';

// Scroll an area of the screen, if (!ScrollConsoleScreenBuffer(hOut, ref ScrollRect,

IntPtr.Zero,

Dest, ref FillData))

Console.WriteLine("Couldn't scroll the screen buffer.");

// Wait until the user is done viewing the information. Console.Write("\r\nPress any key when ready..."); Console.Read();

This example shows you a couple of new tricks to use when working with Win32 API calls. The first problem you need to overcome is allowing the clipping rectangle to contain a null value. Unfortunately, neither C# nor Visual Basic will allow you to assign a null value (Nothing) to a structure, so you need to devise another way to overcome the problem. There are a number of ways to do this, but the example code shows the most convenient way. Simply create two declarations of the function. The first contains a place for the clipping rectangle, while the second doesn't.

The second problem is one that doesn't even appear in the code, but could cause a problem if you don't look for it in the Platform SDK documentation. The CHAR_INFO structure contains a union as shown in the following code:

typedef struct_CHAR_INFO { union {

WCHAR UnicodeChar; CHAR AsciiChar; } Char;

WORD Attributes; } CHAR_INFO, *PCHAR_INFO;

A union is a special class type for C++ that says you must supply one of the data types to fill the structure, but only one of the data types. The CHAR_INFO structure can accept either an ASCII character or a Unicode character as its first data member. In this case, we don't need to worry about the union because the .NET language takes care of this concern automatically. However, in cases where the language doesn't resolve the problem for you, you'll need to come up with a creative solution. In many cases, the best solution is to create multiple versions of the data structure—one for each of the types listed in the union.

The actual mechanics of the ScrollConsoleScreenBuffer() function are straightforward. The code shows how to fill out the data structures. The example moves some text that originally appears at the top of the screen to a location around the middle of the screen as shown in Figure 6.9. The addition of a clipping rectangle makes it easy to move text within a certain area of the display. Any text that appears outside of the clipping rectangle at the time of the scroll remains untouched. Any text that would appear outside of the clipping rectangle after the scroll is clipped.

■ D:V011t Source (o<W'Chapter O6VCttcroeefluf1arVbln'0ebug\S«roanlMtef .en

a

• to scroll.

E

•«roll. ..

Prtia My luay uKon r«<4y...a

Ikii ia i«m Aal

fro a a any key to

zJ

Figure 6.9: Moving text around on screen is easy when using the ScrollConsoleScreenBuffer() function.

Was this article helpful?

0 0

Responses

  • ruben
    What is console area in data structure?
    4 years ago

Post a comment