Obliczanie rozmiaru tekstu przed rysowaniem na płótnie

Używam Delphi 7. Jestem bardziej niż zaznajomiony z używaniem płótna i rysowaniem tekstu na płótnie, a także używaniem TCanvas.TextHeight itp. Problem pojawia się, gdy chcę zaimplementować Zawijanie Worda. Nie tylko potrzebuję najlepszego sposobu rysowania tekstu na płótnie i automatycznego zawijania go do określonego ograniczenia szerokości, ale także muszę wiedzieć, jak wysoko (lub ile linii)będzie po zawinięciu. Zanim narysuję tekst, muszę przygotować inny obrazek, który musi być wystarczająco duży, aby umieść zawinięty tekst. Jest to próba powtórzenia, jak iPhone wyświetla wiadomości SMS, z balonem po obu stronach ekranu w zmiennej wysokości przewijania pole (TScrollingWinControl jest moją bazą).

Author: Jerry Dodge, 2011-10-11

1 answers

Użyj (prawie) Wszechmocnego DrawText funkcja wykorzystująca początkowy prostokąt oraz flagi DT_WORDBREAK (co oznacza, że łańcuch powinien być zawinięty wyrazem) i DT_CALCRECT:

procedure TForm1.FormPaint(Sender: TObject);
const
  S = 'This is a sample text, I think, is it not?';
var
  r: TRect;
begin
  r := Rect(10, 10, 60, 60);
  DrawText(Canvas.Handle,
    PChar(S),
    Length(S),
    r,
    DT_LEFT or DT_WORDBREAK or DT_CALCRECT);

  DrawText(Canvas.Handle,
    PChar(S),
    Length(S),
    r,
    DT_LEFT or DT_WORDBREAK);
end;

Ze względu na flagę DT_CALCRECT, Pierwsza DrawText nie rysuje niczego, a jedynie zmienia wysokość r tak, aby mogła zawierać cały ciąg S (lub zmniejszyć szerokość r, Jeśli S pasuje do pojedynczej linii; ponadto, jeśli S zawiera słowo, które nie pasuje do pojedynczej linii, szerokość linii nie może być mniejsza niż szerokość linii. r zostanie zwiększona). Potem możesz robić co chcesz z r, a potem możesz narysować ciąg na serio.

Spróbuj tego, na przykład:

procedure TForm1.FormPaint(Sender: TObject);
const
  S: array[0..3] of string = ('Hi! How are you?',
    'I am fine, thanks. How are you? How are your kids?',
    'Fine!',
    'Glad to hear that!');
  Colors: array[boolean] of TColor = (clMoneyGreen, clSkyBlue);
  Aligns: array[boolean] of integer = (DT_RIGHT, DT_LEFT);
var
  i, y, MaxWidth, RectWidth: integer;
  r, r2: TRect;
begin

  y := 10;
  MaxWidth := ClientWidth div 2;

  for i := low(S) to high(S) do
  begin

    Canvas.Brush.Color := Colors[Odd(i)];

    r := Rect(10, y, MaxWidth, 16);
    DrawText(Canvas.Handle,
      PChar(S[i]),
      Length(S[i]),
      r,
      Aligns[Odd(i)] or DT_WORDBREAK or DT_CALCRECT);

    if not Odd(i) then
    begin
      RectWidth := r.Right - r.Left;
      r.Right := ClientWidth - 10;
      r.Left := r.Right - RectWidth;
    end;

    r2 := Rect(r.Left - 4, r.Top - 4, r.Right + 4, r.Bottom + 4);
    Canvas.RoundRect(r2, 5, 5);

    DrawText(Canvas.Handle,
      PChar(S[i]),
      Length(S[i]),
      r,
      Aligns[Odd(i)] or DT_WORDBREAK);

    y := r.Bottom + 10;

  end;

end;

procedure TForm1.FormResize(Sender: TObject);
begin
  Invalidate;
end;

Zrzut ekranu http://privat.rejbrand.se/DrawTextChat.png

 33
Author: Andreas Rejbrand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-10 22:40:54