📄 frxengine.pas
字号:
end;
if b.FGroup<>nil then
ShowGroupFooters(TfrxGroupHeader(b.FGroup), 0);
if not FirstTime then { some bands have been printed }
begin
RemoveFromVHeaderList(b.FHeader);
if not b.FooterAfterEach then
ShowBand(b.FFooter);
end;
if Report.Terminated then break;
end;
end;
begin
FVMasterBand:= HBand;
FVMasterBand.FOriginalObjectsCount:= FVMasterBand.Objects.Count;
FVMasterBand.AllowSplit:= False;
FVHeaderList.Clear;
FVPageList.Clear;
FVPageList.Add(Pointer(0));
CurVColumn:= 0;
ShowBandTree(TfrxReportPage(HBand.Page).FVSubBands);
FVPageList.Add(Pointer(FVMasterBand.Objects.Count));
end;
procedure TfrxEngine.InitPage;
begin
{ fill in the header/footer lists }
FHeaderList.Clear;
if FPage.TitleBeforeHeader then
begin
FHeaderList.AddItem(FindBand(TfrxReportTitle), 0, False);
FHeaderList.AddItem(FindBand(TfrxPageHeader), 0, False);
end
else
begin
FHeaderList.AddItem(FindBand(TfrxPageHeader), 0, False);
FHeaderList.AddItem(FindBand(TfrxReportTitle), 0, False);
end;
FFooterList.Clear;
FFooterList.Add(FindBand(TfrxColumnFooter));
FFooterList.Add(FindBand(TfrxPageFooter));
{ calculating the page/footer sizes }
PageHeight:= FPage.PaperHeight * fr01cm-FPage.TopMargin * fr01cm-
FPage.BottomMargin * fr01cm;
PageWidth:= FPage.PaperWidth * fr01cm-FPage.LeftMargin * fr01cm-
FPage.RightMargin * fr01cm;
{ reset the current position }
CurX:= 0;
CurY:= 0;
CurColumn:= 1;
FPageCurX:= 0;
FIsFirstPage:= True;
FIsLastPage:= False;
if (PreviewPages.Count = 0) or not FPage.PrintOnPreviousPage then
AddPage
else
begin
PreviewPages.CurPage:= PreviewPages.Count-1;
CurY:= PreviewPages.GetLastY;
ShowBand(TfrxReportTitle);
end;
if FFirstReportPage then
PreviewPages.FirstPage:= PreviewPages.CurPage;
FColumnTop:= CurY;
ShowBand(TfrxColumnHeader);
FHeaderList.AddItem(FindBand(TfrxColumnHeader), 0, False);
RemoveFromHeaderList(FindBand(TfrxReportTitle));
OutlineRoot;
AddPageOutline;
end;
function TfrxEngine.FooterHeight:Extended;
var
i:Integer;
begin
Result:= 0;
for i:= 0 to FFooterList.Count-1 do
if FFooterList[i]<>nil then
Result:= Result+TfrxBand(FFooterList[i]).Height;
end;
function TfrxEngine.FindBand(Band:TfrxBandClass):TfrxBand;
begin
Result:= FPage.FindBand(Band);
end;
procedure TfrxEngine.ShowBand(Band:TfrxBand);
var
chBand:TfrxBand;
begin
if Band<>nil then
begin
if Band.KeepChild then
StartKeep(Band);
DoShow(Band);
chBand:= Band.Child;
if (chBand<>nil) and (Band.Visible or Band.PrintChildIfInvisible) then
ShowBand(chBand);
if Band.KeepChild then
EndKeep(Band);
if Band is TfrxDataBand then
FAggregates.AddValue(Band);
end;
end;
procedure TfrxEngine.ShowBand(Band:TfrxBandClass);
begin
ShowBand(FindBand(Band));
end;
procedure TfrxEngine.AddToHeaderList(Band:TfrxBand);
begin
{ only header bands with "Reprint on new page" flag can be added }
if ((Band is TfrxHeader) and TfrxHeader(Band).ReprintOnNewPage) or
((Band is TfrxGroupHeader) and TfrxGroupHeader(Band).ReprintOnNewPage) then
FHeaderList.AddItem(Band, FPageCurX, FKeeping);
end;
procedure TfrxEngine.AddToVHeaderList(Band:TfrxBand);
begin
{ only header bands with "Reprint on new page" flag can be added }
if ((Band is TfrxHeader) and TfrxHeader(Band).ReprintOnNewPage) or
((Band is TfrxGroupHeader) and TfrxGroupHeader(Band).ReprintOnNewPage) then
FVHeaderList.Add(Band);
end;
procedure TfrxEngine.RemoveFromHeaderList(Band:TfrxBand);
begin
if Band<>nil then
FHeaderList.RemoveItem(Band);
end;
procedure TfrxEngine.RemoveFromVHeaderList(Band:TfrxBand);
begin
if Band<>nil then
FVHeaderList.Remove(Band);
end;
function TfrxEngine.FreeSpace:Extended;
begin
Result:= PageHeight-FooterHeight-CurY;
end;
procedure TfrxEngine.Stretch(Band:TfrxBand);
var
i:Integer;
h, maxh:Extended;
c:TfrxView;
HaveSub, NeedShift:Boolean;
procedure DoSubReports;
var
i:Integer;
SaveCurX, SaveCurY, SavePageCurX:Extended;
Sub:TfrxSubReport;
MainBand:Boolean;
AllObjects:TList;
c:TfrxComponent;
begin
{ create a band which will accepts all subsequent output }
MainBand:= False;
if FOutputTo = nil then
begin
Band.FOriginalObjectsCount:= Band.Objects.Count;
FOutputTo:= TfrxNullBand.Create(nil);
MainBand:= True;
end;
{ save the current position }
SaveCurX:= CurX;
SaveCurY:= CurY;
SavePageCurX:= FPageCurX;
{ looking for subreport objects }
for i:= 0 to Band.Objects.Count-1 do
if TObject(Band.Objects[i]) is TfrxSubReport then
begin
Sub:= TfrxSubReport(Band.Objects[i]);
if not Sub.Visible or not Sub.PrintOnParent or not MainBand then continue;
{ set up all properties... }
FPageCurX:= SavePageCurX+Sub.Left;
CurX:= SaveCurX+Sub.Left;
CurY:= Sub.Top;
{ ...and run the subreport }
RunPage(Sub.Page);
end;
{ restore saved position }
CurX:= SaveCurX;
CurY:= SaveCurY;
FPageCurX:= SavePageCurX;
if MainBand then
begin
{ copy all output to the band }
AllObjects:= FOutputTo.AllObjects;
for i:= 0 to AllObjects.Count-1 do
begin
c:= AllObjects[i];
if (c is TfrxView) and not (c is TfrxSubReport) then
begin
c.Left:= c.AbsLeft;
c.Top:= c.AbsTop;
c.Parent:= Band;
end;
if c is TfrxStretcheable then
TfrxStretcheable(c).StretchMode:= smDontStretch;
end;
{ Clear the FOutputTo property. Extra objects will be freed
in the Unstretch method. }
FOutputTo.Free;
FOutputTo:= nil;
end;
end;
procedure ShiftObjects(Parent:TfrxReportComponent; Amount:Extended);
var
i:Integer;
v:TfrxView;
diff:Extended;
begin
for i:= 0 to Parent.FShiftChildren.Count-1 do
begin
v:= Parent.FShiftChildren[i];
if v.ShiftMode = smAlways then
begin
v.Top:= v.Top+Amount;
ShiftObjects(v, Amount+v.FShiftAmount);
end
else if v.ShiftMode = smWhenOverlapped then
begin
if v.Top < Parent.Top+Parent.Height then
begin
diff:= Parent.Top+Parent.Height-v.Top;
v.Top:= Parent.Top+Parent.Height;
ShiftObjects(v, diff);
end;
end
end;
end;
begin
FCurBand:= Band;
HaveSub:= False;
NeedShift:= False;
PrepareShiftTree(Band);
{ it is not necessary for vertical bands }
if Band<>FVMasterBand then
begin
{ firing band OnBeforePrint event }
Report.CurObject:= Band.Name;
Band.BeforePrint;
Report.DoBeforePrint(Band);
end;
{ firing OnBeforePrint events, stretching objects }
for i:= 0 to Band.Objects.Count-1 do
begin
c:= Band.Objects[i];
if (c is TfrxSubReport) and TfrxSubReport(c).PrintOnParent then
HaveSub:= True;
{ skip getdata for vertical bands' objects }
if Band<>FVMasterBand then
begin
Report.CurObject:= c.Name;
c.BeforePrint;
if Band.Visible then
begin
Report.DoBeforePrint(c);
if c.Visible then
begin
c.GetData;
Report.DoNotifyEvent(c, c.OnAfterData);
end;
end;
end;
if not Band.Visible or not c.Visible then continue;
if (c is TfrxStretcheable) and (TfrxStretcheable(c).StretchMode<>smDontStretch) then
begin
h:= TfrxStretcheable(c).CalcHeight;
if h > c.Height then
begin
c.FShiftAmount:= h-c.Height; { needed to shift underlying objects }
c.Height:= h; { stretch the object }
NeedShift:= True;
end
else
c.FShiftAmount:= 0;
end;
end;
if not Band.Visible then Exit;
{ shift objects }
if NeedShift then
ShiftObjects(Band, 0);
{ check subreports that have PrintOnParent option }
if HaveSub then
DoSubReports;
{ calculate the max height of the band }
maxh:= 0;
for i:= 0 to Band.Objects.Count-1 do
begin
c:= Band.Objects[i];
if c.Top+c.Height > maxh then
begin
maxh:= c.Top+c.Height;
if (c is TfrxDMPMemoView) and (ftBottom in TfrxDMPMemoView(c).Frame.Typ) then
maxh:= maxh+fr1CharY;
end;
end;
if Band.Stretched then
Band.Height:= maxh;
{ fire Band.OnAfterCalcHeight event }
Report.CurObject:= Band.Name;
Report.DoNotifyEvent(Band, Band.OnAfterCalcHeight);
{ set the height of objects that should stretch to max height }
for i:= 0 to Band.Objects.Count-1 do
begin
c:= Band.Objects[i];
if (c is TfrxStretcheable) and (TfrxStretcheable(c).StretchMode = smMaxHeight) then
begin
c.Height:= maxh-c.Top;
if (c is TfrxDMPMemoView) and (ftBottom in TfrxDMPMemoView(c).Frame.Typ) then
c.Height:= c.Height-fr1CharY;
end;
end;
end;
procedure TfrxEngine.UnStretch(Band:TfrxBand);
var
i:Integer;
c:TfrxView;
begin
{ fire OnAfterPrint event }
if Band.Visible then
for i:= 0 to Band.Objects.Count-1 do
begin
c:= Band.Objects[i];
Report.CurObject:= c.Name;
Report.DoAfterPrint(c);
end;
{ restore state }
for i:= 0 to Band.Objects.Count-1 do
begin
c:= Band.Objects[i];
c.AfterPrint;
end;
Report.CurObject:= Band.Name;
Report.DoAfterPrint(Band);
Band.AfterPrint;
{ remove extra band objects if any }
if Band.FOriginalObjectsCount<>-1 then
begin
while Band.Objects.Count > Band.FOriginalObjectsCount do
TObject(Band.Objects[Band.Objects.Count-1]).Free;
Band.FOriginalObjectsCount:=-1;
end;
end;
procedure TfrxEngine.AddPage;
var
i:Integer;
SaveCurX:Extended;
SaveCurLine, SaveCurLineThrough:Integer;
Band:TfrxBand;
begin
PreviewPages.AddPage(FPage);
CurY:= 0;
Band:= FindBand(TfrxOverlay);
if (Band<>nil) and not TfrxOverlay(Band).PrintOnTop then
ShowBand(Band);
CurY:= 0;
SaveCurX:= CurX;
HeaderHeight:= 0;
for i:= 0 to FHeaderList.Count-1 do
begin
{ use own CurX-we may be inside subreports now }
CurX:= FHeaderList[i].Left;
Band:= FHeaderList[i].Band;
if FIsFirstPage and (Band is TfrxPageHeader) and
not TfrxPageHeader(Band).PrintOnFirstPage then
continue;
if Band<>nil then
if not FKeeping or not FHeaderList[i].IsInKeepList then
begin
Band.Overflow:= True;
SaveCurLine:= CurLine;
SaveCurLineThrough:= CurLineThrough;
CurLine:= Band.FLineN;
CurLineThrough:= Band.FLineThrough;
FCallFromAddPage:= True;
{ fix the stack overflow error if call NewPage from ReportTitle }
if Band is TfrxReportTitle then
FHeaderList[i].Band:= nil;
if Band is TfrxPageHeader then
HeaderHeight:= Band.Height;
ShowBand(Band);
FCallFromAddPage:= False;
Band.Overflow:= False;
CurLine:= SaveCurLine;
CurLineThrough:= SaveCurLineThrough;
end;
end;
CurX:= SaveCurX;
end;
procedure TfrxEngine.EndPage;
var
i:Integer;
Band:TfrxBand;
procedure ShowBand(Band:TfrxBand);
begin
if Band = nil then Exit;
Stretch(Band);
try
if Band.Visible then
begin
Band.Left:= 0;
Band.Top:= CurY;
if Band is TfrxPageFooter then
if (FIsFirstPage and not TfrxPageFooter(Band).PrintOnFirstPage) or
(FIsLastPage and not TfrxPageFooter(Band).PrintOnLastPage) then
Exit;
if not PreviewPages.BandExists(Band) then
PreviewPages.AddObject(Band);
CurY:= CurY+Band.Height;
end;
finally
UnStretch(Band);
end;
FAggregates.Reset(Band);
end;
begin
if FPage.Columns > 1 then
begin
EndColumn;
CurX:= FPageCurX;
CurColumn:= 1;
FColumnTop:= 0;
end;
for i:= 0 to FFooterList.Count-1 do
begin
Band:= FFooterList[i];
if Band is TfrxPageFooter then
CurY:= PageHeight-Band.Height;
ShowBand(Band);
end;
Band:= FindBand(TfrxOverlay);
if (Band<>nil) and TfrxOverlay(Band).PrintOnTop then
begin
CurY:= 0;
ShowBand(Band);
end;
FIsFirstPage:= False;
end;
procedure TfrxEngine.AddColumn;
var
i:Integer;
DontShow:Boolean;
AddX:Extended;
procedure DoShow(Band:TfrxBand);
begin
Band.Overflow:= True;
Stretch(Band);
try
if Band.Visible then
begin
Band.Left:= CurX;
Band.Top:= CurY;
if not DontShow then
PreviewPages.AddObject(Band);
CurY:= CurY+Band.Height;
end;
finally
UnStretch(Band);
Band.Overflow:= False;
end;
end;
procedure ShowBand(Band:TfrxBand);
begin
while Band<>nil do
begin
DoShow(Band);
if Band.Visible or Band.PrintChildIfInvisible then
Band:= Band.Child else
break;
end;
end;
begin
CurColumn:= CurColumn+1;
AddX:= frxStrToFloat(FPage.ColumnPositions[CurColumn-1]) * fr01cm;
CurY:= FColumnTop;
{ if FColumnTop = 0, we need to calculate the column position if page header
band exists. Elsewhere, we skip the page header }
for i:= 0 to FHeaderList.Count-1 do
begin
CurX:= FHeaderList[i].Left+AddX;
DontShow:= FHeaderList[i].Band is TfrxPageHeader;
if not DontShow or (CurY = 0) then
ShowBand(FHeaderList[i].Band);
end;
CurX:= FPageCurX+AddX;
end;
procedure TfrxEngine.EndColumn;
var
Band:TfrxBand;
begin
Band:= FindBand(TfrxColumnFooter);
if Band = nil then Exit;
// CurY:= PageHeight-FooterHeight;
Stretch(Band);
try
if Band.Visible then
begin
Band.Left:= CurX-FPageCurX;
Band.Top:= CurY;
PreviewPages.AddObject(Band);
end;
finally
UnStretch(Band);
end;
FAggregates.Reset(Band);
end;
procedure TfrxEngine.NewPage;
begin
if FKeeping then
PreviewPages.CutObjects(FKeepPosition);
EndPage;
AddPage;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -