Rotate multi-line text on any angle

I need to rotate MULTI-LINE text on canvas.

All examples shows how to rotate single-line text.

Function must to work on any windows (95-XP) (SetWorldTransform isn't suitable).
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Taken from win32 programmer reference:

The CreateFont function creates a logical font that has specific characteristics. The logical font can subsequently be selected as the font for any device.

HFONT CreateFont(

    int nHeight,      // logical height of font
    int nWidth,      // logical average character width
    int nEscapement,      // angle of escapement
    int nOrientation,      // base-line orientation angle
    int fnWeight,      // font weight
    DWORD fdwItalic,      // italic attribute flag
    DWORD fdwUnderline,      // underline attribute flag
    DWORD fdwStrikeOut,      // strikeout attribute flag
    DWORD fdwCharSet,      // character set identifier
    DWORD fdwOutputPrecision,      // output precision
    DWORD fdwClipPrecision,      // clipping precision
    DWORD fdwQuality,      // output quality
    DWORD fdwPitchAndFamily,      // pitch and family
    LPCTSTR lpszFace       // pointer to typeface name string

with this you can create the font of your choice then you output the text with

This is the definition in Win32 programmers reference but you can also use the TCanvas.Textout
BOOL TextOut(

    HDC hdc,      // handle of device context
    int nXStart,      // x-coordinate of starting position  
    int nYStart,      // y-coordinate of starting position  
    LPCTSTR lpString,      // address of string
    int cbString       // number of characters in string

oh .. for multiline .. either use Textout once for each line ( if you want to choose the space between the lines or in most cases you can use the combination #13#10 in your text.
'text1' + #13#10 + 'Text2';

good luck

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
There is a component available that I use and modified to easily rotate a bitmap. It is available (freeware with source) from :

(I had to fix/add the transparent property to the main routine)

With that component it is easy to rotate and image to any angle. Now I also do multiline rotations using a TMemo. First you need to create a rectangle to contain the test as a graphic. Use one line in the memo for one line fo text. I use this an OnMouseDwon event in a TImage. I can also load an image if I want to paste the text onto it.


procedure TFAddSticky.Image1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
 bmp : TBitmap;
 IsMouseDown := True;
 image1.Picture := nil;
 bmp := TBitmap.Create;
   bmp.Width := 210;
   bmp.Height := 165;
   bmp.Canvas.Brush.Color := ColorComboBox1.ColorValue;
   bmp.Canvas.FillRect(rect(0, 0, bmp.Width, bmp.Height));
   if (ColorComboBox1.ColorValue = clBlack) or (ColorComboBox1.ColorValue = clMaroon) or
   (ColorComboBox1.ColorValue = clGreen) or (ColorComboBox1.ColorValue = clNavy) then
   bmp.Canvas.Font.Color := clWhite
     bmp.Canvas.Font.Color := clBlack;
   if ColorComboBox1.ColorValue = clWhite then
    bmp.Transparent := True
      bmp.Transparent := False;
   bmp.Canvas.TextOut(10, 5, Memo1.Lines[0]);
   bmp.Canvas.TextOut(10, 20, Memo1.Lines[1]);
   bmp.Canvas.TextOut(10, 35, Memo1.Lines[2]);
   bmp.Canvas.TextOut(10, 50, Memo1.Lines[3]);
   bmp.Canvas.TextOut(10, 65, Memo1.Lines[4]);
   bmp.Canvas.TextOut(10, 80, Memo1.Lines[5]);
   bmp.Canvas.TextOut(10, 95, Memo1.Lines[6]);
   bmp.Canvas.TextOut(10, 110, Memo1.Lines[7]);
   bmp.Canvas.TextOut(10, 125, Memo1.Lines[8]);
   bmp.Canvas.TextOut(10, 140, Memo1.Lines[9]);
    tempbmp := TBitmap.Create;
   // Get an image (bmp) I want to stick this text on
    tempbmp.LoadFromFile(ExtractFileDir(ParamStr(0)) + '\~tmp.bmp');    
  // Stick this sticky on the canvas where  the mouse is at and clicked. NOT NEEDED NOW
  // I would use ...Draw(0,0,bmp) for now.
  tempbmp.Canvas.Draw(Round(X*3.333), Round(Y*3.33),bmp);
    Image1.Picture.Bitmap := tempbmp;  

To rotate the image add the rotimg.pas to your uses clauses (no need to install the component) and then somewhere above and before sticking the image to the canvas rotate it. I.E. (a snippet)

if ComboBox2.Text = 'Angled Down' then // ComboBox has a numeric value for angles
     TheAngle := -SpinEdit2.Value;
     tempbmp.Canvas.Draw(Round(X*2.6), Round(Y*3),CreateRotatedBitmap(bmp, TheAngle, 16777215));
   if ComboBox2.Text = 'Angled Up' then
     TheAngle := SpinEdit2.Value;   //3.86          //4.3
     tempbmp.Canvas.Draw(Round(X*3), Round(Y*0.8),CreateRotatedBitmap(bmp, TheAngle, 16777215));
     ComboBox2.Text := 'Horizontal';
     TheAngle := 0;                         //4.5
     tempbmp.Canvas.Draw(Round(X*3.3), Round(Y*3.35),CreateRotatedBitmap(bmp, TheAngle, 16777215));
    Image1.Picture.Bitmap := tempbmp;

Haope this may help you.
Will this help? Of course, it only works with TrueType fonts:

procedure DrawAngledText(Canvas: TCanvas; X, Y: Integer;
  const Angle: Double; Alignment: Integer; const Text: String);
  LogFont: TLogFont;
  FontHandle: THandle;
  TextAlign: Integer;
  GetObject(Canvas.Font.Handle, SizeOf(LogFont), @LogFont);
  LogFont.lfEscapement := Round(Angle * 10);
  LogFont.lfOrientation := LogFont.lfEscapement;
  LogFont.lfQuality := PROOF_QUALITY;
  FontHandle := SelectObject(Canvas.Handle, CreateFontIndirect(LogFont));
  TextAlign := SetTextAlign(Canvas.Handle, Alignment);
  Canvas.TextOut(X, Y, Text);
  SetTextAlign(Canvas.Handle, TextAlign);
  DeleteObject(SelectObject(Canvas.Handle, FontHandle));

The Angle parameter is in degrees and the Alignment parameter specifies the text alignment by using a mask of the values in the following list. Only one flag can be chosen from those that affect horizontal and vertical alignment.

The reference point will be on the base line of the text.

The reference point will be on the bottom edge of the bounding rectangle.

The reference point will be on the top edge of the bounding rectangle.

The reference point will be aligned horizontally with the center of the bounding rectangle.

The reference point will be on the left edge of the bounding rectangle.

The reference point will be on the right edge of the bounding rectangle.

sample usage:
procedure TForm1.FormPaint(Sender: TObject);
  DrawAngledText(Canvas, ClientWidth div 2, ClientHeight div 2,
  45, TA_BOTTOM or TA_CENTER, 'Powered by Borland Delphi.');

Code is courtesy of Kambiz of
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.