7

I want a TPageControl and some TTabSheets, with 'per tabsheet' tooltip hints visible as I hover over each tab in turn.

Is there any way of getting this effect in Delphi 2009?

Roddy
  • 66,617
  • 42
  • 165
  • 277

5 Answers5

7

Just hook the Page Control's Mouse Move event and use the TabAtPos property to determine which tab the mouse is hovering over. Then assign that tab's Hint to the Page Control's hint property.

procedure TForm.PageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);
var
  tabindex: integer;
begin
  tabindex := PageControl.IndexOfTabAt(X, Y);
  if (tabindex >= 0) and (PageControl.Hint <> PageControl.Pages[tabindex].Hint) then
  begin
    Application.CancelHint;
    PageControl.Hint := PageControl.Pages[tabindex].Hint;
    PageControl.ShowHint := true;
  end;
end;

CancelHint/ShowHint will take care of updating the hint window when mouse moves directly from one tab to another.

Improved but ugly version below also temporarily changes HintPause to 0 when mouse is moved directly from tab to tab so that the hint is redisplayed immediately. (The "ugly" part of the solution goes to the Application.ProcessMessages call which forces hint messages to be processed before HintPause is restored.)

procedure TForm.PagesMouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);
var
  hintPause: integer;
  tabindex: integer;
begin
  tabindex := PageControl.IndexOfTabAt(X, Y);
  if (tabindex >= 0) and (PageControl.Hint <> PageControl.Pages[tabindex].Hint) then
  begin
    hintPause := Application.HintPause;
    try
      if PageControl.Hint <> '' then
        Application.HintPause := 0;
      Application.CancelHint;
      PageControl.Hint := PageControl.Pages[tabindex].Hint;
      PageControl.ShowHint := true;
      Application.ProcessMessages; // force hint to appear
    finally Application.HintPause := hintPause; end;
  end;
end;

To hide the hint on the main page body, assign the following method to the page control's OnMouseLeave event.

procedure TForm.PageMouseLeave(Sender: TObject);
begin
  PageControl.Hint := '';
  PageControl.ShowHint := false;
end;
gabr
  • 26,580
  • 9
  • 75
  • 141
  • TabAtPos doesn't exist, you meant IndexOfTabAt(x,Y). This *so* nearly works right. Except that as you move from one tab to another, the hint doesn't update or re-show. – Roddy Aug 28 '09 at 12:41
  • Apologies; I was using TRzTabSheet (Raize Components) which has a TabAtPos property and works well. You could just programmatically show the hint on a change of tabindex using the THintWindow class. Set the Page Control's Show Hint property to false and create your own. –  Aug 30 '09 at 23:13
  • IndexOfTabAt exists in Delphi Tokyo! – Gabriel Jul 04 '19 at 09:13
  • @Roddy- IndexOfTabAt exists in Delphi Tokyo! – Gabriel Jul 04 '19 at 09:13
  • @Rigel - this may be related to my comment in my [answer](https://stackoverflow.com/a/1257794/18484) - that Raize components has been acquired by Embarcadero for Delphi as of 2015. – Argalatyr Jul 09 '19 at 03:39
6

In Raize Components, this can be accomplished by setting the trzpagecontrol.tabhints property to true. Good components can save you a lot of time (therefore money).

(just a happy customer, btw)

Update (in response to comment from @Rigel) from raize.com FAQ (Raize Components tab):

What happened to Raize Components?

Back in 2015 Embarcadero acquired Raize Components from us and rebranded the product as the Konopka Signature VCL Controls (KSVC). Initially they sold the product separately, but for the past several releases of RAD Studio, the components have been available for free through the GetIt Package Manager. Simply open the GetIt Package Manager from the Delphi or C++Builder Tools menu and search for “Konopka” to locate the installer. The component names, units, and packages are the same as they were in Raize Components, just the product name is different.

Argalatyr
  • 4,639
  • 3
  • 36
  • 62
  • 2
    +1 - The investment in Raize components is well worth it. The support is world class, and the visual style options can really set your application apart from others using standard controls. – skamradt Aug 11 '09 at 16:01
  • Agreed. We use Raize almost exclusively for all UI design work. Great components and good support. –  Aug 14 '09 at 03:16
  • Looks like they abandoned the Component library. Is not there on their website: https://raize.com/ – Gabriel Jul 04 '19 at 09:12
  • It would have been nice if the original page would have been left in place, with an announcement instead of being deleted :) – Gabriel Jul 11 '19 at 14:50
1

1 - fill in the .Hint property, and set the .ShowHint property to True for the PageControl (assuming each tabsheet has ParentShowHint set to true; otherwise you'll have to set each page individually).

2 - Assign this event to the PageControl's OnChange event handler:

procedure TForm1.PageControl1Change(Sender: TObject);
begin
  PageControl1.Hint := PageControl1.ActivePage.Hint;
end;

After you do that, the hint will be whatever the active tab is. I am not sure how to make it change the hint based on where the mouse is hovering - that's an interesting phenomenon I've never noticed before, actually.

JosephStyons
  • 57,317
  • 63
  • 160
  • 234
  • I think the question was about showing page-specific hints without changing the active page. – Wolf Mar 06 '18 at 13:51
1

On the tPageControl.OnMouseMove find TabIndex by Pgctrl.IndexOfTabAt( X, Y ) and assign TabSheet hint to the tPageControl hint

Look here:

http://www.delphigroups.info/2/9/321680.html

Mira
  • 11
  • 2
0

Originally working on a C++ Builder 6 (!) project (so please forgive any typo in this transcript), I started with the answer of Gerard[1] and reduced the code as much as possible. To better control the calls of Application.CancelHint, I introduced the member FLastHintTabIndex, it must be initialized with -1.

procedure TForm1.PageControl1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
var
  TabIndex: Integer;
begin
  TabIndex := PageControl1.IndexOfTabAt(X, Y);
  if FLastHintTabIndex <> TabIndex then
      Application.CancelHint;
  if TabIndex <> -1 then
      PageControl1.Hint = PageControl1.Pages[TabIndex].Hint;
  FLastHintTabIndex := TabIndex;
end;

[1] my answer doesn't contain much new, but I find all that code and text too distracting.

Wolf
  • 9,679
  • 7
  • 62
  • 108