Custom Hints for Each Tab in Delphi’s TTabSet or TTabControl (Plus: Hints in TStatusBar)

Custom Hint For Each Tab
Tab set controls are commonly used to display tabbed pages within a dialog box.
The TTabControl control can be used to add a control with multiple tab settings to a form. The TTabSet control presents horizontal tabs users can click to initiate actions.

Both TTabSet and TTabControl are a single object (not made up of several pages hosting different controls, like the case is with TPageControl). When the current tab changes, the tab control must directly update its contents to reflect the change in an OnChange event handler.

To have a set of tabs for the tab set control you specify a list of strings as the value of the Tabs property. Ever wondered how to have specific hint for each tab?

Specific Tab – Specific Hint?

The Hint and ShowHint properties specify whether the control displays its hint when the mouse pointer rests momentarily over the control (when ShowHint is true).

For TTabSet and TTabControl there’s only the Hint property you can set and this hint will appear for the entire control – not taking into account the selected tab or alike.

If you use tab controls you might need to display different hints when the mouse hovers over a specific tab of the tab control.

In the Delphi IDE there’s a tab control with 3 tabs “Code”, “Design”, “History”. Would it not be helpful if a hint would appear when you code and hover your mouse over the “Design” tab – for example to “hint” the name of the form you are working on.

If you need to change the hint of the tab control taking into account where (over what) the mouse is, here’s how to do it.

Have a TTabSet control with several tabs (defined by the Tabs property), and handle the OnMouseMove event:

procedure TForm1.TabControl1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
{$WRITEABLECONST ON}
const oldPos : integer = -1;
{$WRITEABLECONST OFF}
var
  iPos : integer;
begin
  iPos := TabControl1.IndexOfTabAt(x,y);
  if (iPos > -1)  then
  begin
    if iPos <> oldPos then
      Application.CancelHint;
    TabControl1.Hint := Format('%d. - %s', [iPos, TabControl1.Tabs[iPos]]);
    oldPos := iPos;
  end
  else
    TabControl1.Hint := '';
end;

In the OnMouseMove event handler the Hint property is changed to provide the name of the tab the mouse is over. The code uses the ItemAtPos method of the TTabControl to get the index of the tab under the mouse.

When the mouse moves from one tab to another we have to cancel the “popup” hint display – for this purpose I’ve added a writable constant oldPos to remember over what tab the mouse was when hint-for-tab was changed.

If you are working with TTabControl, you can use the next code:

procedure TForm1.TabSet1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  iPos : integer;
begin
  iPos := TabSet1.ItemAtPos(Point(x,y));
  if iPos > -1 then
    TabSet1.Hint := Format('%d. - %s', [iPos, TabSet1.Tabs[iPos]])
  else
    TabSet1.Hint := '';
end;

The code is much the same as used with TTabSet, only the method to be called is IndexOfTabAt. Note: for some reason the standard “popup” hint does not get displayed for the TTabSet control (even without this OnMouseMove handling)

Hints in TStatusBar

The TStatusBar Delphi control displays a row of panels, usually aligned at the bottom of a form.

The AutoHint specifies whether the status bar’s text is set automatically to the current hint, if SimplePanel property is set to true.

When AutoHint is true, the status bar automatically responds to hint actions by displaying the long version of the hint’s text.

If multiple panels are defined in the Panels property, the auto hint would go to first panel.

Display (Auto) Hint in a Specific Panel of a Status Bar

If you want the current hint to be displayed in some other panel, as needed per your application design (something else displayed in the first panel) you might want to display auto hints in some other panel of a status bar.

Handle the OnHint event of the status bar, read the Application.Hint property to get the hint; and finally display the hint in a different panel:

procedure THintForm.StatusBar1Hint(Sender: TObject) ;
begin
  //make sure StatusBar1's AutoHint = true
  //also make sure you have at least 2 panels defined 
  //as this would redirect the hint to the second panel
  StatusBar1.Panels[1].Text := Application.Hint;
end;

That’s it. Now each tab has its own hint (displayed in a specific panel of the status bar).

4 thoughts on “Custom Hints for Each Tab in Delphi’s TTabSet or TTabControl (Plus: Hints in TStatusBar)

  1. Andrew Sachs

    StatusBar1.Panels[1] means it goes to the second panel.
    With only one panel defined I get a List index out of bounds exception.

    Reply
  2. Andrew Sachs

    Also, hint does not change when moving from tab to tab of the TabControl (but it does change in the StatusBar)

    and hints do not pop up AT ALL in a TabSet. I even created a fresh one with no MouseMove event, just straight, with Hello World typed in Object Inspector – Properties – Hint and with ShowHint set to True.

    Application.HintPause := 100; // tip from someone having similar problems

    I am using Delphi XE on Windows XP .

    Reply
    1. zarkogajic Post author

      Hi Andrew, thanks for noticing. I was concentrated on the status bar display (as that’s what’s important for me). I guess no hints for TTabSet is some issue with the control itself (as even without this OnMouseMove handling, the Hint does not appear for TabSet).

      As for hint not being changed when you move between TabControl tabs – I’ve rewritten the code in a different way to handle this.

      Reply

Leave a Reply to Andrew Sachs Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.