Link to home
Start Free TrialLog in
Avatar of dabestprogrammerindauniverse
dabestprogrammerindauniverse

asked on

Changing Text Line Spacing using Windows API

Hi everyone,

I am currently programming in delphi and drawing text on a Canvas using the DrawText windows API.
The method can draw text and wrap it inside a specified Rectangle. The problem is that I can't modify the
vertical spacing between lines once the text wraps. anyone knows how? Thanks in advance!
:)

Here's my code:
const
   TEXT = 'The quick brown fox jumped over the sly lazy dog.';
var
   Flags : integer;
   MyRect : TRect;
begin
   Flags := DT_WORDBREAK;
   MyRect := Rect(0,0,20,20);
   DrawText(Image1.Canvas.Handle, PChar(TEXT), Length(TEXT), MyRect, Flags);
end;
Avatar of aikimark
aikimark
Flag of United States of America image

include the DT_CALCRECT flag value to have the DrawText function return the height of the text.
http://www.undu.com/Articles/010129a.html
http://www.undu.com/Articles/981008d.html

You can also get the height (in pixels) of the current font settings with:
Th:=Image1.Canvas.TextHeight('Xg');        {Height of current font in pixels}
Avatar of dabestprogrammerindauniverse
dabestprogrammerindauniverse

ASKER

thanks aikimark,
but my question is how to change the width between the lines of the spacing between the lines. :)
you might have to roll-your-own line wrapping:
Loop through the words in the string, appending each word (to be written to your canvas) until the temporary string is larger than the rectangle you wish to draw.  

Remove the last word added (or hyphenate it, which is a more advanced technique and more difficult).

Write the string to the canvas

Reset the string variable

Move the CurrentY position of the canvas down by some multiplier of the height of the fontsize.

Start appending new words with the next iteration of the loop until you have written all the words.
Yup, I figured that out. Also, in case a line consists of only one word whose width is wider than the specified rect, then the clipping should be on a per character basis. So there isn't any other way is there?
thanks! :)
I do not know of any property, method, or API that would allow you do this easily.

Here's an interesting idea for you to explore:
1. Use DrawText to automatically wrap your text
2. save the characters or character images from each line into a data structure
3. Clear the drawing area rectangle
4. increase the height of the drawing area by the
number_of_lines * (inter_line_space_increase - 1)
5. loop through your saved lines and print/draw them at the appropriate location.

============
I've never written a hyphenation routine, so can't give you much help on that topic.
Another thought would be to use a Rich Text Format object to do the wrapping and inter-line spacing for you and do either of the following:
1. replace the DrawText area with the visible RTF control
2. copy the RTF object's canvas to your Image1.Canvas
hello  dabestprogrammerindauniverse , , I have used the  GetTextExtentExPoint( ) function to get a Line break distance, like this -



procedure TForm1.but_CustomTextClick(Sender: TObject);
var
TextStr: String;
Bmp1: TBitmap;
numChar, lines: Integer;
aSize: tagSize;
begin
// button click event
TextStr := 'This is a text string long enough to wrap a couple of times. And '+
           'More text here, followed by even more text  followed by eveen more text'+
           ' followed by even more text  followed by even moore text';
Bmp1 := TBitmap.Create;
try
  Bmp1.Width := 188;// try to have a 3 pixel border, use 182 below
  Bmp1.Height := 210;
  Bmp1.Canvas.Font.Name := 'Arial';
  Bmp1.Canvas.Font.Size := 12;

  if Length(TextStr) < 1 then Exit;
  lines := 0;
  repeat
  GetTextExtentExPoint(Bmp1.Canvas.Handle, PChar(TextStr),Length(TextStr),182,
                     @numChar, nil, aSize);
  TextOut(Bmp1.canvas.handle,3,(lines*(aSize.cy+8))+3,PChar(TextStr), numChar);
                                              // use the y postion above to adjust the custom spacing per line
  Delete(TextStr,1,numChar);
  Inc(Lines);
  until Length(TextStr) < 1;

  Canvas.Draw(530,290, Bmp1);
  finally
  FreeAndNil(Bmp1);
  end;
end;


 = = = = = = = = = = = = = =  = = = = = = =  =
this seems to work for me, however this does NOT find spaces and punctuation to divide the words, it will chop a word anywhere
  ask questions if you need more
ASKER CERTIFIED SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial