Reader question on different options to align text using GDI+
I received a GDI+ question on text alignment recently. He was concerned because there were only three options to align text: Near, Center, and Far.
It’s actually a bit deeper than that, but the .NET framework designers tried to make it as simply as possible in most cases, yet still give you all the possibilities to format and align text in all the ways that you want.
There are three different parameters that control text alignment in GDI+ (and, therefore .NET programs): Text Alignment, Line Alignment, and whether to align the text to a point or inside a bounding rectangle. The end result gives you 18 different possibilities.
This image shows a short bit of text with all 9 different alignment combinations around 9 different points.

The alignment point is at the intersection of the blue lines. The code is below:
privatevoid DrawPointText( Graphics graphics)
{
float xDelta = (float )this.ClientRectangle.Size.Width / 4f;
float yDelta = ( float ) this.ClientRectangle.Size.Height / 4f;
StringFormat f = new StringFormat();
graphics.DrawLine( Pens.Blue, xDelta, 0f, xDelta,
(float )ClientRectangle.Height );
graphics.DrawLine( Pens.Blue, xDelta * 2f, 0f, xDelta * 2f,
(float )ClientRectangle.Height );
graphics.DrawLine( Pens.Blue, xDelta * 3f, 0f, xDelta * 3f,
(float )ClientRectangle.Height );
graphics.DrawLine( Pens.Blue, 0, yDelta,
( float ) ClientRectangle.Width, yDelta );
graphics.DrawLine( Pens.Blue, 0, yDelta* 2f,
( float ) ClientRectangle.Width, yDelta * 2f);
graphics.DrawLine( Pens.Blue, 0, yDelta * 3f,
( float ) ClientRectangle.Width, yDelta * 3f);
f.Alignment = StringAlignment.Near;
f.LineAlignment = StringAlignment.Near;
graphics.DrawString("Near, Near Line", this.Font, Brushes.Black,
xDelta*3, yDelta, f );
f.LineAlignment = StringAlignment.Center;
graphics.DrawString("Near, Center Line", this.Font, Brushes.Black,
xDelta*3, yDelta*2, f );
f.LineAlignment = StringAlignment.Far;
graphics.DrawString("Near, Far Line", this.Font, Brushes.Black,
xDelta*3, yDelta*3, f );
f.Alignment = StringAlignment.Center;
f.LineAlignment = StringAlignment.Near;
graphics.DrawString("Center, Near Line", this.Font, Brushes.Black,
xDelta*2, yDelta, f );
f.LineAlignment = StringAlignment.Center;
graphics.DrawString("Center, Center Line", this.Font, Brushes.Black,
xDelta*2, yDelta*2f, f );
f.LineAlignment = StringAlignment.Far;
graphics.DrawString("Center, Far Line", this.Font, Brushes.Black,
xDelta*2, yDelta*3f, f );
f.Alignment = StringAlignment.Far;
f.LineAlignment = StringAlignment.Near;
graphics.DrawString("Far, Near Line", this.Font, Brushes.Black,
xDelta, yDelta, f );
f.LineAlignment = StringAlignment.Center;
graphics.DrawString("Far, Center Line", this.Font, Brushes.Black,
xDelta, yDelta*2f, f );
f.LineAlignment = StringAlignment.Far;
graphics.DrawString("Far, Far Line", this.Font, Brushes.Black,
xDelta, yDelta*3f, f );
}
The other nine combinations are created by aligning the text inside a bounding rectangle. This image shows the same text aligned inside the window rectangle, using all 9 alignment combinations.

The code is below:
privatevoid DrawRectText( Graphics graphics)
{
StringFormat f = new StringFormat();
RectangleF bounds = new RectangleF(
( float ) this.ClientRectangle.X,
( float ) this.ClientRectangle.Y,
( float ) this.ClientRectangle.Width,
( float ) this.ClientRectangle.Height );
f.Alignment = StringAlignment.Near;
f.LineAlignment = StringAlignment.Near;
graphics.DrawString( "Near, Near", this.Font, Brushes.Black,
bounds, f );
f.Alignment = StringAlignment.Center;
f.LineAlignment = StringAlignment.Near;
graphics.DrawString( "Center, Near", this.Font, Brushes.Black,
bounds, f );
f.Alignment = StringAlignment.Far;
f.LineAlignment = StringAlignment.Near;
graphics.DrawString( "Far, Near", this.Font, Brushes.Black,
bounds, f );
f.Alignment = StringAlignment.Near;
f.LineAlignment = StringAlignment.Center;
graphics.DrawString( "Near, Center", this.Font, Brushes.Black,
bounds, f );
f.Alignment = StringAlignment.Center;
f.LineAlignment = StringAlignment.Center;
graphics.DrawString( "Center, Center", this.Font, Brushes.Black,
bounds, f );
f.Alignment = StringAlignment.Far;
f.LineAlignment = StringAlignment.Center;
graphics.DrawString( "Center, Center", this.Font, Brushes.Black,
bounds, f );
f.Alignment = StringAlignment.Near;
f.LineAlignment = StringAlignment.Far;
graphics.DrawString( "Near, Far", this.Font, Brushes.Black,
bounds, f );
f.Alignment = StringAlignment.Center;
f.LineAlignment = StringAlignment.Far;
graphics.DrawString( "Center, Far", this.Font, Brushes.Black,
bounds, f );
f.Alignment = StringAlignment.Far;
f.LineAlignment = StringAlignment.Far;
graphics.DrawString( "Far, Far", this.Font, Brushes.Black,
bounds, f );
}
By picking the right alignment, line alignment, and whether you align to a point, or to a bounding rect, you do have all the control you want to place text exactly where it should go. The simplicity of the API can make it easy to ignore that these features exist, but with a bit of digging, you’ll find them.