procedure WordWrappedImage(var APaintBox: TPaintBox; const AFont: TFont; const AText: AnsiString; const ABackground, ABorder, ATransparent: TColor; const ACentered: Boolean = False);
var
bmp: TBitmap;
sa: TStringArray;
s: string;
i: Integer;
PosY, Padding: Integer;
begin
// create a bitmap on the fly
bmp := TBitmap.Create;
try
// set size to paintbox
bmp.SetSize(APaintBox.Width, APaintBox.Height);
// set fake transparent color
bmp.Canvas.Brush.Color := ATransparent;
// fill image with above fake color so we dont have "black" corners
bmp.Canvas.FillRect(bmp.Canvas.ClipRect);
// set real background color and draw rounded corner style like Handoko showed, just adjusted for this example
bmp.Canvas.Brush.Color := ABackground;
bmp.Canvas.Pen.Style := psDash;
bmp.Canvas.Pen.Width := 1; // i prefer a small line around, adjust to your needs
bmp.Canvas.Pen.Color := ABorder;
bmp.Canvas.RoundRect(bmp.Canvas.ClipRect, 15, 15); // adjust the numbers, higher values = bigger corner angle, you can also play with two different values like 15 and 30 to get a different shaped corner
// set font, including color and any set style(s)
bmp.Canvas.Font := AFont;
// space that stay free around text
Padding := 5;
// vertical counter
PosY := Padding;
// temporal string
s := '';
// convert the text to an array of words by splitting them at spaces or lineendings
sa := AText.Split([' ', #10, #13]);
// draw text wordwrapped on image
// this method fails if a word is bigger than the image got space
for i := Low(sa) to High(sa) do
begin
// assign some word to draw for a new line
if s = '' then
s := sa[i]
else
// or begin testing if the collection of words are fitting into the image
begin
// add more words to current line
if (bmp.Canvas.TextWidth(s + ' ' + sa[i]) < (bmp.Width - Padding)) then
s := s + ' ' + sa[i]
else
begin
// draw current line
if ACentered then
bmp.Canvas.TextOut((bmp.Width - bmp.Canvas.TextWidth(s)) div 2, PosY, s)
else
bmp.Canvas.TextOut(Padding, PosY, s);
Inc(PosY, bmp.Canvas.TextHeight(s));
// check if we are in bounds of image
// everything that not fit anymore will be skipped
if ((PosY + bmp.Canvas.TextHeight(s)) > (bmp.Height - Padding)) then
break;
// assign the last word that not fitted for the next line
s := sa[i];
end;
end;
// if it is just one line, draw it
if (s <> '') then
if ACentered then
bmp.Canvas.TextOut((bmp.Width - bmp.Canvas.TextWidth(s)) div 2, PosY, s)
else
bmp.Canvas.TextOut(Padding, PosY, s);
end;
// give the prepared image to the paintbox
APaintBox.Canvas.Draw(0, 0, bmp);
finally
bmp.Free;
end;
end;