如何最好地判断tlabel的标题是否被剪辑(即使用省略号绘制)?
题
我有一个 TLabel
和 EllipsisPosition
设置 epEndEllipsis
而且我需要能够分辨出文本当前是否已剪辑。除了计算自己显示文本所需的区域并将其与标签的实际尺寸进行比较之外,有人是否提出了一种更轻松/更优雅的方法?
实际上,以故障安全的方式计算所需区域也似乎并不像听起来很简单...例如 TCanvas.GetTextHeight
没有考虑到线路。
TCustomLabel.DoDrawText
内部使用 DrawTextW
或者 DrawThemeTextEx
与 DT_CALCRECT
标志以确定是否应该使用省略号。那里涉及很多代码,所有这些都被宣布为 private
. 。简单地复制所有代码不会在我的书中完全符合“优雅”的资格...
有任何想法吗?
(我正在使用Delphi 2010,以防任何人提出特定于Delphi-version的解决方案)
更新1: 我现在发现我可以简单地打电话 TCustomLabel.DoDrawText(lRect, DT_CALCRECT)
直接(仅声明 protected
)让标签执行所需的尺寸计算,而无需重复其代码。我只需要确保暂时设置 EllipsisPosition
到 epNone
或完全使用临时标签实例。实际上,这还不错,如果没有人能想到一个更简单的解决方案,我可能会选择它。
更新2: 我现在添加了解决方案作为单独的答案。事实证明,它比我预期的要简单明了,因此可能没有更容易/更好的方法可以做到这一点,但是我将这个问题打开了一会儿,无论如何,以防万一。
解决方案
fwiw,这是我想到的(这是一种自定义的方法 TLabel
-后裔):
function TMyLabel.IsTextClipped: Boolean;
const
EllipsisStr = '...';
var
lEllipBup: TEllipsisPosition;
lRect: TRect;
begin
lRect := ClientRect;
Dec(lRect.Right, Canvas.TextWidth(EllipsisStr));
lEllipBup := EllipsisPosition;
EllipsisPosition := epNone;
try
DoDrawText(lRect, DT_CALCRECT or IfThen(WordWrap, DT_WORDBREAK));
finally
EllipsisPosition := lEllipBup;
end;
Result := ((lRect.Right - lRect.Left) > ClientWidth)
or ((lRect.Bottom - lRect.Top) > ClientHeight);
end;
因为现在使用与 TCustomLabel.DoDrawText
(尤其是人工填充和正确的Wordwrap设置)它还正确处理了多行和文字包裹的输入文本。请注意,在这种情况下“正确”的意思是“它总是返回 True
当。。。的时候 TLabel
用剪裁的标题绘制 False
除此以外”。
虽然上面的代码按照我最初要求的内容,但我可能不会以这种方式使用它 - 但这更多是由于缺点 TLabel
本身:尤其是使用多行文本,它通常不会像我想要的那样行事,例如,如果没有足够的空间,那么第一行的最后一句话也将始终被截断省略号会安装。
其他提示
作为起点,您可以使用
function DrawStringEllipsis(const DC: HDC; const ARect: TRect; const AStr: string): boolean;
var
r: TRect;
s: PChar;
begin
r := ARect;
GetMem(s, length(AStr)*sizeof(char) + 8);
StrCopy(s, PChar(AStr));
DrawText(DC, PChar(s), length(AStr), r, DT_LEFT or DT_END_ELLIPSIS or DT_MODIFYSTRING);
result := not SameStr(AStr, s);
FreeMem(s);
end;
示例用法:
procedure TForm1.FormClick(Sender: TObject);
begin
Caption := 'Clipped ' + BoolToStr(DrawStringEllipsis(Canvas.Handle, Rect(10, 100, 50, 50), 'This is a text.'), true);
end;
写一个 TExtLabel
具有一个 WasClipped
使用此技术的属性。确实, TLabel
组件是VCL中最简单的组件之一 - 它只是绘制一个字符串。