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.Han dle, PChar(TEXT), Length(TEXT), MyRect, Flags);
end;
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.Han
end;
ASKER
thanks aikimark,
but my question is how to change the width between the lines of the spacing between the lines. :)
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.
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.
ASKER
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! :)
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.
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
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
1. replace the DrawText area with the visible RTF control
2. copy the RTF object's canvas to your Image1.Canvas
hello dabestprogrammerindauniver se , , 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.Han dle, PChar(TextStr),Length(Text Str),182,
@numChar, nil, aSize);
TextOut(Bmp1.canvas.handle ,3,(lines* (aSize.cy+ 8))+3,PCha r(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
procedure TForm1.but_CustomTextClick
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.
@numChar, nil, aSize);
TextOut(Bmp1.canvas.handle
// 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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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.TextHeig