如何最好地以编程方式判断 TLabel 的标题是否被剪裁(即使用省略号绘制)?
我有一个 TLabel
,其中 EllipsisPosition
设置为 epEndEllipsis
,我需要能够判断文本当前是否被剪切。除了自己计算显示文本所需的面积并将其与标签的实际尺寸进行比较之外,有没有人想出一种更简单/更优雅的方法来做到这一点?
实际上,以自动防故障的方式计算所需区域似乎也不像听起来那么简单……例如,TCanvas.GetTextHeight
不考虑换行符。
TCustomLabel.DoDrawText
在内部使用 DrawTextW
或 DrawThemeTextEx
以及 DT_CALCRECT
标志来确定是否应使用省略号与否。这里涉及到相当多的代码,所有这些代码都被声明为私有
。简单地复制所有这些代码在我的书中并不完全符合“优雅”的条件...
有什么想法吗?
(我正在使用 Delphi 2010,以防有人提出特定于 Delphi 版本的解决方案)
更新 1: 我现在发现我可以简单地调用 TCustomLabel.DoDrawText( lRect, DT_CALCRECT)
(仅声明为受保护
),让标签执行所需的尺寸计算,而无需重复其代码。我只需确保临时将 EllipsisPosition
设置为 epNone
或完全使用临时标签实例。这实际上并没有那么糟糕,如果没有人能想到更简单的解决方案,我可能会选择它。
更新 2: 我现在已将我的解决方案添加为单独的答案。事实证明,它比我预期的要直接得多,所以可能没有更简单/更好的方法来做到这一点,但无论如何,我都会把这个问题再留一会儿,以防万一。
I have a TLabel
with EllipsisPosition
set to epEndEllipsis
and I need to be able to tell whether the text is currently clipped or not. Besides calculating the area required to display the text myself and comparing it with the actual dimensions of the label, has anyone come up with an easier/more elegant way of doing this?
Actually, calculating the required area in a fail-safe manner also doesn't appear to be as straight forward as it sounds... For instance TCanvas.GetTextHeight
does not take into account linebreaks.
TCustomLabel.DoDrawText
internally uses either DrawTextW
or DrawThemeTextEx
with the DT_CALCRECT
flag to determine whether it should use the ellipsis or not. There's quite a lot of code involved there, all of which is declared private
. Simply duplicating all that code would not exactly qualify as "elegant" in my book...
Any ideas?
(I'm using Delphi 2010 in case anyone comes up with a Delphi-version-specific solution)
Update 1: I now figured out that I can simply call TCustomLabel.DoDrawText(lRect, DT_CALCRECT)
directly (which is merely declared protected
) to let the label perform the required size calculation without having to duplicate its code. I just have to make sure to either temporarily set EllipsisPosition
to epNone
or use a temporary label instance altogether. This is actually not that bad and I might just go with it if noone can think of an even simpler solution.
Update 2: I have now added my solution as a separate answer. It turned out to be rather more straight-forward than I anticipated so there probably is no easier/better way to do it but I'll leave this question open for a little while longer anyway just in case.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
FWIW,这就是我想到的(这是自定义
TLabel
后代的方法):因为它现在使用与
TCustomLabel.DoDrawText
完全相同的逻辑(尤其是人工填充和正确的 WordWrap 设置)它还可以正确处理多行和自动换行的输入文本。请注意,在这种情况下,“正确”意味着“当使用剪切标题绘制TLabel
时,它始终返回True
,否则返回False
”。虽然上面的代码满足了我最初的要求,但我可能不会以这种方式使用它 - 但这更多是由于
TLabel
本身的缺点:特别是对于多行文本,它通常不会这样做我本来希望它,例如,当没有足够的空间容纳多行时,第一行的最后一个单词总是会被截断,即使整行加上省略号已经安装。FWIW, here's what I came up with (this is a method of a custom
TLabel
-descendant):As this now uses exactly the same logic as
TCustomLabel.DoDrawText
(especially the artificial padding and the correct WordWrap setting) it also deals correctly with multi-line and word-wrapped input texts. Note that "correctly" in this case means "it always returnsTrue
when theTLabel
is drawn with a clipped caption andFalse
otherwise".While the above code does what I originally asked for I will probably not use it this way - but this is more due to shortcomings of
TLabel
itself: Especially with multi-line text it often does not behave the way I would have wanted it to, e.g. when there is not enough space for multiple lines, the last word of the first line will always be truncated even if that entire line plus the ellipsis would have fitted.作为起点,您可以使用
示例用法:
使用此技术编写具有
WasClipped
属性的TExtLabel
组件并不困难。事实上,TLabel
组件是 VCL 中最简单的组件之一——它只是绘制一个字符串。As a starting point, you could use
Sample usage:
It wouldn't be hard to write a
TExtLabel
component that has aWasClipped
property using this technique. Indeed, theTLabel
component is one of the simplest components in the VCL -- it just draws a string.