📄 sgr_def.pas
字号:
end;
procedure Tsp_XYPlot.AddMarker(const FM:Tsp_PlotMarker; const WDM:Tsp_WhenDrawMarker);
begin
if FM<>nil then begin
with MarkerList(WDM) do if IndexOf(FM)<0 then Add(FM);
if FM.Visible then CustomInvalidate(False,False,True);
end;
end;
procedure Tsp_XYPlot.SetMarkerAt(const FM:Tsp_PlotMarker;
const WDM:Tsp_WhenDrawMarker; Front:boolean);
var ci:integer;
begin
with MarkerList(WDM) do begin
if Front and (Last<>Self) then begin
ci:=IndexOf(Self);
if (ci>-1) then Move(ci,Count-1);
end
else begin
ci:=IndexOf(Self);
if ci>0 then Move(ci,0);
end;
end;
end;
function Tsp_XYPlot.FindXAutoMin(WX:Tsp_WhatXAxis; var min:double ):boolean;
var j,k:integer; tm:double;
begin
Result:=False;
if fSeries.Count<1 then Exit;
k:=-1;
for j:=0 to fSeries.Count-1 do with Tsp_DataSeries(fSeries[j]) do
begin
if Active and (XAxis=WX) and GetXMin(min) then
begin
k:=j;
break;
end;
end;
if k > -1 then
begin
Result:=True;
for j:=k+1 to fSeries.Count-1 do with Tsp_DataSeries(fSeries[j]) do
begin
if Active and (XAxis=WX) and GetXMin(tm) then
begin
if tm<min then min:=tm;
end;
end;
end;
end;
function Tsp_XYPlot.FindXAutoMax(WX:Tsp_WhatXAxis; var max:double ):boolean;
var j,k:integer; tm:double;
begin
Result:=False;
if fSeries.Count<1 then Exit;
k:=-1;
for j:=0 to fSeries.Count-1 do with Tsp_DataSeries(fSeries[j]) do
begin
if Active and (XAxis=WX) and GetXMax(max) then
begin
k:=j;
break;
end;
end;
if k > -1 then
begin
Result:=True;
for j:=k+1 to fSeries.Count-1 do with Tsp_DataSeries(fSeries[j]) do
begin
if Active and (XAxis=WX) and GetXMax(tm) then
begin
if tm>max then max:=tm;
end;
end;
end;
end;
function Tsp_XYPlot.FindYAutoMin(WY:Tsp_WhatYAxis; var min:double ):boolean;
var j,k:integer; tm:double;
begin
Result:=False;
if fSeries.Count<1 then Exit;
k:=-1;
for j:=0 to fSeries.Count-1 do with Tsp_DataSeries(fSeries[j]) do
begin
if Active and (YAxis=WY) and GetYMin(min) then
begin
k:=j;
break;
end;
end;
if k > -1 then
begin
Result:=True;
for j:=k+1 to fSeries.Count-1 do with Tsp_DataSeries(fSeries[j]) do
begin
if Active and (YAxis=WY) and GetYMin(tm) then
begin
if tm<min then min:=tm;
end;
end;
end;
end;
function Tsp_XYPlot.FindYAutoMax(WY:Tsp_WhatYAxis; var max:double ):boolean;
var j,k:integer; tm:double;
begin
Result:=False;
if fSeries.Count<1 then Exit;
k:=-1;
for j:=0 to fSeries.Count-1 do with Tsp_DataSeries(fSeries[j]) do
begin
if Active and (YAxis=WY) and GetYMax(max) then
begin
k:=j;
break;
end;
end;
if k > -1 then
begin
Result:=True;
for j:=k+1 to fSeries.Count-1 do with Tsp_DataSeries(fSeries[j]) do
begin
if Active and (YAxis=WY) and GetYMax(tm) then
begin
if tm>max then max:=tm;
end;
end;
end;
end;
function Tsp_XYPlot.DoAutoMinMax(Axis:Tsp_Axis):boolean;
var WX:Tsp_WhatXAxis; WY:Tsp_WhatYAxis;
dmin, dmax, gap:double;
bin, bax:boolean;
begin
Result:=False;
if (Axis.fFlags and (sdfAutoMin or sdfAutoMax))=0 then Exit;
if (Axis.fFlags and sdfVertical)<>0 then
begin
if Axis=LA then WY:=dsyLeft else WY:=dsyRight;
bin:=((Axis.fFlags and sdfAutoMin)<>0) and FindYAutoMin(WY, dmin);
bax:=((Axis.fFlags and sdfAutoMax)<>0) and FindYAutoMax(WY, dmax);
end else
begin
if Axis=BA then WX:=dsxBottom else WX:=dsxTop;
bin:=((Axis.fFlags and sdfAutoMin)<>0) and FindXAutoMin(WX, dmin);
bax:=((Axis.fFlags and sdfAutoMax)<>0) and FindXAutoMax(WX, dmax);
end;
if not (bin or bax) then Exit;
if not bin then dmin:=Axis.Min;
if not bax then dmax:=Axis.Max;
gap:=(dmax-dmin)*0.025;
if bin then dmin:=dmin-gap;
if bax then dmax:=dmax+gap;
Result:=True;
with Axis do if (dmin<>Min) or (dmax<>Max)then ChangeMinMax(dmin,dmax);
end;
function Tsp_XYPlot.LimitsStored:boolean;
begin
Result:=LA.fMinMaxStored and BA.fMinMaxStored and
RA.fMinMaxStored and TA.fMinMaxStored;
end;
procedure Tsp_XYPlot.StoreLimits;
begin
if Not LimitsStored then begin
LA.StoreMinMax; BA.StoreMinMax; RA.StoreMinMax; TA.StoreMinMax;
end;
end;
procedure Tsp_XYPlot.RestoreLimits;
begin
if LimitsStored then begin
LA.RestoreMinMax; BA.RestoreMinMax; RA.RestoreMinMax; TA.RestoreMinMax;
Invalidate;
end;
end;
procedure Tsp_XYPlot.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
WindowClass.style := WindowClass.style and not (CS_HREDRAW or CS_VREDRAW);
end;
procedure Tsp_XYPlot.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation=opRemove) then begin
if (AComponent is Tsp_DataSeries) then
RemoveSeries(AComponent as Tsp_DataSeries);
if (AComponent is Tsp_PlotMarker) then
RemoveMarker(AComponent as Tsp_PlotMarker,
(AComponent as Tsp_PlotMarker).WhenDraw);
end;
end;
Const
zsNone=0; zsZoomStart=1; zsZoomRect=2; zsStartPan=3; zsPaning=4;
function NormRect(var R:TRect):TRect;
begin
Result:=R;
with Result do begin
if R.Left>R.Right then begin Left:=R.Right+1; Right:=R.Left+1; end;
if R.Top>R.Bottom then begin Top:=R.Bottom+1; Bottom:=R.Top+1 end;
end;
end;
procedure Tsp_XYPlot.DrawNotRect(R:TRect);
begin
with Canvas do
begin
with Pen do
begin
Style:=psDot;
Color:=clBlack;
Mode:=pmNotXor;
end;
Brush.Color:=clWhite;
with R do begin
PolyLine([TopLeft, Point(Right,Top), BottomRight, Point(Left,Bottom),TopLeft]);
end;
end;
end;
procedure Tsp_XYPlot.RectToLimits(ZR:TRect; D:Tsp_zpDirections);
procedure ZoomAxis(A:Tsp_Axis; p1,p2:integer);
var mi, ma, sw :double; CanZoom:boolean;
begin
with A do
begin
mi:=P2V(p1); ma:=P2V(p2);
if mi>ma then begin sw:=mi; mi:=ma; ma:=sw end;
CanZoom:=True;
if Assigned(fOnZoom) then fOnZoom(A, mi, ma, CanZoom);
if CanZoom then ChangeMinMax(mi,ma);
end;
end;
begin
if D=zpdNone then Exit;
with ZR do begin
if ((Right-Left)>2) and ((Bottom-Top)>2) then
begin
StoreLimits;
if ((Right-Left)>1) and (D in [zpdHorizontal, zpdBoth]) then begin
ZoomAxis(BA, Left, Right);
ZoomAxis(TA, Left, Right);
end;
if ((Bottom-Top)>1) and (D in [zpdVertical, zpdBoth]) then begin
ZoomAxis(LA, Bottom, Top);
ZoomAxis(RA, Bottom, Top);
end;
Invalidate;
end;
end;
end;
procedure Tsp_XYPlot.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if (Button = mbLeft) then
begin
if (Shift=fZoomShift) and (fZoomEnabled<>zpdNone) and
(fZoomData.State=zsNone) then with fZoomData do
begin
R.Left:=X; R.Top:=Y;
case fZoomEnabled of
zpdHorizontal: R.Top:=FR.Top;
zpdVertical: R.Left:=FR.Left;
end;
State:=zsZoomStart;
end
else if (Shift=fPanShift) and (fPanEnabled<>zpdNone) and
(fZoomData.State=zsNone) then with fZoomData do
begin
R.Left:=X; R.Top:=Y;
State:=zsStartPan;
Screen.Cursor := fPanCursor;
end;
end;
inherited MouseDown(Button, Shift, X, Y);
end;
procedure Tsp_XYPlot.MouseMove(Shift: TShiftState; X, Y: Integer);
procedure PanPlot(var ZR:TRect; D:Tsp_zpDirections);
begin
StoreLimits;
with ZR do begin
if ((Right-Left)<>0) and (D in [zpdHorizontal, zpdBoth]) then begin
with BA do ScrollBy(Right-Left);
with TA do ScrollBy(Right-Left);
CustomInvalidate(False,True,True);
end;
if ((Bottom-Top)<>0) and (D in [zpdVertical, zpdBoth]) then begin
with LA do ScrollBy(Bottom-Top);
with RA do ScrollBy(Bottom-Top);
CustomInvalidate(False,True,True);
end;
end;
end;
begin
if fZoomData.State<>zsNone then with fZoomData do
case State of
zsZoomStart: if (abs(R.Left-X)>3) or (abs(R.Top-Y)>3) then
begin
State:=zsZoomRect;
Screen.Cursor := crCross;
R.Right:=X; R.Bottom:=Y;
case fZoomEnabled of
zpdHorizontal: R.Bottom:=FR.Bottom;
zpdVertical: R.Right:=FR.Right;
end;
DrawNotRect(R);
end;
zsZoomRect :
begin
DrawNotRect(R);
R.Right:=X; R.Bottom:=Y;
case fZoomEnabled of
zpdHorizontal: R.Bottom:=FR.Bottom;
zpdVertical: R.Right:=FR.Right;
end;
DrawNotRect(R);
end;
zsStartPan: with R do
if (Left<>X) or (Top<>Y) then
begin
Right:=Left; Bottom:=Top;
Left:=X; Top:=Y;
State:=zsPaning;
PanPlot(R, fPanEnabled);
end;
zsPaning : with R do
begin
Right:=Left; Bottom:=Top;
Left:=X; Top:=Y;
PanPlot(R, fPanEnabled);
end;
end;
inherited MouseMove(Shift, X, Y);
end;
procedure Tsp_XYPlot.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
with fZoomData do
case State of
zsZoomStart: RestoreLimits;
zsZoomRect:
begin
DrawNotRect(R);
RectToLimits(NormRect(R), fZoomEnabled);
end;
zsStartPan:;
zsPaning:
begin
end;
end;
if fZoomData.State<>zsNone then begin
fZoomData.State:=zsNone;
Screen.Cursor := Cursor;
end;
inherited MouseUp(Button, Shift, X, Y);
end;
function MaxI(a,b:integer):integer;
begin
if a>b then Result:=a else Result:=b;
end;
procedure Tsp_XYPlot.Arrange(AvgFntW,FntH:integer);
var BR:TRect; h,w:integer;
begin
FR:=Rect(0,0, DWidth, DHeight);
h:=FntH;
w:=AvgFntW;
with BR do begin
Left:=MaxI(LA.BandWidth(w,h), MaxI(BA.OrgIndent(w,h), TA.OrgIndent(w,h)))+LA.Margin;
Bottom:=MaxI(BA.BandWidth(w,h), MaxI(LA.OrgIndent(w,h), RA.OrgIndent(w,h)))+BA.Margin;
Right:=MaxI(RA.BandWidth(w,h), MaxI(BA.EndIndent(w,h), TA.EndIndent(w,h)))+RA.Margin;
Top:=MaxI(TA.BandWidth(w,h), MaxI(LA.EndIndent(w,h), RA.EndIndent(w,h)))+TA.Margin;
end;
with FR do begin
inc(Left,BR.Left);
dec(Right,BR.Right);
dec(Bottom,BR.Bottom);
inc(Top,BR.Top);
if Left+3>Right then Right:=Left+3;
if Top+3>Bottom then Bottom:=Top+3;
LA.SetLine(Left-1, Bottom-1, Bottom-Top-1);
RA.SetLine(Right, Bottom-1, Bottom-Top-1);
BA.SetLine(Left, Bottom, Right-Left-1);
TA.SetLine(Left, Top-1, Right-Left-1);
end;
ValidArrange:=True;
end;
procedure Tsp_XYPlot.FreshVFont;
var LF:TLogFont; HF:HFont;
begin
VFont.Assign(Font);
GetObject(VFont.Handle, SizeOf(LF), @LF);
with LF do begin
lfEscapement:=900;
lfOrientation:= lfEscapement;
lfWeight:= FW_BOLD;
end;
HF:=CreateFontIndirect(LF);
if HF<>0 then VFont.Handle:=HF;
end;
procedure Tsp_XYPlot.DrawAroundField;
procedure ClearBack;
begin
with DCanvas do
begin
Brush.Style:=bsSolid;
Brush.Color:=Self.Color;
FillRect(Rect(0, 0, DWidth, FR.Top));
FillRect(Rect(0, FR.Bottom+1, DWidth, DHeight));
FillRect(Rect(0, FR.Top, FR.Left, FR.Bottom+1));
FillRect(Rect(FR.Right, FR.Top, DWidth, FR.Bottom+1));
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -