Hello,
Is there any way to determine the position and size of the SubChart with SubChart.ChartRect?
No, not really, because they are two different things. One thing is the position of the TWinControl relative to its parent (Left,Top) and its size (Width,Height), and another thing is the size of the area enclosed by the Chart axes (which is the ChartRect). You can see that if you run a TChart without a series added to it, the ChartRect is empty - this is becuase the series defines the axes, and the length of the axes define the ChartRect. So the ChartRect of your SubChart will be empty until you add a series to it.
What this means, in practice, is that the calculations in my example should be run at the same time as you add a series to your SubChart - as soon as you've added the series, you can call Repaint and obtain the values for ChartRect, e.g. (click Button1 then Button2)
Code: Select all
unit ChartTest;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VclTee.TeeGDIPlus, VCLTee.TeEngine,
Vcl.ExtCtrls, VCLTee.TeeProcs, VCLTee.Chart, Vcl.StdCtrls, VCLTee.TeeWorldSeries, VCLTee.Series,
VCLTee.TeeURL, VCLTee.TeeSeriesTextEd, VCLTee.TeeSubChart, VCLTee.EditChar;
type
TForm1 = class(TForm)
Chart1: TChart;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Chart1AfterDraw(Sender: TObject);
procedure SubChartAfterDraw(Sender: TObject);
private
SubChartTool: TSubChartTool;
SubChart: TChart;
procedure AddSubChart(Resize: Boolean = True; AddSeries: Boolean = True);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.AddSubChart(Resize: Boolean; AddSeries: Boolean);
var t:Integer;
rnd:Double;
begin
SubChartTool:=TSubChartTool.Create(Self);
Chart1.Tools.Add(SubChartTool);
SubChart:=SubChartTool.Charts.AddChart('SubChart');
if Resize then
begin
SubChart.View3D:=false;
SubChart.Height:=300;
SubChart.Width:=400;
SubChart.Top:=10;
SubChart.Left:=Chart1.Width-SubChart.Width-10;
end;
if AddSeries then
begin
SubChart.AddSeries(TLineSeries).FillSampleValues;
end;
SubChart.OnAfterDraw:=SubChartAfterDraw;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
AddSubChart;
Chart1.Repaint;
ShowMessage('SubChart ChartRect: Width ' + IntToStr(SubChart.ChartRect.Width) );
end;
procedure TForm1.Button2Click(Sender: TObject);
var charRect, subRect : TRect;
pixelXUnit,pixelYUnit:Double;
subBottomMax,subLeftMax:Double;
begin
if SubChart <> nil then
begin
charRect:=Chart1.ChartRect;
subRect:=SubChart.ChartRect;
pixelXUnit:=(Chart1.Axes.Bottom.Maximum-Chart1.Axes.Bottom.Minimum)/(charRect.Width-Chart1.Axes.Bottom.MinimumOffset-Chart1.Axes.Bottom.MaximumOffset);
pixelYUnit:=(Chart1.Axes.Left.Maximum-Chart1.Axes.Left.Minimum)/(charRect.Height-Chart1.Axes.Left.MinimumOffset-Chart1.Axes.Left.MaximumOffset);
subBottomMax:=pixelXUnit*subRect.Width;
subLeftMax:=pixelYUnit*subRect.Height;
SubChart.Axes.Bottom.SetMinMax(Chart1.Axes.Bottom.Minimum, subBottomMax);
SubChart.Axes.Left.SetMinMax(Chart1.Axes.Left.Minimum, subLeftMax);
end;
end;
procedure TForm1.SubChartAfterDraw(Sender: TObject);
var subX1,subX2:Integer;
procedure DoBottomAxes;
begin
subX1:=SubChart.Axes.Bottom.CalcXPosValue(1);
subX2:=SubChart.Axes.Bottom.CalcXPosValue(2);
SubChart.Canvas.Pen.Color:=clRed;
SubChart.Canvas.Pen.Width:=3;
SubChart.Canvas.Line(subX1, SubChart.ChartRect.Bottom, subX2, SubChart.ChartRect.Bottom);
SubChart.Canvas.Font.Color:=clRed;
SubChart.Canvas.TextOut(subX1, SubChart.ChartRect.Bottom-20, 'Pixels: '+IntToStr(subX2-subX1));
end;
procedure DoLeftAxes;
begin
subX1:=SubChart.Axes.Left.CalcYPosValue(Chart1.Axes.Left.Minimum);
subX2:=SubChart.Axes.Left.CalcYPosValue(Chart1.Axes.Left.Minimum + 50);
SubChart.Canvas.Pen.Color:=clBlue;
SubChart.Canvas.Pen.Width:=3;
SubChart.Canvas.Line(SubChart.ChartRect.Left, subX1, SubChart.ChartRect.Left, subX2);
SubChart.Canvas.Font.Color:=clBlue;
SubChart.Canvas.TextOut(SubChart.ChartRect.Left+5, subX2, 'Pixels: '+IntToStr(subX1-subX2));
end;
begin
DoBottomAxes;
DoLeftAxes;
end;
procedure TForm1.Chart1AfterDraw(Sender: TObject);
var charX1,charX2:Integer;
procedure DoBottomAxes;
begin
charX1:=Chart1.Axes.Bottom.CalcXPosValue(1);
charX2:=Chart1.Axes.Bottom.CalcXPosValue(2);
Chart1.Canvas.Pen.Color:=clRed;
Chart1.Canvas.Pen.Width:=3;
Chart1.Canvas.Line(charX1, Chart1.ChartRect.Bottom, charX2, Chart1.ChartRect.Bottom);
Chart1.Canvas.Font.Color:=clRed;
Chart1.Canvas.TextOut(charX1, Chart1.ChartRect.Bottom - 20, 'Pixels: '+IntToStr(charX2-charX1));
end;
procedure DoLeftAxes;
begin
charX1:=Chart1.Axes.Left.CalcYPosValue(Chart1.Axes.Left.Minimum);
charX2:=Chart1.Axes.Left.CalcYPosValue(Chart1.Axes.Left.Minimum + 50);
Chart1.Canvas.Pen.Color:=clBlue;
Chart1.Canvas.Pen.Width:=3;
Chart1.Canvas.Line(Chart1.ChartRect.Left, charX1, Chart1.ChartRect.Left, charX2);
Chart1.Canvas.Font.Color:=clBlue;
Chart1.Canvas.TextOut(Chart1.ChartRect.Left+5, charX2, 'Pixels: '+IntToStr(charX1-charX2));
end;
begin
DoBottomAxes;
DoLeftAxes;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Chart1.OnAfterDraw:=Chart1AfterDraw;
Chart1.AddSeries(TLineSeries).FillSampleValues;
end;
end.