9
votes

In Delphi i wish to draw text inside a TRect. I am hoping for the following functionality:

  1. Draw the text centred vertically within the TRect
  2. Draw the text centred horizontally within the TRect
  3. If there is space for more than 1 line of text (using TRect's height), draw the text multiline
  4. If the text does not fit in the TRect (either on a single or mult line) then append ellipsis to the text.

I can see the Windows.DrawText() function almost covers this functionality, however when writing text, multiline and vertically centred are mutually exclusive.

I was wondering if this functionality is built into windows (2000+)? If not is there a way to do this without writing my own function?

2
Can't you use TLabel? I think it has all the functionality required.Andriy M
Yes it probably does, but i do not want to use a label, i have a canvas to draw on.Simon

2 Answers

20
votes

Sorry, this is a combination of all previous answers and comments. But it seems OP needs more assistance.

function DrawTextCentered(Canvas: TCanvas; const R: TRect; S: String): Integer;
var
  DrawRect: TRect;
  DrawFlags: Cardinal;
  DrawParams: TDrawTextParams;
begin
  DrawRect := R;
  DrawFlags := DT_END_ELLIPSIS or DT_NOPREFIX or DT_WORDBREAK or
    DT_EDITCONTROL or DT_CENTER;
  DrawText(Canvas.Handle, PChar(S), -1, DrawRect, DrawFlags or DT_CALCRECT);
  DrawRect.Right := R.Right;
  if DrawRect.Bottom < R.Bottom then
    OffsetRect(DrawRect, 0, (R.Bottom - DrawRect.Bottom) div 2)
  else
    DrawRect.Bottom := R.Bottom;
  ZeroMemory(@DrawParams, SizeOf(DrawParams));
  DrawParams.cbSize := SizeOf(DrawParams);
  DrawTextEx(Canvas.Handle, PChar(S), -1, DrawRect, DrawFlags, @DrawParams);
  Result := DrawParams.uiLengthDrawn;
end;

procedure TForm1.FormPaint(Sender: TObject);
const
  S = 'This is a very long text as test case for my paint routine.';
var
  R: TRect;
begin
  SetRect(R, 100, 100, 200, 140);
  Canvas.Rectangle(R);
  InflateRect(R, -1, -1);
  Caption := Format('%d characters drawn', [DrawTextCentered(Canvas, R, S)]);
end;
5
votes

Measure the text first using DT_CALCRECT. Pass DT_WORDBREAK to specify that word wrapping is enabled. This will allow you to find the required height for your text. Then you can, in your code, calculate the vertical offset that gives you vertically centred text, and draw to that offset.