如何最好地以编程方式判断TLabel的标题是否被剪裁(即使用省略号绘制)?

我有一个
TLabel
EllipsisPosition
设置为
epEndEllipsis
,我需要能够判断文本当前是否被剪裁。除了计算自己显示文本所需的区域并将其与标签的实际尺寸进行比较之外,还有人想出一个更简单/更优雅的方法吗? 实际上,以故障安全方式计算所需区域似乎也不像听起来那么直接......例如,
TCanvas.GetTextHeight
不考虑换行符。
TCustomLabel.DoDrawText
在内部使用
DrawTextW
DrawThemeTextEx
DT_CALCRECT
标志来确定是否应使用省略号。那里涉及了很多代码,所有代码都被声明为
private
。简单地复制所有代码并不完全符合我书中的“优雅”...... 有任何想法吗? (我正在使用Delphi 2010以防任何人提出特定于Delphi版本的解决方案) 更新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设置),它还可以正确处理多行和自动换行的输入文本。请注意,在这种情况下,“正确”意味着“当使用剪切的标题绘制
TLabel
时,它总是返回
True
,否则为
False
”。 虽然上面的代码完成了我最初的要求,但我可能不会这样使用它 - 但这更多是由于
TLabel
本身的缺点:特别是对于多行文本,它通常不会按照我想要的方式运行,例如当没有足够的空间用于多行时,第一行的最后一个单词将始终被截断,即使整行加上省略号也适合。     

bab

作为起点,你可以使用
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;
使用这种技术编写具有
WasClipped
属性的
TExtLabel
组件并不困难。实际上,
TLabel
组件是VCL中最简单的组件之一 - 它只是绘制一个字符串。     

要回复问题请先登录注册