test

progging - To wander about and beg; to seek food or other supplies by low arts; to seek for advantage by mean shift or tricks.
progging - Programmer slang for writing computer code.

tirsdag 23. august 2011

Fun with Tooltip - Delphi THintWindow

On most occasions getting a tooltip on a control is as simple as clicking enable and typing a string.

In the case of TeeChart you can get a tooltip on a Series by adding a tool called "Mark Tips".

After assigning this to a series, a tooltip will automatically show up when you hold the mouse over the series. BUT, It will not show up when holding the mouse over the series' mark, which is what I needed. So then I had to implement the tooltip functionality my self.



I used the THintWindow class to show a tooltip that looks the same as the other tooltips, although I had to set the (background) color property to clInfoBk in order for it to look the same. To find out what part of the chart the mouse was in I used the TeeChart function procedure TCustomChart.CalcClickedPart(Pos: TPoint; Var Part: TChartClickedPart);. This will return a TChartClickedPart record that will give you a lot of useful information, like if its a Series or SeriesMarks etc. It will the also have a reference to the series itself as well as the index of the series.

I used this method to show tooltip on both the SeriesMarks and the Series, so I could skip using the "Mark Tips" tool from TeeChart.

The THintWindow was okay to use after reading the documentation. It has methods for calculating it's necessary width and height. It was too tricky to to find the size of the cursor so that it could be positioned at the bottom of the mouse cursor (like is normally done) so I simply placed it on top of the mouse cursor.
Following is the code that is called on the MouseMove event:


procedure TFrame_Plot.ShowEventSeriesToolTip();
var
  point: TPoint;
  clickedPart: TChartClickedPart;
  labelString: string;
  rect: TRect;
begin
  point := Chart.GetCursorPos();
  Chart.CalcClickedPart(point, clickedPart);
  Case clickedPart.Part of
    cpSeriesMarks, cpSeries:
    begin
      if (clickedPart.ASeries = SeriesInfoEvent) or (clickedPart.ASeries = SeriesEvent) then 
      begin
        if Assigned(CV_HintWindow) and (CV_HintWindow.Tag <> clickedPart.PointIndex) then 
        begin
          // Hide and free it!
          CV_HintWindow.ReleaseHandle();
          FreeAndNil(CV_HintWindow);
        end;
        if not Assigned(CV_HintWindow) then begin
          labelString := clickedPart.ASeries.Labels[clickedPart.PointIndex];
          CV_HintWindow := THintWindow.Create(Self);
          CV_HintWindow.Color := clInfoBk;
          // Calculate the WIDHT of the rectangle
          rect := CV_HintWindow.CalcHintRect(200, labelString, nil);
          // Find the position on screen to place the tooltip
          rect.TopLeft := Chart.ClientToScreen(point);
          // Move position so that it's above mouse cursor
          rect.Top := rect.Top - rect.Bottom;
          // Adjust Right and Bottom considering position
          rect.Right := rect.Right + rect.Left;
          rect.Bottom := rect.Bottom + rect.Top;
          // Use the tag to remember which Event we are showing tooltip for
          CV_HintWindow.Tag := clickedPart.PointIndex;
          // Show it!
          CV_HintWindow.ActivateHint(rect, labelString);
        end
      end
      else if Assigned(CV_HintWindow) then begin
        // Hide and free it!
        CV_HintWindow.ReleaseHandle();
        FreeAndNil(CV_HintWindow);
      end;
    end;
  else
    if Assigned(CV_HintWindow) then begin
      // Hide and free it!
      CV_HintWindow.ReleaseHandle();
      FreeAndNil(CV_HintWindow);
    end;
  end;
end;
The result looks like this:


That's it!

Ingen kommentarer:

Legg inn en kommentar