TMS FNC Hint — Guides
HTML content
Assign any HTML string to a control's Hint property. The FNC HTML engine renders bold, italic, colour, images, and basic tables.
Button1.Hint := '<b>Save</b><br/><i>Ctrl+S</i> — saves the current file.';
Set ShowHint := True on the control (and on the form or application, as the framework requires). TTMSFNCHint has no Active property — dropping it on the form installs its hint window class, and it takes over hint rendering from that point on.
Appearance
The hint window paints itself from three appearance objects on the component — Fill, Stroke, and Font — plus a Shadow flag. There is no rounding, padding, or size property: everything else about the box is derived from the measured text (see Positioning and hint rect calculation below).
TMSFNCHint1.Fill.Kind := gfkSolid;
TMSFNCHint1.Fill.Color := gcLightyellow;
TMSFNCHint1.Stroke.Kind := gskSolid;
TMSFNCHint1.Stroke.Color := gcGray;
TMSFNCHint1.Font.Name := 'Segoe UI';
TMSFNCHint1.Font.Size := 10;
TMSFNCHint1.Shadow := True;
Set Kind as well as Color. A fill left at gfkNone or a stroke left at gskNone is not painted at all, so assigning only Color looks like the appearance was ignored. Colours are TTMSFNCGraphicsColor values (gcLightyellow, gcGray, …) or a raw $AARRGGBB literal — not VCL cl* constants.
Shadow is honoured on Windows by suppressing the CS_DROPSHADOW window class style, so it takes effect when the hint window is created rather than on the next repaint.
Show and hide delays
The show delay, auto-hide delay, and cursor offset are compile-time constants in the hint unit (HintDelay, HintHideDelay, HintOffsetX, HintOffsetY), not published properties — there is nothing to set at design time or runtime. When you need a hint on your own schedule, drive it yourself with ShowHintAt / HideHint and your own TTimer, and check IsShowing before acting.
Positioning and hint rect calculation
Sizing and positioning are two separate steps, and knowing which is which is the difference between a hint that lays out correctly and one that jumps to the corner of the screen. Calculate measures the hint text with the component's Font, adds a fixed 4 x 2 pixel padding, and then raises OnCalculateHintRect so you can adjust the result. That rect is a size anchored at (0, 0) — the show position is applied afterwards by offsetting the rect by the requested screen coordinates. Reach for the event to enforce a minimum width, cap a long hint, or add padding; do not use it to move the hint, because your origin will be offset away.
procedure TForm1.FormCreate(Sender: TObject);
begin
TMSFNCHint1.Fill.Kind := gfkSolid;
TMSFNCHint1.Fill.Color := gcLightyellow;
TMSFNCHint1.Stroke.Kind := gskSolid;
TMSFNCHint1.Stroke.Color := gcGray;
TMSFNCHint1.Font.Name := 'Segoe UI';
TMSFNCHint1.Font.Size := 10;
TMSFNCHint1.OnCalculateHintRect := DoCalculateHintRect;
end;
procedure TForm1.DoCalculateHintRect(Sender: TObject; AHint: String;
var ARect: TRect);
begin
{ ARect is the measured text box anchored at (0,0) plus the component's
4 x 2 pixel padding - a SIZE, not a screen position. Enforce a minimum
width and add breathing room; the show position is applied afterwards. }
if ARect.Width < 220 then
ARect.Right := ARect.Left + 220;
ARect.Bottom := ARect.Bottom + 8;
end;
procedure TForm1.ShowSaveHint;
const
HINT_TEXT = '<b>Save</b><br/>Writes the current document to disk.';
var
R: TRect;
P: TPointF;
begin
{ Calculate runs the same measurement path the hint window uses, including
OnCalculateHintRect, so the size here matches what will be displayed. }
R := TMSFNCHint1.Calculate(HINT_TEXT);
{ ShowHintAt takes screen coordinates and offsets the calculated rect by them. }
P := Button1.LocalToScreen(PointF(0, Button1.Height + 4));
TMSFNCHint1.ShowHintAt(HINT_TEXT, Round(P.X), Round(P.Y));
Caption := Format('hint size %d x %d', [R.Width, R.Height]);
end;
procedure TForm1.HideSaveHint;
begin
if TMSFNCHint1.IsShowing then
TMSFNCHint1.HideHint;
end;
Points worth remembering:
- The handler signature is
procedure(Sender: TObject; AHint: String; var ARect: TRect)—AHintis the text being measured, andARectis an integerTRect, not aTRectF. Calculateruns the event too, so the size you read back fromCalculateis the size that will be shown.- Assigning an absolute rect (
ARect := Rect(10, 10, 300, 60)) sets both the size and an origin offset that is added to the show position, which is almost never what you want.
Custom drawing
Use OnBeforeDrawHint to replace the default rendering and OnAfterDrawHint to add to it. OnBeforeDrawHint carries var ADefaultDraw: Boolean; set it to False to suppress the built-in fill, stroke, and HTML text so your own painting on AGraphics is all that appears. OnAfterDrawHint has no such flag — it always runs on top of whatever was drawn. Both receive the hint string and the window rect, so a badge, icon, or separator can be positioned relative to the same box OnCalculateHintRect sized.