0

I am trying to draw a word-wrapped string within centered both vertically and horizontally within a bitmap using WinAPI's DrawText function.

The problem is that if text is longer than the available space and "END ELLIPSIS" (...) is added to a cropped string, the reported drawing coordinates returned when using the "DT_CALCRECT" report the uncropped number of lines which messes with the vertical centering calculations.

I read many posts on this, and thought that "Delphi - Draw text multiline in the centre of a rect" may hold the answer, but it didn't (screenshot of the code output using the sample in the linked question http://zoomplayer.com/pix/font_vcenter.jpg). The author of the accepted answer suggested I create a new question so here it is.

For quick-reference, here is a slightly simplified (removing unrelated code) text rendering code from the linked accepted answer:

procedure DrawTextCentered(Canvas: TCanvas; const R: TRect; S: String);
var
  DrawRect: TRect;
  DrawFlags: Cardinal;
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;
  DrawTextEx(Canvas.Handle, PChar(S), -1, DrawRect, DrawFlags, nil);
end;

As you can see from the screenshot, the problem is after the initial call to DrawText with the "DT_CALCRECT" flag to measure the output height for later vertical centering, rendering the string "Trending in: Worldwide" returns a DrawRect.Bottom value representing 3 lines of text even though only 2 lines are drawn, breaking the vertical centering code.

bLight
  • 803
  • 7
  • 23
  • Not sure this works out, but try passing the `DT_MODIFYSTRING` flag on the first call, and repeat the `DrawText` call to calculate the bounding rectangle, in case the string has been updated (indicating truncation). That is assuming, that `DT_CALCRECT` and `DT_MODIFYSTRING` are in fact compatible, although the documentation doesn't indicate otherwise. – IInspectable Jun 07 '17 at 10:07
  • That is what the documentation promises it does, "and extends the base of the rectangle to bound the last line of text". Don't ignore the return value. – Hans Passant Jun 07 '17 at 10:09
  • @IInspectable I tried that, but for some reason it did not modify the string (maybe a clue?) – bLight Jun 07 '17 at 10:10
  • @HansPassant Yes, but supposedly only for lines that are actually drawn, if you look at the sample image, the text is cropped and "..." added at the end of the second line, so no third line is drawn but the returning coordinates are as if it was drawn, preventing me from measuring the draw area. – bLight Jun 07 '17 at 10:13

0 Answers0