Search code examples
delphidelphi-xe2

Adding OnHint-like functionality to a third party component


Due to cosmetic reasons the app I'm maintaining uses an ancient component from DevExpress that pre-dated their current grid controls (TdxMasterView if you're interested). What I want to be able to do is to have a tooltip that displays the current cell's text, however this component does not have an OnHint event exposed.

I have been able to get the functionality that I need using the MouseMove event, however as the code requires it to translate the mouse cursor into a cell and then retrieve the contents I think this is too much code for an event that is fired so frequently (although it doesn't feel TOO laggy in operation).

The component itself is derived from TCustomControl, so has the basic Hint and ShowHint properties, however what I think I want is to be able to either expose or add an event that will fire only when the hint bubble will be shown (i.e. the OnHint event or equivalent). All I need to get the correct text is the X and Y coordinates of the mouse. This appears to be tied up in TControlAction, however I'm not entirely sure how this works as it's not immediately clear from a first glance at the code and it's not exposed by the component.

Does anyone have any example code where they have achieved something similar? I have access to the underlying source, so can modify it a bit if needed (DevExpress will never release an update to this code, so normal risks of doing this don't really apply), but I'd prefer to work by helper function, windows message or some sort of decorator if possible.

I suppose the other option is to have a timer to enable/disable the event, but that seems a bit of a sucky (if simple) solution.


Solution

  • Implement procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW; in your code.

    procedure TMyComponent.CMHintShow(var Message: TCMHintShow);
    var
      CellIdx: Integer;
      Handled: Boolean;
      HintStr: string;
      LHintInfo: PHintInfo;
    begin
      Message.Result := 1; // Don't show the hint
      if Message.HintInfo.HintControl = Self then
      begin
        with Message.HintInfo.CursorPos do
        begin
          CellIdx := ImageAtPos(X, Y);
        end;
    
        Handled := False;
        HintStr := '';
        if Assigned(FOnGetHint) then
          FOnGetHint(Self, CellIdx, HintStr, Handled);
        LHintInfo := Message.HintInfo;
        if (CellIdx <> -1) then
        begin
          if not Handled then
            HintStr := Hint;
          LHintInfo.CursorRect := GetCellRect(CellIdx);
          Handled := True;
        end;
        if Handled then
        begin
          LHintInfo.HintStr := HintStr;
          Message.Result := 0; // Show the hint
        end;
      end;
    end;