DevCity.NET - http://devcity.net
Text Techniques (1)
http://devcity.net/Articles/145/1/article.aspx
Ged Mead

Ged Mead (XTab) is a Microsoft Visual Basic MVP who has been working on computer software and design for more than 25 years. His journey has taken him through many different facets of IT. These include training as a Systems Analyst, working in a mainframe software development environment, creating financial management systems and a short time spent on military laptop systems in the days when it took two strong men to carry a 'mobile' system.

Based in an idyllic lochside location in the West of Scotland, he is currently involved in an ever-widening range of VB.NET, WPF and Silverlight development projects. Now working in a consultancy environment, his passion however still remains helping students and professional developers to take advantage of the ever increasing range of sophisticated tools available to them.

Ged is a regular contributor to forums on vbCity and authors articles for DevCity. He is a moderator on VBCity and the MSDN Tech Forums and spends a lot of time answering technical questions there and in several other VB forum sites. Senior Editor for DevCity.NET, vbCity Developer Community Leader and Admin, and DevCity.NET Newsletter Editor. He has written and continues to tutor a number of free online courses for VB.NET developers.

 
by Ged Mead
Published on 3/30/2005
 

Sometimes plain old standard horizontal text just won’t do the job.Maybe you need vertical text...

... of one kind or the other. The DrawString method of the Graphics Class holds the answers to both of these little problems.Read on to see how it can be done.


Vertical Text: Top to Bottom

Problem:

   You want to want to write a text string on a label vertically, top to bottom (rotated 90 degrees clockwise)

 

Solution

   Draw the string on the label using the Graphics DrawString method.    Use the FormatFlags Property of the System.Drawing.StringFormat Class, selecting DirectionVertical from the StringFormatFlags Enumeration.

Code

   If that sounds technical, it’s only because there are several steps involved, but it isn’t really as complicated as it might seem.     Let’s start with the code, then we can break it down into understandable steps.

    Place a label named Label1 on a form.   Put this Imports statement at the top of the form:

Imports System.Drawing.Text

   And this code in the Label’s Paint event:

Private Sub Label1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Label1.Paint
        Dim strText As String = "Top to Bottom"
        Dim lbl1gfx As Graphics = e.Graphics
        Dim fnt As Font = New Font("Verdana", 12, FontStyle.Regular)
        Dim SF As New StringFormat
        SF.FormatFlags = StringFormatFlags.DirectionVertical
        lbl1gfx.Clear(Color.White)
        lbl1gfx.TextRenderingHint = _
          TextRenderingHint.AntiAlias
        lbl1gfx.DrawString(strText, fnt, Brushes.Black, 12, 12, SF)
    End Sub

Run the Project and your string will be displayed vertically.

If you want a step by step breakdown of this code, check out the next page.

 

Code Breakdown (1)

  

 1.  Putting the code inside the Label’s Paint event ensures that the text is refreshed every time the label has to be redrawn.   This can happen if, for example, the form is minimized or another form or even another application is opened on top of it, causing it to be obscured.

 Private Sub Label1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Label1.Paint

  2.       Next is the text that we want to display vertically in the label.

 Dim strText As String = "Top to Bottom"

3.       The Label control has a Graphics object with which  it is associated.  Without getting too deep into the technicalities, this can be thought of as the canvas on which the control’s text and images are drawn and it is the same size and shape as the control itself.
   There’s more to it than that, but if you think of the Graphics object in that way,  you oftentimes won’t need to delve any further into its complexities.

 Dim lbl1gfx As Graphics = e.Graphics

So in this case, we can get hold of the Graphics object for this particular control by extracting it from the
    ByVal e As System.Windows.Forms.PaintEventArgs
  element of the event’s parameters.


