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 :)
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 have WordWrap
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 to DrawThemeTextEx
and DrawText
), 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 in stdctrls.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 being virtual
- 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.) Being dynamic
, your descendant class's version will be called by AdjustBounds
. 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 :)