如何为 TLabel (TGraphicControl) 创建调整大小事件
我正在尝试创建 TLabel 后代,当文本宽度超过标签宽度时,它将显示带有整个标题的提示。我已将 EllipsisPosition 属性设置为 epEndEllipsis,并且我的标题会自动在末尾用省略号缩短。没关系。
但是我需要收到通知,文本已被缩短以设置提示。在我的情况下,只有当文本更改(消息 CM_TEXTCHANGED)和调整组件大小时才会发生这种情况。
这就是我的问题 - 如何通知我我的 TLabel 已调整大小? 我在那里有锚点,因此它会随表单一起调整大小,但我想将其包装在单独的 TLabel 中后裔。
这段代码可以工作,但是有没有更好的方法?类似于 WM_EXITSIZEMOVE,但为 TGraphicControl 工作?
procedure TEllipsisLabel.WMWindowPosChanged(var Message: TWMWindowPosChanged);
begin
inherited;
if Assigned(Parent) then
if Canvas.TextWidth(Caption) > Width then
begin
ShowHint := True;
Hint := Caption;
end
else
begin
ShowHint := False;
Hint := '';
end;
end;
非常感谢:)
I'm trying to create TLabel descendant, which will display hint with the whole caption when the text width exceed label width. I've set the EllipsisPosition property to epEndEllipsis and my caption is automatically shorted by an ellipsis at the end. That's fine.
However I need to be notified, that the text has been shortened to set up the hint. This in my case may happen only when the text is changed (message CM_TEXTCHANGED) and when the component is resized.
And that's my question - how can I be notified, that my TLabel has been resized ? I have the anchors there, so it's resized along with the form, but I would like to wrap it in the separate TLabel descendant.
This code works, but isn't there a better way ? Something like WM_EXITSIZEMOVE, but working for TGraphicControl ?
procedure TEllipsisLabel.WMWindowPosChanged(var Message: TWMWindowPosChanged);
begin
inherited;
if Assigned(Parent) then
if Canvas.TextWidth(Caption) > Width then
begin
ShowHint := True;
Hint := Caption;
end
else
begin
ShowHint := False;
Hint := '';
end;
end;
Thanks a lot :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为您不希望收到关于
TLabel
后代已调整大小的通知。 相反,您希望收到它已缩短文本的通知。我知道它们看起来相同,但事实并非如此 - 标签可能仍然比文本更宽,它可能打开了WordWrap
等。此外,TCustomLabel
后代可以使用几种不同的方法来绘制文本,基于主题/Vista/Aero 发光的东西(它们归结为DrawThemeTextEx
和DrawText
),因此您需要连接到该系统以准确了解它正在绘制的文本正在做什么,包括渲染文本的大小是。如果您使用的是非 Starter 版本的 Delphi,请查看
stdctrls.pas
中的TCustomLabel
源代码。有两个感兴趣的方法:TCustomLabel.DoDrawText
- 这会绘制文本和/或计算文本边界矩形(考虑椭圆、换行等)。 在内部,它会生成一个更改后的字符串,即实际绘制的文本。换句话说,此方法的功能是告诉您文本是否合适。两者都是
动态
,在语义上等同于虚拟
- 即,您可以覆盖它们。不幸的是,DoDrawText 不会返回它正在绘制的最终文本字符串 - 如果返回,您可以覆盖它,调用继承的版本并将绘制的文本与真实文本进行比较。但是,您可以重写并重新实现它,并自己执行此操作。使用 VCL 代码作为指导(您需要同等的功能,尽管您不应该直接复制它,因为它属于 Embarcadero。)由于
动态
,您的后代类的版本将由AdjustBounds< 调用/代码>。在代码中,当您缩短文本时,还要设置一个已缩短的标志或立即生成提示。瞧。您准确地知道它何时被缩短:)
I don't think you want to be notified that the
TLabel
descendant has been resized. Instead, you want to be notified that it has shortened the text. I know they seem the same, but they're not - the label might still be wider than the text, it might haveWordWrap
turned on, etc. In addition,TCustomLabel
descendants can use a couple of different methods to draw text, based on theming / Vista / Aero glow stuff (they boil down toDrawThemeTextEx
andDrawText
), so you need to hook into that system to know exactly what the text it's drawing is doing, including what the size of the rendered text is.If you're using a non-Starter edition of Delphi, have a look at the
TCustomLabel
source instdctrls.pas
. There are two methods of interest:TCustomLabel.AdjustBounds
- this is where the bounding rectangle is set, and it adjusts for word wrapping etc. It does this by calling (as does painting) the other method of interest:TCustomLabel.DoDrawText
- this paints the text and/or calculates the text bounding rectangle accounting for ellipses, wrapping, that kind of thing. Internally, it generates an altered string that is the text that is actually painted. In other words, this method's functionality is what tells you whether the text fits or not.Both are
dynamic
, which is semantically equivalent to beingvirtual
- ie, you can override them.DoDrawText
unfortunately doesn't return the final text string it's painting - if it did, you could override it, call the inherited version and compare the painted text with the real text. However, you can override and reimplement it, and do this yourself. Use the VCL code as a guide (you want equivalent functionality, although you should not copy it directly since it's owned by Embarcadero.) Beingdynamic
, your descendant class's version will be called byAdjustBounds
. In your code, when you shorten the text, also set a flag it's been shortened or generate the hint immediately. Voila. You accurately know exactly when it's been shortened :)我想不出还有什么比
WM_WINDOWPOSCHANGED
更好的了:这看起来很理想。您有什么理由反对使用它?
I can't think of anything better than
WM_WINDOWPOSCHANGED
:That looks ideal. What do you have against using it?
我认为您需要重写 AdjustBounds 方法。尝试以下代码(只需创建一个带有 TButton 和 TLabel 的表单,然后用此代码替换 .pas)。此示例演示了在文本更改时检测标签大小的变化。不过,您需要创建自己的事件。
I think you need to override the AdjustBounds method. Try the following code (simply create a form with a TButton and TLabel on it and replace the .pas with this code). This example demonstrates detecting a label size change if the text changes. You will need to create your own event though.
您只需重写
Resize
方法即可。但是,请注意,您的代码与
TCustomLabel.DoDrawText
确定何时绘制省略号的方式不同,因此您可能会得到意外的结果。此外,省略号绘制也可能是由字体更改、主题设置更改以及其他一些事件引起的。
You can simply override
Resize
method. However, be aware that your codeis different from how
TCustomLabel.DoDrawText
determines when to draw ellipses so you may get unexpected results.Also, the ellipses drawing may also be caused by a font change, a theme setting change, and maybe some other events.