|
Language: |
Visual Basic.NET 2003 |
|
Description: |
Standard Windows Form Label control capable
of rotating its text from -360 to 360 degrees.
This control has two reference modes, center and
quadrant. |
|
Sample: |
 |
In a recent programming endeavor I had the need to
have text displayed in the vertical position. As
usual, what I thought would be a 10 min solution became
a 3 day journey. I just assumed that the standard
windows form label control had a build in property that
would determine the orientation. Once I looked and
Googled for the property I soon found I was out of
luck. I never did find an all inclusive answer to
my problem, although I found several good leads that
lead me in the right direction. With the lack of
answers I decided to write this tutorial to show how to
create a label control that will rotate on any angle.
As with many problems of this type, the best way to
handle the problem is to create your own custom control.
In this case the rotating label will inherit all of it
attributes from the existing label control. The
first step is to create a new Windows Control Library project and name it Rotating_Label_Control as shown in Figure 1.
|

Figure 1 - Create Project |

Figure 2 - Select override
OnPaint |
The second step is to create the structure of the
class. As a general rule of thumb I always include
Option Strict On and Option Explicit On .
Option Strict On
Option Explicit On |
Next change the class name and Inherit the
System.Windows.Forms.Label namespace
Public Class
Rotating_Label
Inherits System.Windows.Forms.Label
End Class |
There is no need to keep the Windows Form Designer
generated code so that can be safely deleted. The
place that we will insert the rotation is in the OnPaint
function. Visual Studio gives us an easy way of
doing this. From the drop down menus just below
the file tabs, select (Overrides) and OnPaint as shown
in figure 2. The designer produces the following
code.
| Protected
Overrides Sub OnPaint(ByVal e As
System.Windows.Forms.PaintEventArgs)
End Sub |
Also at this step add two properties. These
will show up under the Misc. Section in the form
designer. The first property is the rotation angle
that the text should take. This property should be
self explanatory. The second is the mode which the
text should be displayed as. The mode is set as a
boolean as to use self-centering or quadrant based
alignment. Centering text rotates the text around
the center of the text field and acts like center
justify in a word processor. This is most likely
the preferred method if the text will be dynamically
changed during runtime. The second method attaches
the text to the label container in one of the corners,
depending on the rotation angle. This acts as a
weird left (right, top, or bottom depending which
quadrant you are in) justify in a word processor.
The purpose of this mode is mostly for design time
labels. For example, if I have several labels tilted on
a -90 degree angle (vertical) with different text
lengths I would prefer the quadrant mode because the
text does not grow from the center and I can align all
of the labels from the bottom left corner. Below
is the code to add for the two properties. We will
encounter both in the OnPaint method.
'Priviate
Variables
Private _rotationAngle As Integer
Private _quadrantMode As Boolean
'Properties
Public Property rotationAngle() As Integer
Get
Return _rotationAngle
End Get
Set(ByVal Value As Integer)
_rotationAngle = Value
MyBase.Refresh()
End Set
End Property
Public Property quadrantMode() As Boolean
Get
Return _quadrantMode
End Get
Set(ByVal Value As Boolean)
_quadrantMode = Value
MyBase.Refresh()
End Set
End Property |
Now we will move on to the OnPaint override.
First we find out what the text area dimensions are.
This is not the dimensions of the label control but the
dimensions of the actual text field. Next is a
variable that converts the rotated angle into radians
which is used for the trig functions in quadrant mode.
Lastly is a variable that captures the foreground color
as a brush. The DrawString function takes a brush
but the font property only offers a dwawing.color
object.
'variables
to capture the size of the text area
Dim width As Double =
e.Graphics.MeasureString(Text,
Me.Font).Width
Dim height As Double =
e.Graphics.MeasureString(Text,
Me.Font).Height
'convert the rotation angle into radians for
trig functions
Dim angleRadian As Double = ((_rotationAngle
Mod 360) / 180) * Math.PI
'capture the forground color as a brush
Dim myBrush As Brush = New
SolidBrush(Me.ForeColor) |
Next is a selector for either center or quadrant
modes in the form of a if statement. First we will
tackle the quadrant mode. To make a rotation, two
operations must occur, the rotation and adjustment on
the x,y axis for the rotation. If only the
rotation occurs a clipping of the text occurs. In
the simplest case of quadrant I, the bottom left part of
the string is chopped off. To compensate I moved
the sting to the right the distance of the clipping.
The clipping distance can be found by using trig as the
label container and string rectangle forms a triangle.
I will not go much further into this as I'm still
looking at several sheets of green engineering graph
paper and hoping not to relive that experience again for
quite some time. The appropriate correction is
made for each quadrant in the if / ifelse structure.
If _quadrantMode
= True Then
'Quad I
If (_rotationAngle >= 0 AndAlso _rotationAngle
< 90) Or (_rotationAngle < -270 AndAlso _rotationAngle
>= -360) Then
e.Graphics.TranslateTransform(CInt(Math.Sin(angleRadian)
* height), 0)
'Quad II
ElseIf (_rotationAngle >= 90 AndAlso _rotationAngle
< 180) Or (_rotationAngle < -180 AndAlso _rotationAngle
>= -270) Then
e.Graphics.TranslateTransform(ClientRectangle.Width,
CInt(height - (Math.Sin(angleRadian) *
height)))
'Quad III
ElseIf (_rotationAngle >= 180 AndAlso _rotationAngle
< 270) Or (_rotationAngle < -90 AndAlso _rotationAngle
>= -180) Then
e.Graphics.TranslateTransform(ClientRectangle.Width
+ CInt(Math.Sin(angleRadian) * height),
ClientRectangle.Height)
Else 'Quad IV
e.Graphics.TranslateTransform(0,
ClientRectangle.Height -
CInt(Math.Cos(angleRadian) * height))
End If |
I can not take credit for the center mode as I browed
it from Chester Ragel who has an article on The Code
Project Website [http://www.codeproject.com/cs/miscctrl/customtext.asp].
The borrowed code is written in C# and actually has more
functionality than my code as it also produces arcs and
circles. I understand the code but I will not
explain it here
Else
'Center Mode
e.Graphics.TranslateTransform(CInt((ClientRectangle.Width
+ (height * Math.Sin(angleRadian)) - (width
* Math.Cos(angleRadian))) / 2),
CInt((ClientRectangle.Height - (height *
Math.Cos(angleRadian)) - (width *
Math.Sin(angleRadian))) / 2))
End If |
Finially the code is ended with the rotation and
writing of the string.
'Make the
actual rotation,and draw the string
e.Graphics.RotateTransform(CInt(_rotationAngle))
e.Graphics.DrawString(Me.Text, Me.Font,
myBrush, 0, 0)
e.Graphics.ResetTransform() |
|

Figure 3 - Adding a Control |
Once the code is
complete, compile it and you should get an error
stating that an object with the type of class
library can not be started directly. This
is fine and indicated that the project DLL was
complied successfully. From another
project in which you want to use the new control
in, go to the designer view. Right click
in a tab and select add/remove items as shown in
figure 3. Go to browse and go to the /bin
directory of the Rotating_Label project.
Select Vertical_Label_Control.dll and click OK.
You should not see the control displayed in the
tab. When needed simply add the control
just like the regular label, set the properties,
and your all done. A .zip file with the
control source and example project is included
below.
Rotating_Label_Control.zip |
|