Rotated Text - CodeProject

:

Introduction

This tip will attempt to assist you in understanding and using the PictureBox TranslateTransform and RotateTransform functions in C#. Imagine that this also applies to other .NET languages. I also imagine that it applies to other containers with graphic interfaces, but I've not tried.

Background

I've read a few articles on this, and I'd read that it's better to perform the Translate first and the rotate second, but nothing which really helped me to understand what is going on. In the end, I wrote a simple program with just this functionality so that I could see (and hopefully understand) what it all means.

My purpose for performing the text rotation was to elegantly label the Y axis on a graph. Initially, I tried doing this and nothing came out - I realise now that it was just because the text was being rendered outside the bounds of the PictureBox.

TranslateTransform

This function simply repositions the origin (where is 0,0 ?) in the graphics object for any subsequent rendering. You could take the view that this is unnecessary because there's no problem with using a position with negative coordinates, but more on this below...

RotateTransform

This function causes any subsequent rendering to be rotated about the origin.

Main Bit of Code

I'm not a fan of over-commenting, but here goes...

// Our picturebox is an empty container, so we must create the bitmap to go in it.
Bitmap bmp1 = new Bitmap(pictureBox1.Width, pictureBox1.Height);

//Now make a GDI+ graphics connection to the bitmap
Graphics gr1 = Graphics.FromImage(bmp1);

//We want our text to look good, so we'll tell GDI+ to apply AntiAliasing to anything
//we add
gr1.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;

//Now we're ready to perform our first function - TranslateTransform
//We're not actually moving anything graphical here, we're just telling GDI+
//that we want to move the origin of the graphics object for subsequent rendering
gr1.TranslateTransform(trX, trY);

//Next comes the RotateTransform
//Again we're not actually moving anything graphical, we're just telling GDI+
//that anything we draw from now on is to be rotated.
gr1.RotateTransform(R);

//Now add the text.
gr1.DrawString("Some text", drawFont, Brushes.Black, DSX, DSY);

//Finally, put the bitmap (which has been updated via GDI+) into the picturebox.
pictureBox1.Image = bmp1;

In my app, I've also included the StringFormat argument to the DrawString call because it has a useful and associated function. The app front-end looks like this:

https://www.codeproject.com/KB/cs/894884/TransformRotate_1.jpg

Now, in my particular case, I want the text rotate counter-clockwise by 90 degrees to be centred in the tall/thin box vertically and be on the leftmost extreme, so let's try rotating the text. If we just put a rotation in, then it disappears, but with a "Translate" it works:

https://www.codeproject.com/KB/cs/894884/TransformRotate_2.jpg

It's not in the centre yet though, so I'll add 150 to the X position and tell StringFormat to Centre align it there.

https://www.codeproject.com/KB/cs/894884/TransformRotate_3.jpg

So that works. Interestingly though, I could instead take the view that I'm repositioning my origin at the halfway point and then positioning my text at 0,0 like this:

https://www.codeproject.com/KB/cs/894884/TransformRotate_4.jpg

Um, ok. That's exactly the same. So let's try NOT moving my origin, and using a NEGATIVE X position:

https://www.codeproject.com/KB/cs/894884/TransformRotate_5.jpg

Sure enough, that works too.

I think each set is equally as valid, but each for different reasons:

The first says "I want to refer to my coordinates as if the box were horizontal instead of vertical."
The second says "I want to rotate my text around a certain point"
The third says "I appreciate that my origin is now unusual, but I'm OK with that."

C# Project

The project can be found here.

History

  • V1 20150408 164000
  • V2 Tidied-up and released by Deeksha Shenoy
  • V3 Image links fixed by author (probably incorrectly changed "Article" back to "cs")