How to show hint using Application.ActivateHint on Delphi?

Dmitry picture Dmitry · Feb 22, 2013 · Viewed 16.8k times · Source

I have the following code trying to show a hint:

procedure TMyGrid.OnGridMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
var
  aPoint: TPoint;
begin
  inherited;
  //Application.Hint := 'Hint Text';
  //Application.ShowHint := True;
  Grid.Hint := 'Hint Text';
  Grid.ShowHint := True;
  aPoint.X := X;
  aPoint.Y := Y;
  Application.ActivateHint(aPoint);
end;

But there is no hint appears. What's wrong?

Answer

Remy Lebeau picture Remy Lebeau · Feb 22, 2013

Rather than trying to force TApplication to display a new Hint in your grid control's OnMouseMove event, the correct approach is to instead have your grid process the CM_HINTSHOW message to customize the current Hint whenever it is shown normally.

The CM_HINTSHOW message provides you with a pointer to a THintInfo record in its LPARAM value. THintInfo has a CursorPos member that tells you the current mouse position within the control's client area, and a CursorRect member that allows you to define a rectangle within the control's client area that the current hint should be valid for (THintInfo has other members for customizing the hint further, suh as text, color, window class, show/hide timeouts, etc). When the mouse moves outside of that rectangle but is still within the control's client area, the CM_HINTSHOW message is generated again to obtain new information to update the current Hint with.

If you need to update the hint on every mouse move, you can define a custom CursorRect that only contains the current CursorPos, for example:

type
  TMyGrid = class(...)
  private
    procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW;
  end;

procedure TMyGrid.CMHintShow(var Message: TCMHintShow);
begin
  with Message.HintInfo^ do
  begin
    HintStr := Format('Hint Text (%d,%d)', [CursorPos.X, CursorPos.Y]);
    CursorRect := Rect(CursorPos.X, CursorPos.Y, CursorPos.X, CursorPos.Y);
  end;
end;