Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

DrawText 3 sentences within a rect

Posted on 2000-02-23
23
Medium Priority
?
1,202 Views
Last Modified: 2013-12-03
Given a node / rectangular region and a DC, I have 3 text sentences that I want to display

thus:

--------------------
| 102.  This is the
| second sentence,
| the number was the
| first.  This is the
| third sentence.
--------------------

The first sentence is the node 'number' which should be shown in a red italic font.  The second sentence is in bold (and a slightly larger font).  The third sentence is in normal font.  It all has to word wrap and the node should grow in size to accomodate all the text.

The ::DrawText API function relies on a single rectangular area, whereas I have three potentially irregularly shaped areas (because I want to draw each sentence appended to each previous sentence, rather than beginning each sentence on a new line).

Some advice I got was that I probably need to use the more primitive CDC:TextOut method, together with CDC:SetTextAlign method. The TextOut method allows to draw a string starting at a specific position with the current font of the DC. However, TextOut does not automatically do wordwrap, so I may have to do wordwrap manually.

Can someone give me the Delphi code to achieve this?  The code has to run in a DLL that is callable by my VC++ activeX - so I hope that doesn't complicate things too much.
0
Comment
Question by:abulka
  • 10
  • 8
  • 3
  • +2
23 Comments
 
LVL 8

Expert Comment

by:ZifNab
ID: 2553888
Hi abulka,

have a look at the GetTextExtentExPoint and GetTextExtentPoint32 function

