Ah, even after years of programming in Delphi, there’s still something new I learn every day (lucky me).
Just recently I needed to have hints (help tooltips) for some buttons to stay visible longer than hints for other controls (like edits, memos and alike).
Found no straight forward solution here…
… but the solution is really simple 🙂
On Hints and Application
Hints are defined using the Hint property every TControl descendant exposes. Hint property is a string value specifying the text that appears when users move (and stop) the mouse over the control. Usually you would use hints to provide some more info about the underlying control (imagine a button on a toolbar and a hint providing more details / help to what the button does). The ShowHint property then determines if the Hint text appears for the control – it is False by default.
The actual display of the hints is under the Application control (global object controlling your Delphi application). The global Application object of type TApplication also has the ShowHint and Hint properties. By default, ShowHint for Application is true. The Hint property stores the Hint value of the control when the mouse is moving over the control.
The Application further exposes the following hint related properties
- HintColor – specifies the color of the hint boxes for the Hints for the application. Default is clInfoBk.
- HintPause – specifies the time interval in milliseconds that passes before the control’s Hint appears when the user places the mouse pointer on a control.
- HintShortPuase – specifies the time in milliseconds to wait before bringing up a Hint if another Hint has already been shown.
- HintHidePause – specifies the time interval in milliseconds to wait before hiding the hint if the mouse has not moved from the control. The default is 2500 (2.5 seconds)
By looking at the above, I would like to have HintHidePuase be longer for some specific controls in my application.
If I set Application.HintHidePause = 10000 then all controls will display their hints longer – therefore a no go.
Just to mention: each Hint can actually have two parts: short and long – separated using the pipe “|” character. Short hints are what gets displayed in the pop-up window. The “long” part of the Hint is displayed by the TStatusBar control. Use the GetShortHint and GetLongHint function to extract short and long parts from the Hint value. If there’s no “|” in Hint, long value is an empty string.
TApplicationEvents To The Rescue
Now, there’s the TApplicationEvents component you can drop on a form. The TApplicationEvents wraps up events of the global Application object. The TApplicationEvents has two interesting hint-related events: OnHint and OnShowHint.
The OnHint event is of the “standard” TNotifyEvent type. From the OnHint event you can read Application.Hint and eventually alter or display it somewhere also (like in a status bar).
The OnShowHint seems to be much more promising! The OnShowHint occurs when the application is about to display the popup window with the hint – and we can use it to change the appearance and behavior of the hint tooltip! Here’s the signature:
TShowHintEvent = procedure ( var HintStr: string; var CanShow: Boolean; var HintInfo: Vcl.Controls.THintInfo) of object;
The HintStr is the text of the hint. The CanShow is the last moment to permit or prevent the hint for displaying. The HintInfo is what I’m looking for!
The HintInfo parameter contains information about the appearance and behavior of the popup window. Changing its fields will customize the way the Hint is displayed!
A peek at the THintInfo brings the declaration:
THintInfo = record HintControl: TControl; HintWindowClass: THintWindowClass; HintPos: TPoint; HintMaxWidth: Integer; HintColor: TColor; CursorRect: TRect; CursorPos: TPoint; ReshowTimeout: Integer; HideTimeout: Integer; HintStr: string; HintData: TCustomData; end;
Note the two fields:
- HintControl – the control for which hint processing is occurring.
- HideTimeout field – the number of milliseconds to show the hint. By default, it is set to the value of the Application variable’s HintHidePause property.
Ha! To have four time stay-longer hints for some buttons I can: if HintControl is TButton then HideTimeout := 4 * Application.HintHidePause;
Finally, if you’ve come so far, here’s a short code example.
- Drop a few buttons on a form
- Drop the TApplicationEvents also
- Drop some more controls of whatever type
Here’s OnCreate (not to have to specify Hint/ShowHint for controls manually):
procedure THintsForm.FormCreate(Sender: TObject); var i : integer; begin for i := 0 to -1 + self.ControlCount do begin Controls[i].ShowHint := true; Controls[i].Hint := 'Hint for ' + Controls[i].Name end; end;
And here’s Application’s OnShowHint – where I will ensure longer hints for buttons:
procedure THintsForm.ApplicationEvents1ShowHint( var HintStr: string; var CanShow: Boolean; var HintInfo: THintInfo); begin if HintInfo.HintControl is TButton then begin //make hints stay longer for buttons HintInfo.HideTimeout := HintInfo.HideTimeout * 4; //alter the hint string HintInfo.HintStr := Format('%s%sWill stay for %d ms', [HintInfo.HintStr, #13#10, HintInfo.HideTimeout]); end; end;
Run this and note that the popup window with the hint will stay visible for 10 seconds if you place your mouse over the button(s) and do not move it.
A confession: in my real application I needed to have longer visible hints for the nodes of the virtual tree view.