4.  Although we are all very familiar with the use of fonts in general, we don’t often have to get involved with them as objects in their own right.   We’ve been pretty well led by the hand most times, having to do no more than choose a font, a font color, a font size and a style from a dropdown list.
  
   When hand building text in the way that we are with DrawString, you also have to create an instance of  the particular font that you want to use.   This is one of those rare occasions where Intellisense doesn’t lead you by the hand every step of the way.   It’s still a big help, of course, but you have to type in the name of the Font family you want to use (i.e. there isn’t a list for you to choose from).   It’s not asking a lot of the developer, but we do tend to get used to having it all done for us, so you need to be ready for that.

   The only other potential gotcha with creating a font is that sometimes – but only sometimes - the permutations of arguments don’t reveal themselves in exactly the way you might expect.   That is, you may be expecting to enter a font size as the next parameter, but when you look up and check the screen you may see that it has jumped straight to the FontStyle parameter.  It’s not the biggest problem in the world, but something to watch out for.

   Font sizes are listed as “emSize”, by the way, in Intellisense when instantiating Font object instances.

  So, the code line below sets the Font Family to Verdana,  Font Size to 12, and the FontStyle to Regular (that is, not Bold, Underlined, Italic, etc).

Dim fnt As Font = New Font("Verdana", 12, FontStyle.Regular)

5.  StringFormat is a Class within the Drawing Class that offers you choices of text layout, including alignment and spacing.   Alignment is of course the area we are interested in at the moment.  The first line above creates a new instance of a StringFormat object.

     Within the StringFormat class, there is a Property called FormatFlags.   We can access this property and select one or more of the choices from the Enumeration of StringFormatFlags on offer.   The second line of code therefore selects the DirectionVertical choice from the enumeration and assigns it to the StringFormat instance we created and named SF.

 Dim SF As New StringFormat
 SF.FormatFlags = StringFormatFlags.DirectionVertical

6.     The next line isn’t always necessary.   However if you are going to replace one text display with something different then you will need to Clear the Graphics object first, otherwise the second text string will be appended to the first one.
   You can clear the label to any backcolor you choose. 

   lbl1gfx.Clear(Color.White)

7.    The next line is also optional, but recommended.   TextRenderingHints offer a small range of choices of text quality.  In general - as with most things processing based – the better the quality demanded, the bigger the potential performance hit.    For a tiny code example such as this one, the processing performance reduction is negligible.
   The AntiAlias option used in this example is often the best quality/performance choice for general application work.

  Note that if you decide that you don’t want to use a TextRenderingHint then you can also dispense with the Imports statement I recommended earlier that you place at the top of the form.

  lbl1gfx.TextRenderingHint =  _ TextRenderingHint.AntiAlias

8.  And, finally, the text is “written” or drawn using DrawString.  The parameters are Text string, Font, Brush used to draw(write) with, String Origin X-Position, String Origin Y-Position, StringFormat.

   We have already dealt with the text string and the font.  
The brush used is a basic system defined Brush object: you can select any of the known colors for the brush by picking the one of your choice from the drop down list in Intellisense.

   The String Origin values represent the number of pixels from the left hand side of the label (X-Position) and from the top of the label (Y-Position) from where the text drawing starts.

lbl1gfx.DrawString(strText, fnt, Brushes.Black, 12, 12, SF)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p>

  As you can see from the step by step code, it’s all fairly straightforward and you have several choices and options open to you.

    Although this example uses a label control,  you are not limited to this.   You can use the same technique with minimal changes to create the same display on the surface of a form, a Button, a PictureBox or any other control which has a Text property.

 

 

Vertical Text: Bottom to Top

