Use tabs and a StringFormat object to align text drawn on a window in C#


The Graphics class’s DrawString method draws a string on a window, PictureBox, Bitmap, or other drawing surface. DrawString has several overloaded versions, some of which take a StringFormat object as a parameter. That object lets you define things such as the text’s horizontal and vertical alignment. It also lets you define tab stops so you can align tab-delimited text when you draw it.

This example uses the following code to align tab-delimited text.

// Draw some text aligned in columns.
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
string headings = "Title\tPrice\t# Pages\tYear";
string[] lines =
{
"Essential Algorithms: A Practical Approach to Computer Algorithms\t$60.00\t624\t2013",
"MCSD Certification Toolkit (Exam 70-483): Programming in C#\t$59.99\t648\t2013",
"Visual Basic 2012 Programmer's Reference\t$44.99\t840\t2012",
"Start Here! Fundamentals of Microsoft .NET Programming\t$19.99\t266\t2011",
"Stephens' C# Programming with Visual Studio 2010 24-Hour Trainer\t$44.99\t552\t2010",
"WPF Programmer's Reference\t$54.99\t624\t2010",
"Beginning Database Design Solutions\t$44.99\t552\t2008",
"Powers of Two\t$2.04\t8\t16",
};
// Prepare a StringFormat to use the tabs.
using (StringFormat string_format = new StringFormat())
{
// Define the tab stops.
float[] tabs = { 450, 75, 75 };
string_format.SetTabStops(0, tabs);
// Draw the headings.
float margin = 10;
float y = 10;
using (Font font = new Font("Times New Roman", 13, FontStyle.Bold))
{
e.Graphics.DrawString(headings, font,
Brushes.Blue, margin, y, string_format);
}
// Draw a horizontal line.
y += 1.4f * Font.Height;
e.Graphics.DrawLine(Pens.Blue, margin, y, margin + tabs.Sum() + 50, y);
y += 5;
// Draw the book entries.
using (Font font = new Font("Times New Roman", 11))
{
foreach (string line in lines)
{
e.Graphics.DrawString(line, font,
Brushes.Black, margin, y, string_format);
y += 1.2f * this.Font.Height;
}
}
}
}

The code sets the Graphics object’s TextRenderingHint to AntiAlias so it produces smooth text. It then defines a tab-delimited header and some tab-delimited text data.

Next the program creates a StringFormat object. It calls the object’s SetTabStops method to define tab stops for drawn text. The first parameter to SetTabStops is an offset that is added to the first tab stop. The second parameter is an array of relative tab stop distances.

In other words, the X position of the first tab stop is the offset value plus the first value in the tab stop array. (The distances are specified in the units given by the Graphics object’s PageUnit property.) The X position of the second tab stop is the X position of the first tab stop plus the second value in the array. And so on. (I’m not sure why an offset is included. You can set the offset to 0 and simply add any offset to the first tab stop value. that seems simpler.)

The code then creates a header font and draws the tab-delimited heading text. It increases the Y coordinate where it will draw next and draws a horizontal line under the headings. It then moves the Y coordinate down again to prepare to draw the text data.

Next the code loops through the lines of text data drawing each and increasing the Y coordinate. The StringFormat object aligns the tab-delimited values so they line up below the column headings.

If you look at the picture above, you’ll see that the data lines up nicely below the headings. Unfortunately all of the values are aligned on the left and that may not be what you want. For example, you might like numeric values to line up on the right. (Trying to align the columns by setting the StringFormat object’s Alignment and LineAlignment properties just makes things weird.)

In my next post, I’ll show you how you can align different columns in different ways. It’s more work but more flexible.

   

This entry was posted in fonts, graphics, strings. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *