2

TAction has a OnHint event, but unfortunately not a OnHideHint event. This has the following drawback: I have ToolButtons and other controls associated with actions. Whenever the mouse is over such a control, the hint of the Action is shown in the StatusBar; (I have set the StatusBar's AutoHint property to True). But when the mouse leaves the ToolButton, the previous custom text in the StatusBar (which is not from a hint) is NOT automatically restored! Now I could write an OnMouseLeave event handler for each and every control on the form to restore my custom text in the StatusBar, but this would be cumbersome! Isn't there something which automatically restores the previous text in the StatusBar? An OnHideHint event in TAction would be ideal!

user1580348
  • 5,721
  • 4
  • 43
  • 105

2 Answers2

2

That is default behavior, When AutoHint is True, the status bar automatically responds to hint actions by displaying the long version of the hint's text in the first panel.

The issue that you are having is that when you leave a control with your mouse, you are basically entering another window, it's parent control. And because that parent has no Hint string value assigned to it, the HintAction is updated to an empty string.

If you want to return the default value when there is no hint to display then drop a TApplicationEvents component on the form and use the TApplication.OnHint event like this:

var
  OriginalPanelText : String = 'BLA';

procedure TForm1.ApplicationEvents1Hint(Sender: TObject);
begin

   if StatusBar1.SimplePanel or (StatusBar1.Panels.Count = 0)
  then
    if Application.Hint <> ''
    then
       StatusBar1.SimpleText := Application.Hint
    else
       StatusBar1.SimpleText := OriginalPanelText
  else
    if Application.Hint <> ''
    then
      StatusBar1.Panels[0].Text := Application.Hint
    else
      StatusBar1.Panels[0].Text := OriginalPanelText;

end;
Peter
  • 2,977
  • 1
  • 17
  • 29
0

The AutoHint magic all happens in TStatusBar.ExecuteAction. When the hint stops showing that code sets the status bar text to be empty. You could modify the behaviour like this:

type
  TStatusBar = class(ComCtrls.TStatusBar)
  private
    FRestoreTextAfterHintAction: string;
  public
    function ExecuteAction(Action: TBasicAction): Boolean; override;
  end;

function TStatusBar.ExecuteAction(Action: TBasicAction): Boolean;
var
  HintText: string;
begin
  if AutoHint and not (csDesigning in ComponentState) and
     (Action is THintAction) and not DoHint then begin
    HintText := THintAction(Action).Hint;
    if SimplePanel or (Panels.Count=0) then begin
      if HintText='' then begin
        SimpleText := FRestoreTextAfterHintAction;
      end else begin
        FRestoreTextAfterHintAction := SimpleText;
        SimpleText := HintText;
      end;
    end else begin
      if HintText='' then begin
        Panels[0].Text := FRestoreTextAfterHintAction;
      end else begin
        FRestoreTextAfterHintAction := Panels[0].Text;
        Panels[0].Text := HintText;
      end;
    end;
    Result := True;
  end else begin
    Result := inherited ExecuteAction(Action);
  end;
end;

I've used a rather crude interposer class and a brittle instance variable to store the text to be restored. You could tart this up to be a little more robust if you wish. The code above at least shows you the place you need to add your hooks.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    Was about to explain but you deleted it before I could post comment. This is first time I down voted one of your answers and for good reason, I don't believe that it's necessary to go through the trouble of using interposer classes and modifying a function when you can do it in a much more easier way, why start hacking at it when there's clearly an already implemented way around it? And I don't know why you would post 12 hours after me, clearly I have explained why this happens and offered a good solution, other then screw with me idk. – Peter Jun 11 '13 at 11:22
  • @Peter It's just a different way to do it. Encapsulating the behaviour in the control allows you to avoid having to add `Application.OnHint` handlers. What has the existence of a 12 hour old answer have to do with any of this? I think you need to relax a little here. Nobody is out to "screw with you". It's just an SO answer for heaven's sake! – David Heffernan Jun 11 '13 at 11:37
  • @PeterVonča I don't mind the downvote. Anyway, it costs you rep! ;-) – David Heffernan Jun 11 '13 at 13:36
  • Thanks to both for their good ideas! I like the simplicity of Peter Vonča's solution and the OOP approach of David Heffernan's solution. Because the situation in my code is rather complex, I actually use a modification of a mixture of ideas in both solutions. Thanks - SO rules! – user1580348 Jun 12 '13 at 20:45