Problem:

   You want to want to write a text string on a label vertically, bottom to top (rotated 90 degrees anticlockwise

Solution

   Draw the String using the DrawString method of the Graphics Class.  Use Transformations to move the start point of the text downwards and to rotate the text from horizontal to vertical.


The Code

      Reading some of the textbooks and articles that deal with Graphics Transformations can seriously damage your sanity!   Luckily, the transformations we are going to apply to this label’s text are relatively easy to follow if, as before, we break the code down into manageable, understandable chunks.

   Here is the code which produces the label text shown in the graphic at the top of this page:

Imports

System.Drawing.Text

Private Sub Label2_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Label2.Paint
  '  Draw text vertically, from bottom to top
  '   The text to be drawn on the label
   Dim strText As String = "Bottom to Top"
   '  The Graphics object for this label
   Dim g2 As Graphics = e.Graphics
  '  The font, size and style to draw text 
  Dim fnt As Font = New Font("Arial", 12, FontStyle.Bold)
  '   Move origin point of text down to bottom of label
  g2.TranslateTransform(13, Label2.Height - 25)
  '  Rotate the text the required number of degrees
  g2.RotateTransform(270)
  '  Optional TextRenderingHint
  g2.TextRenderingHint = TextRenderingHint.ClearTypeGridFit
  '  Finally we draw the string
  g2.DrawString(strText, fnt, Brushes.White, 0, 0)
 End Sub

  That's it!  Run this code and the text will appear in the label bottom to top.  There is a more detailed breakdown on the next page.

 

Code Breakdown (2)

 

1.  The first three lines will be familiar from the first example that we just dissected, so I won’t go through them again.

  Dim strText As String = "Bottom to Top"
  '  The Graphics object for this label
  Dim g2 As Graphics = e.Graphics
  '  The font, size and style to draw text 
  Dim fnt As Font = New Font("Arial", 12, FontStyle.Bold)

2.   Translations can become very complex, but this one is fairly straightforward.   I see that the MSDN definition of TranslateTransform is:” Prepends the specified translation to the transformation matrix of this Graphics object”

     Well, that’s clear enough then!   To be fair, it’s a totally accurate description, but I’m just not sure just how much further forward it would take your understanding of the topic.   In other circumstances it may be necessary to get right into the technical details, but for today we can take a much shallower dip into the water.

     For our purposes here, when you set the values for TranslateTransform all you are doing is moving the start point of the string that will be drawn.   The first value is the X-Position (number of pixels from the left  of the label border) and second value is the Y-Position (pixels from the top of the label).

    The values I’ve used should make sense to you now.   The X-Position is 13 pixels from the left edge.   The Y-Position is calculated by counting 25 pixels backwards from the bottom of the label.   This point (X:13, Y:Label2.Height – 25) is where the top left hand corner of the text string will begin.

  If you want to see the effect of this TranslateTransform line, try commenting out the line which follows it  (i.e. the RotateTransform one).   You will then see quite clearly how the start point of the string has been shunted down the label.  And will also see why we do in fact need the next line to swivel the text so that it is written upwards instead of horizontally.

  g2.TranslateTransform(13, Label2.Height - 25)

 

3.  Next,  the code which rotates the text.  The value of 270 represents the number of degrees in that rotation, so the text will swivel from horizontal to vertical.  In case you were wondering, a value of -90 (minus 90) will have exactly the same effect.

 

  g2.RotateTransform(270)

 

  The final lines show very little change from the code in the first example.  You will see that I changed the TextRenderingHint setting because this one seemed to produce a better finish for the black on white label on my monitor.   You may want to experiment with these settings to find the one that best suits your purposes.

 

   g2.TextRenderingHint = TextRenderingHint.ClearTypeGridFit
   '  Finally we draw the string
   g2.DrawString(strText, fnt, Brushes.White, 0, 0)

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p> 

<o:p>  As with the first example, you can apply the above technique to many other controls in order to rotate the text as required.   </o:p>

<o:p></o:p> 

<o:p>  You probably don’t need me to tell you that by tweaking the number of degrees in the rotation angle, you can also write diagonally.</o:p>

<o:p></o:p> 

<o:p></o:p> 

 

Summary

  In this article you have seen how easy it is to rotate text on a control or a form.

   To do this, we used the following graphics methods, objects and techniques:

• DrawString
• Font Object
• FontStyles
• Graphics Object
• RotateTransform method
• StringFormat
• StringFormatFlags
• System Brushes
• TextRenderingHint
• TranslateTransform method

   In the next article in the Text Techniques series, we will see that it is equally easy to display text on a label, button or other control using a variety of fonts, font styles and text colors.