绘制画布之前计算文本的大小 [英] Calculating size of text before drawing to a canvas
问题描述
我使用的是Delphi 7.我比以前熟悉使用画布和绘图文本,并使用TCanvas.TextHeight等。当我想实现Word Wrap时,会出现问题。我不仅需要最好的方法来将文本绘制到画布上,而且可以自动将其包装到给定的宽度约束,但是我也需要知道它被包装后会有多高(或多少行)。在绘制文本之前,我需要准备另一张图像,这个图像需要足够大才能放置文本。这是一个尝试复制iPhone如何显示短信,在一个可变高度滚动框(TScrollingWinControl是我的基础)中的屏幕两边的一个baloon。
I'm using Delphi 7. I'm more than familiar with using a canvas and drawing text to a canvas, and also using TCanvas.TextHeight etc. The problem arises when I want to implement Word Wrap. Not only do I need the best way to draw text to a canvas and have it automatically wrap to a given width constraint, but I also need to know how high (or how many lines) it will be after it's wrapped. I need to prepare another image before I draw the text, an image which needs to be just big enough to place the wrapped text. This is an attempt to replicate how an iPhone displays SMS messages, with a baloon on either side of the screen in a variable height scrolling box (TScrollingWinControl is my base).
推荐答案
使用(几乎)全能的 DrawText
函数使用初始矩形,标志 DT_WORDBREAK
(意味着字符串应该是文字包装的)和 DT_CALCRECT
:
Use the (almost) omnipotent DrawText
function using an initial rectangle, and the flags DT_WORDBREAK
(meaning that the string should be word-wrapped) and 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
做任何你想要的,然后你可以绘制字符串为真。
Due to the flag DT_CALCRECT
, the first DrawText
will not draw anything, but only alter the height of r
so that it can contain the entire string S
(or reduce the width of r
if S
happens to fit on a single line; in addition, if S
contains a word that does not fit on a single line, the width of r
will be increased). Then you can do whatever you wish with r
, and then you can draw the string for real.
尝试这个,例如:
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;
屏幕截图http://privat.rejbrand.se/DrawTextChat.png
这篇关于绘制画布之前计算文本的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!