【问题标题】:Calculating size of text before drawing to a canvas在绘制到画布之前计算文本的大小
【发布时间】:2011-12-04 20:43:55
【问题描述】:

我正在使用 Delphi 7。我非常熟悉使用画布和在画布上绘制文本,以及使用 TCanvas.TextHeight 等。当我想实现自动换行时就会出现问题。我不仅需要将文本绘制到画布上并使其自动换行到给定宽度约束的最佳方法,而且我还需要知道它在换行后的高度(或行数)。我需要在绘制文本之前准备另一个图像,该图像需要足够大以放置包装的文本。这是一个尝试复制 iPhone 显示 SMS 消息的方式,在可变高度滚动框中的屏幕两侧都有一个气球(TScrollingWinControl 是我的基础)。

【问题讨论】:

  • 使用DrawText,让系统自动换行

标签: delphi canvas delphi-7 word-wrap


【解决方案1】:

使用(几乎)无所不能的DrawText 函数,使用初始矩形,以及标志DT_WORDBREAK(意味着字符串应该是自动换行)和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;

由于标志DT_CALCRECT,第一个DrawText不会绘制任何东西,只会改变r的高度,使其可以包含整个字符串S(或减少r的宽度如果S 恰好适合单行;另外,如果S 包含不适合单行的单词,则r 的宽度将增加)。然后你可以用r做任何你想做的事情,然后你就可以真正地绘制字符串了。

试试这个,例如:

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;

【讨论】:

  • 嗨安德烈亚斯 - 像往常一样的好答案!
猜你喜欢
  • 2015-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-08
  • 2023-03-09
  • 1970-01-01
  • 2011-10-28
相关资源
最近更新 更多