delphiwinapiresizenotificationstlabel

How to create resize event for TLabel (TGraphicControl)


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 :)


Solution

  • 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:

    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 :)