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.
Viser innlegg med etiketten TeeChart. Vis alle innlegg
Viser innlegg med etiketten TeeChart. Vis alle innlegg

tirsdag 6. september 2011

Position the legend in the upper right corner of a TeeChart chart


The TeeChart has many ways of position the Legend on the chart. You can set it to custom and make it a percentage of the width of the chart, but simply putting it on the right side of the chart and make it stay there when the form was resized, was not straight forward.






The solution was to handle the ChartGetLegendPos and ChartGetLegendRect events.
// The following two event handlers are here to position the legend (and it's text)
// in the upper right corner of the chart. This was not possible to simply configure
// in the TeeChart editor.
procedure TFrm.ChartGetLegendPos(Sender: TCustomChart;
  Index: Integer; var X, Y, XColor: Integer);
var
  diff: Integer;
begin
  diff := X - XColor;
  XColor := Sender.Legend.Left + 7;
  X := XColor + diff;
end;

procedure TFrm.ChartGetLegendRect(Sender: TCustomChart;
  var Rect: TRect);
var
 w, h: Integer;
begin
  w := Rect.Right - Rect.Left;
  h := Rect.Bottom - Rect.Top;
  Rect.Top := Sender.ChartRect.Top;
  Rect.Bottom := Rect.Top + h;
  Rect.Left := Sender.ChartRect.Left + (Sender.ChartWidth - w);
  Rect.Right := Rect.Left + w;
end;

tirsdag 30. august 2011

Dynamically adding TQRChart at run-time on a QuickReport

Handle the BeforePrint method in the TQuickRep class to clone the TeeChart graphs...

procedure TQReport.QReportBeforePrint(Sender: TCustomQuickRep;
  var PrintReport: Boolean);
var
  i: Integer;
  LV_Height: Integer;
  LV_Top: Integer;
  LV_Chart : TChart;
  tmp: TQRChart;
begin
  // Divide height between the N charts
  LV_Height := Round(DetailBand1.Height / ChartList.Count);
  LV_Top := 0; // Starting point

  for LV_Chart in ChartList do begin
    { Create the QRChart }
    tmp:=TQRChart.Create(Self);
    { Create the QRDBChart }
    With TQRDBChart.Create(tmp) do
    begin
      Parent:=TWinControl(tmp);
      Name:=TeeGetUniqueName(Owner,'QRChart');
      Title.Text.Clear;
      Title.Text.Add(tmp.ClassName);
    end;
    { add the QRChart to the QuickReport... }
    With tmp do
    begin
      ParentReport := Self;
      Parent := DetailBand1;
      Width := DetailBand1.Width;
      Height := LV_Height;
      Left := 0;
      Top := LV_Top;
      // Move next chart down
      LV_Top := LV_Top + LV_Height;
      { Copy Series and do special formatting}
      Chart.FreeAllSeries;
      Chart.Assign(LV_Chart);
      for i:=0 to LV_Chart.SeriesCount-1 do
        CloneChartSeries(LV_Chart[i]).ParentChart := Chart;

      Chart.Color := clWhite;
      // To include all data - and not only the last 10 years
      Chart.BottomAxis.Automatic := True;
      // Remove gradient background for printing
      Chart.BackWall.Gradient.Visible := False;
    end;
  end;
end;
The QReport tips are taken from here:
http://www.steema.com/support/faq/NewVCL/FAQ_VCL_QUICKREPORT.htm

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!