Regards, Zif.
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2553913
here is an example (of course you don't work with a memo canvas):

{Gets the TextWidth in pixels of a string if it was in the memo}
function TForm1.MemoTextWidth(Memo : TMemo; s : string) : integer;
 var
   p : pChar;
   dc : hDc;
   r : TRect;
   sz : TSize;
   OldFont : THandle;
begin
   Result := 0;
   if Length(s) = 0 then exit; {Exit if we have an empty string}
  {Copy the stirng to a pChar}
   GetMem(p, Length(s) + 1);
   StrPCopy(p, s);
   {Get the canvas of the memo}
    dc := GetDc(Memo.Handle);
   {Select the font into the canvas}
     OldFont := SelectObject(dc, Memo.Font.Handle);
   {Get the text width}
     GetTextExtentPoint(dc, p, length(s), sz);
   {Select the old font back into the canvas}
     SelectObject(dc, OldFont);
   {Release the memo's canvas}
     ReleaseDc(Memo1.Handle, dc);
   {Clean up and return the text width}
     FreeMem(p, Length(s) + 1);
     Result := sz.cx;
end;
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 2553919
another way for determing the text-width is

                              function GetTextWidth(Font: TFont; S: string): integer;
                               var
                                 Canvas: TCanvas;
                                 DC: HDC;
                               begin
                                 // create canvas
                                 Canvas := TCanvas.Create;
                                 // get DC for screen device
                                 DC := GetDC(0);
                                 try
                                   // make canvas use it
                                   Canvas.Handle := DC;
                                 
                                   // assign font to canvas
                                   Canvas.Font.Assign(Font);
                               
                                   // get textwidth from canvas
                                   Result := Canvas.TextWidth(S);
                                 finally
                                   // release DC again
                                   ReleaseDC(0, DC);
                                   Canvas.Handle := 0;
                                 end;
                                 // free resources
                                 Canvas.Free;
                               end;
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 5

Expert Comment

by:TheNeil
ID: 2554008
Abulka,

Try this routine. Setup the thre text strings (or as many as you need), setup the fonts, and the rectangle size, and off it should go. This will do the word wrapping and everything taht you need.

procedure TForm1.Button1Click(Sender: TObject);

  FUNCTION TextExt(DC : THandle; Text : STRING): TSize;
  begin
    Result.cX := 0;
    Result.cY := 0;
    Windows.GetTextExtentPoint32(DC, PChar(Text), Length(Text), Result);
  END;

VAR
  x          : LONGINT;
  y          : LONGINT;
  tx         : LONGINT;
  n          : LONGINT;
  m          : LONGINT;
  LineHeight : LONGINT;
  RectWidth  : LONGINT;
  RectLeft   : LONGINT;
  RectTop    : LONGINT;
  curWord    : STRING;
  curSent    : STRING;
  str        : ARRAY [1..3] OF STRING;
  Fonts      : ARRAY [1..3] OF TFont;
  stlStrings : TStringList;
  bmpTemp    : TBitmap;
  dc         : THandle;
BEGIN
  bmpTemp := TBitmap.Create;
  bmpTemp.Width := 200;
  bmpTemp.Height := 200;

  RectWidth := 200;
  RectLeft  := 100;
  RectTop   := 0;

  Str[1] := '102.';
  Str[2] := 'This is the second sentence, the number was the first.';
  Str[3] := 'This is the third sentence.';

  Fonts[1] := TFont.Create;
  Fonts[2] := TFont.Create;
  Fonts[3] := TFont.Create;
  Fonts[1].Name  := 'Arial';
  Fonts[1].Size  := 8;
  Fonts[1].Color := clBlack;
  Fonts[2].Assign(Fonts[1]);
  Fonts[3].Assign(Fonts[1]);

  Fonts[2].Color := clRed;

  dc := bmpTemp.Canvas.Handle;

  bmpTemp.Canvas.Font := Fonts[1];
  lineHeight := TextExt(dc, 'Aj').cy;
  bmpTemp.Canvas.Font := Fonts[2];
  IF TextExt(dc, 'Aj').cy > lineHeight
  THEN
    lineHeight := TextExt(dc, 'Aj').cy;
  bmpTemp.Canvas.Font := Fonts[3];
  IF TextExt(dc, 'Aj').cy > lineHeight
  THEN
    lineHeight := TextExt(dc, 'Aj').cy;

  stlStrings := TStringList.Create;
  x := 0;
  y := 0;
  FOR n := 1 TO 3
  DO
  BEGIN
    bmpTemp.Canvas.Font := Fonts[n];
    dc := bmpTemp.Canvas.Handle;

    IF TRIM(Str[n]) <> ''
    THEN
    BEGIN
      tx := x;
      curWord := '';
      curSent := '';
      stlStrings.Clear;
      FOR m := 1 TO Length(Str[n])
      DO
      BEGIN
        IF Str[n][m] = ' '
        THEN
        BEGIN
          IF (TextExt(dc, curSent + ' ' + curWord).cx + tx) > RectWidth
          THEN
          BEGIN
            stlStrings.Add(curSent);
            curSent := curword;
            tx := 0;
          END
          ELSE
            curSent := curSent + ' ' + curWord;
          curWord := '';
        END
        ELSE
          curWord := curWord + Str[n][m];
      END;

      IF curWord <> ''
      THEN
      BEGIN
        IF (TextExt(dc, curSent + ' ' + curWord).cx + tx) > RectWidth
        THEN
        BEGIN
          stlStrings.Add(curSent);
          curSent := curword;
        END
        ELSE
          curSent := curSent + ' ' + curWord;
        curWord := '';
      END;

      IF curSent <> ''
      THEN
        stlStrings.Add(curSent);

      FOR m := 0 TO (stlStrings.Count - 1)
      DO
      BEGIN
        TextOut(dc, RectLeft + x, RectTop + y, PCHAR(stlStrings[m]), Length(stlStrings[m]));

        x := 0;
        y := y + lineHeight;
      END;
      y := y - lineHeight;
      x := TextExt(dc, stlStrings[stlStrings.Count - 1]).cx
    END;
  END;

  stlStrings.Free;
  Image1.Canvas.Draw(0, 0, bmpTemp);
  bmpTemp.Free;

  Fonts[1].Free;
  Fonts[2].Free;
  Fonts[3].Free;
end;

The Neil
0
 

Author Comment

by:abulka
ID: 2560135
The Neil - thanks for the comprehensive code.  I pasted it in to Delphi 4 and plonked down an Timage component (which you seem to need) and it SORT OF WORKS.  Instead of

--------------------
| 102.  This is the
| second sentence,
| the number was the
| first.  This is the
| third sentence.
--------------------

I am getting

--------------------
| 102.  This is the seco
| number was the first
| sentence.
--------------------

??

Also - any thoughts on wrapping this delphi code in a dll and calling it from C++, passing in a DC and the 3 strings?  What happens to the delphi code's dependency on TImage?

-Andy
0
 
LVL 5

Expert Comment

by:TheNeil
ID: 2564241
Andy,

I know exactly wjhat is happening and the code is working fine. The initialising of the rectangle to draw the thing in in wrong.

  bmpTemp.Width := 200;
  bmpTemp.Height := 200;

  RectWidth := 200;
  RectLeft  := 100;

It's defined a drawing area 200 wide and a rectangle 200 wide BUT it's drawing the rectangle at 100 pixels in instead of 0. Either increase the width of the drawing area (bmpTemp.Width :=...) or move the position where the rectangle is being drawn (RectLeft := ...)

Believe me, this DOES work

The Neil
0
 

Author Comment

by:abulka
ID: 2566939
Adjusted points to 250
0
 

Author Comment

by:abulka
ID: 2566940
The Neil - I fiddled with RectLeft := and the code seems to work!  Thanks.

1. When I increase the font to 12/14 point the sentences start clipping and looking horrible.  Is there a fix for this?

2. Also, as mentioned in my original question, I am wanting to put your function in a DLL and call it from VC++.  I will pass in a DC and some strings.  So what happens to the current delphi code's dependency on TImage?  All I will have is a DC.

3. Finally, is there a way of getting the bounds of the resulting rect that was used to format the text?  The initial area I would want to pass to your function should 'autosize' the rect area and return the finished rect.
0
 

Author Comment

by:abulka
ID: 2567358
The Neil - I fiddled with RectLeft := and the code seems to work!  Thanks.

1. When I increase the font to 12/14 point the sentences start clipping and looking horrible.  Is there a fix for this?

2. Also, as mentioned in my original question, I am wanting to put your function in a DLL and call it from VC++.  I will pass in a DC and some strings.  So what happens to the current delphi code's dependency on TImage?  All I will have is a DC.

3. Finally, is there a way of getting the bounds of the resulting rect that was used to format the text?  The initial area I would want to pass to your function should 'autosize' the rect area and return the finished rect.
0
 
LVL 5

Expert Comment

by:TheNeil
ID: 2568023
I deliberately coded the routine to use device contexts. In my example code I'm outputting to a TImage but I only ever deal with the device context when manipulating the image, measuring text, outputting text etc. Close to the start of the routine I get the device context (placed in dc) and use that all the way through until I output the results to the display.

As for returning the final size of the rectangle then it should be possible. The width will never change so obviously you only need to return the new height. It's actually very easy to do, just insert the following line before the stringlist is destroyed:

Final_Height := y + line_height;

Your question about increasing the point size DOES create problems. The code can handle different font sizes easily but the problem comes in the way it text wraps. If a word is too long to fit on a line, it adds it to the NEXT line. If however it is too long for that line then it leaves it there and DOESN'T split it any further. What you need to do is make the rectangle wide enough to fit the longest word in. I know it's not an ideal solution but the alternative is to start splitting words and that's very tricky

The Neil
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 2574421
Listening
0
 

Author Comment

by:abulka
ID: 2586075
Thanks for your comments.  

> Your question about increasing the point size DOES create problems...What you need to do is make the rectangle wide enough to fit the longest word in.<<

I'm not sure this is going to work.  I mean - no matter how wide I define the rectangular output area to be, at around 14 pt I get clipping on BOTH the RHS margin and on the bottom of EACH letter.

1. Regarding the clipping occuring on the RHS - you say this will require more fancy word wrapping to be implemented. Surely we can calculate the space remaining and the space that will be needed by the particular word and output the word that will not fit on the next line instead? Isn't this what the algorithm is supposed to be basically doing anyway?

2. What worries me more is the clipping that occurs on the bottom of EACH CHARACTER (at 14pt and above).  It's like the vertical line spacing is being calculated wrongly, so each subsequent line is drawn slightly on top of the previous line.  

I haven't studied your algorithm in detail yet, but perhaps the vertical height of the characters is not being accurately calculated, or the spacing between lines is not being added into the equation?
0
 
LVL 3

Expert Comment

by:gandalf_the_white
ID: 2586726
listening
0
 
LVL 5

Expert Comment

by:TheNeil
ID: 2586887
The problem with word wrapping is not in my code and you have reached the same point as my code - if it finds a word that won't fit onto the end of the current line then it outputs it to the nect line...but what if that single word is too long for the next line? The code at the moment will just output it and it will get cut. To get around this you have to start splitting the text into letters not words.

Ok, as for clipping the text at the bottom, the code is supposed to be caculating the tallest piece of text (based on the 3 fonts), and use that height as the line height for ALL the text. Therefore it should have a gap if anything. I can't see what's up with it but if you want me to investigate it then I can (if I get a few spare minutes)

The Neil
0
 

Author Comment

by:abulka
ID: 2589533
Adjusted points to 300
0
 

Author Comment

by:abulka
ID: 2589534
>> ... if it finds a word that won't fit onto the end of the current line then it outputs it to the next line...<<

Mostly this works ok, but not always.  For example, short words like "all" and "me" at the RHS are clipped into "al" and "me" with half the "e" missing.  Try 14pt and 18 pt (I just change the one point in the code & re-run).

>> if that single word is too long for the next line? The code at the moment will just output it and it will get cut. <<

fair enough, I accept this limitation to the code.  It's the fragments of the little words being cut off that is worrying (see my first point).

>> Ok, as for clipping the text at the bottom, the code is supposed to be caculating the tallest piece of text <<

Again, if you could look at this glitch, I would appreciat it.

0
 
LVL 5

Expert Comment

by:TheNeil
ID: 2590758
Ok, I've checked the code and fixed the second problem. The first problem (word clipping) I can't reproduce. Can you tell me which sentences you're using, the rectangle dimensions etc.

Here's the code with the fixed line height calculation

procedure TForm1.Button1Click(Sender: TObject);

  FUNCTION TextExt(DC : THandle; Text : STRING): TSize;
  begin
    Result.cX := 0;
    Result.cY := 0;
    Windows.GetTextExtentPoint32(DC, PChar(Text), Length(Text), Result);
  END;

VAR
  x          : LONGINT;
  y          : LONGINT;
  tx         : LONGINT;
  n          : LONGINT;
  m          : LONGINT;
  LineHeight : LONGINT;
  RectWidth  : LONGINT;
  RectLeft   : LONGINT;
  RectTop    : LONGINT;
  curWord    : STRING;
  curSent    : STRING;
  str        : ARRAY [1..3] OF STRING;
  Fonts      : ARRAY [1..3] OF TFont;
  stlStrings : TStringList;
  bmpTemp    : TBitmap;
  dc         : THandle;
BEGIN
  bmpTemp := TBitmap.Create;
  bmpTemp.Width := 200;
  bmpTemp.Height := 400;

  RectWidth := 150;
  RectLeft  := 0;
  RectTop   := 0;

  Str[1] := '102.';
  Str[2] := 'This is the second sentence, the number was the first. Me I am.';
  Str[3] := 'This is the third sentence. Tiny be it.';

  Fonts[1] := TFont.Create;
  Fonts[2] := TFont.Create;
  Fonts[3] := TFont.Create;
  Fonts[1].Name  := 'Arial';
  Fonts[1].Size  := 18;
  Fonts[1].Color := clBlack;
  Fonts[2].Assign(Fonts[1]);
  Fonts[3].Assign(Fonts[1]);

  Fonts[2].Color := clRed;
  Fonts[2].Size  := 14;
  Fonts[3].Size  := 8;

  bmpTemp.Canvas.Font := Fonts[1];
  dc := bmpTemp.Canvas.Handle;
  lineHeight := TextExt(dc, 'Aj').cy;

  bmpTemp.Canvas.Font := Fonts[2];
  dc := bmpTemp.Canvas.Handle;
  IF TextExt(dc, 'Aj').cy > lineHeight
  THEN
    lineHeight := TextExt(dc, 'Aj').cy;

  bmpTemp.Canvas.Font := Fonts[3];
  dc := bmpTemp.Canvas.Handle;
  IF TextExt(dc, 'Aj').cy > lineHeight
  THEN
    lineHeight := TextExt(dc, 'Aj').cy;

  stlStrings := TStringList.Create;
  x := 0;
  y := 0;
  FOR n := 1 TO 3
  DO
  BEGIN
    bmpTemp.Canvas.Font := Fonts[n];
    dc := bmpTemp.Canvas.Handle;

    IF TRIM(Str[n]) <> ''
    THEN
    BEGIN
      tx := x;
      curWord := '';
      curSent := '';
      stlStrings.Clear;
      FOR m := 1 TO Length(Str[n])
      DO
      BEGIN
        IF Str[n][m] = ' '
        THEN
        BEGIN
          IF (TextExt(dc, curSent + ' ' + curWord).cx + tx) > RectWidth
          THEN
          BEGIN
            stlStrings.Add(curSent);
            curSent := curword;
            tx := 0;
          END
          ELSE
            curSent := curSent + ' ' + curWord;
          curWord := '';
        END
        ELSE
          curWord := curWord + Str[n][m];
      END;

      IF curWord <> ''
      THEN
      BEGIN
        IF (TextExt(dc, curSent + ' ' + curWord).cx + tx) > RectWidth
        THEN
        BEGIN
          stlStrings.Add(curSent);
          curSent := curword;
        END
        ELSE
          curSent := curSent + ' ' + curWord;
        curWord := '';
      END;

      IF curSent <> ''
      THEN
        stlStrings.Add(curSent);

      FOR m := 0 TO (stlStrings.Count - 1)
      DO
      BEGIN
        TextOut(dc, RectLeft + x, RectTop + y, PCHAR(stlStrings[m]), Length(stlStrings[m]));

        x := 0;
        y := y + lineHeight;
      END;
      y := y - lineHeight;
      x := TextExt(dc, stlStrings[stlStrings.Count - 1]).cx
    END;
  END;

  stlStrings.Free;
  Image1.Canvas.Draw(0, 0, bmpTemp);
  bmpTemp.Free;

  Fonts[1].Free;
  Fonts[2].Free;
  Fonts[3].Free;
end;

The Neil
0
 

Author Comment

by:abulka
ID: 2590865
Re: the first clipping problem: this is the code fragment I have that contains the rect/text strings:

BEGIN
  bmpTemp := TBitmap.Create;
{
  bmpTemp.Width := 200;
  bmpTemp.Height := 200;

  RectWidth := 200;
  RectLeft  := 100;
}
  bmpTemp.Width := 200;
  bmpTemp.Height := 200;

  RectWidth := 200;
  RectLeft  := 5;

  RectTop   := 0;

  Str[1] := '102.';
  Str[2] := 'This is the second sentence, the number was the first.';
  Str[3] := 'This is the third sentence. I hope you don''t mind me typing this and talking about all sorts of things, whilst the formatting algorithm does its thing.  Wow I hope this works ok.';

  Fonts[1] := TFont.Create;
  Fonts[2] := TFont.Create;
  Fonts[3] := TFont.Create;
  Fonts[1].Name  := 'Arial';
  Fonts[1].Size  := 14;
  Fonts[1].Color := clBlack;
  Fonts[2].Assign(Fonts[1]);
  Fonts[3].Assign(Fonts[1]);

------------------

Mucking around with various font sizes should generate the problem.  I am running at 1024x768.

By the way, my form is

object Form1: TForm1
  Left = 192
  Top = 107
  Width = 696
  Height = 480
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Image1: TImage
    Left = -1
    Top = 0
    Width = 283
    Height = 187
  end
  object Button1: TButton
    Left = 402
    Top = 201
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
end

------------------
0
 
LVL 5

Expert Comment

by:TheNeil
ID: 2591013
Spotted what you're doing wrong. The code is doing exactly what it's supposed to do. You set the left of the rectangle (RectLeft) to 5. You either need to set it to zero OR set the width of the rectangle to 205. The width of the bitmap needs to be RectLeft + RectWidth otherwise you get text clipping happening.

This is because I set the size of the bitmap to be close to the size of the rectangle. If you define the bitmap to be something big (640x480) then you wouldn't have noticed the problem. Sorry

The Neil =:)
0
 

Author Comment

by:abulka
ID: 2598578
The code is looking pretty good now.  I was about to accept when just for fun I tried out the following strings:
  Str[1] := 'hi';
  Str[2] := 'there';
  Str[3] := 'everyone';

and saw that the word 'there' was being chopped off into 'the' !!?  So I see
 'hi the everyone'

0
 
LVL 5

Accepted Solution

by:
TheNeil earned 1200 total points
ID: 2599868
Oops. I've hunted through found out what the problem was. Just in case you care, the code was resetting the x position to the length of the previous line of text BUT because all three were fitting on one line, the x position was being set to the length of the second piece of text and forgetting about the first piece of text. Oops (again).

Here's the complete (hopefully perfect) routine:

procedure TForm1.Button1Click(Sender: TObject);

  FUNCTION TextExt(DC : THandle; Text : STRING): TSize;
  begin
    Result.cX := 0;
    Result.cY := 0;
    Windows.GetTextExtentPoint32(DC, PChar(Text), Length(Text), Result);
  END;

VAR
  x          : LONGINT;
  y          : LONGINT;
  tx         : LONGINT;
  n          : LONGINT;
  m          : LONGINT;
  LineHeight : LONGINT;
  RectWidth  : LONGINT;
  RectLeft   : LONGINT;
  RectTop    : LONGINT;
  curWord    : STRING;
  curSent    : STRING;
  str        : ARRAY [1..3] OF STRING;
  Fonts      : ARRAY [1..3] OF TFont;
  stlStrings : TStringList;
  bmpTemp    : TBitmap;
  dc         : THandle;
BEGIN
  bmpTemp := TBitmap.Create;
  bmpTemp.Width := 200;
  bmpTemp.Height := 400;

  RectWidth := 150;
  RectLeft  := 0;
  RectTop   := 0;

  Str[1] := '102.';
  Str[2] := 'This is the second sentence, the number was the first. Me I am.';
  Str[3] := 'This is the third sentence. Tiny be it.';

//  Str[1] := 'hi';
//  Str[2] := 'there';
//  Str[3] := 'everyone';

  Fonts[1] := TFont.Create;
  Fonts[2] := TFont.Create;
  Fonts[3] := TFont.Create;
  Fonts[1].Name  := 'Arial';
  Fonts[1].Size  := 18;
  Fonts[1].Color := clBlack;
  Fonts[2].Assign(Fonts[1]);
  Fonts[3].Assign(Fonts[1]);

  Fonts[2].Color := clRed;
  Fonts[2].Size  := 14;
  Fonts[3].Size  := 8;

  bmpTemp.Canvas.Font := Fonts[1];
  dc := bmpTemp.Canvas.Handle;
  lineHeight := TextExt(dc, 'Aj').cy;

  bmpTemp.Canvas.Font := Fonts[2];
  dc := bmpTemp.Canvas.Handle;
  IF TextExt(dc, 'Aj').cy > lineHeight
  THEN
    lineHeight := TextExt(dc, 'Aj').cy;

  bmpTemp.Canvas.Font := Fonts[3];
  dc := bmpTemp.Canvas.Handle;
  IF TextExt(dc, 'Aj').cy > lineHeight
  THEN
    lineHeight := TextExt(dc, 'Aj').cy;

  stlStrings := TStringList.Create;
  x := 0;
  y := 0;
  FOR n := 1 TO 3
  DO
  BEGIN
    bmpTemp.Canvas.Font := Fonts[n];
    dc := bmpTemp.Canvas.Handle;

    IF TRIM(Str[n]) <> ''
    THEN
    BEGIN
      tx := x;
      curWord := '';
      curSent := '';
      stlStrings.Clear;
      FOR m := 1 TO Length(Str[n])
      DO
      BEGIN
        IF Str[n][m] = ' '
        THEN
        BEGIN
          IF (TextExt(dc, curSent + ' ' + curWord).cx + tx) > RectWidth
          THEN
          BEGIN
            stlStrings.Add(curSent);
            curSent := curword;
            tx := 0;
          END
          ELSE
            curSent := curSent + ' ' + curWord;
          curWord := '';
        END
        ELSE
          curWord := curWord + Str[n][m];
      END;

      IF curWord <> ''
      THEN
      BEGIN
        IF (TextExt(dc, curSent + ' ' + curWord).cx + tx) > RectWidth
        THEN
        BEGIN
          stlStrings.Add(curSent);
          curSent := curword;
        END
        ELSE
          curSent := curSent + ' ' + curWord;
        curWord := '';
      END;

      IF curSent <> ''
      THEN
        stlStrings.Add(curSent);

      FOR m := 0 TO (stlStrings.Count - 1)
      DO
      BEGIN
        TextOut(dc, RectLeft + x, RectTop + y, PCHAR(stlStrings[m]), Length(stlStrings[m]));

        IF (stlStrings.Count - 1) > 0
        THEN
          x := 0;
        y := y + lineHeight;
      END;
      y := y - lineHeight;

      IF (stlStrings.Count - 1) > 0
      THEN
        x := TextExt(dc, stlStrings[stlStrings.Count - 1]).cx
      ELSE
        x := x + TextExt(dc, stlStrings[stlStrings.Count - 1]).cx;
    END;
  END;

  stlStrings.Free;
  Image1.Canvas.Draw(0, 0, bmpTemp);
  bmpTemp.Free;

  Fonts[1].Free;
  Fonts[2].Free;
  Fonts[3].Free;
end;

The Neil
0
 

Author Comment

by:abulka
ID: 2602881
Seems to work great now.  Thanks!
0
 
LVL 5

Expert Comment

by:TheNeil
ID: 2603713
It took some doing but thanks for the points

The Neil =:)
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…
Suggested Courses

926 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question