PageRenderTime 90ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/Source/FR_Class.pas

http://github.com/FastReports/FreeReport
Pascal | 7335 lines | 6646 code | 487 blank | 202 comment | 865 complexity | 52e74cfa96e31edbea7bd9f745adfb88 MD5 | raw file
  1. {*****************************************}
  2. { }
  3. { FastReport v2.3 }
  4. { Report classes }
  5. { }
  6. { Copyright (c) 1998-99 by Tzyganenko A. }
  7. { }
  8. {*****************************************}
  9. unit FR_Class;
  10. interface
  11. {$I FR.inc}
  12. uses
  13. SysUtils, Windows, Messages, Classes, Graphics, Printers, Controls,
  14. Forms, StdCtrls, ComCtrls, Dialogs, Menus, Buttons,
  15. FR_View, FR_Pars, FR_Intrp, FR_DSet, FR_DBSet, FR_DBRel
  16. {$IFDEF Delphi6}
  17. , Variants
  18. {$ENDIF}
  19. {$IFDEF IBO}
  20. , IB_Components
  21. {$ELSE}
  22. , DB
  23. {$ENDIF};
  24. const
  25. // object flags
  26. flStretched = 1;
  27. flWordWrap = 2;
  28. flWordBreak = 4;
  29. flAutoSize = 8;
  30. flBandNewPageAfter = 2;
  31. flBandPrintifSubsetEmpty = 4;
  32. flBandPageBreak = 8;
  33. flBandOnFirstPage = $10;
  34. flBandOnLastPage = $20;
  35. flBandRepeatHeader = $40;
  36. flPictCenter = 2;
  37. flPictRatio = 4;
  38. flWantHook = $8000;
  39. // object types
  40. gtMemo = 0;
  41. gtPicture = 1;
  42. gtBand = 2;
  43. gtSubReport = 3;
  44. gtLine = 4;
  45. gtAddIn = 10;
  46. // frame types
  47. frftNone = 0;
  48. frftRight = 1;
  49. frftDown = 2;
  50. frftLeft = 4;
  51. frftUp = 8;
  52. // text align
  53. frtaLeft = 0;
  54. frtaRight = 1;
  55. frtaCenter = 2;
  56. frtaVertical = 4;
  57. frtaMiddle = 8;
  58. frtaDown = 16;
  59. type
  60. TfrDrawMode = (drAll, drCalcHeight, drAfterCalcHeight, drPart);
  61. TfrBandType = (btReportTitle, btReportSummary,
  62. btPageHeader, btPageFooter,
  63. btMasterHeader, btMasterData, btMasterFooter,
  64. btDetailHeader, btDetailData, btDetailFooter,
  65. btSubDetailHeader, btSubDetailData, btSubDetailFooter,
  66. btOverlay, btColumnHeader, btColumnFooter,
  67. btGroupHeader, btGroupFooter,
  68. btCrossHeader, btCrossData, btCrossFooter, btNone);
  69. TfrDataSetPosition = (psLocal, psGlobal);
  70. TfrValueType = (vtNotAssigned, vtDBField, vtOther, vtFRVar);
  71. TfrPageMode = (pmNormal, pmBuildList);
  72. TfrBandRecType = (rtShowBand, rtFirst, rtNext);
  73. TfrRgnType = (rtNormal, rtExtended);
  74. TfrReportType = (rtSimple, rtMultiple);
  75. TfrView = class;
  76. TfrBand = class;
  77. TfrPage = class;
  78. TfrReport = class;
  79. TfrExportFilter = class;
  80. TDetailEvent = procedure(const ParName: String; var ParValue: Variant) of object;
  81. TEnterRectEvent = procedure(Memo: TStringList; View: TfrView) of object;
  82. TBeginDocEvent = procedure of object;
  83. TEndDocEvent = procedure of object;
  84. TBeginPageEvent = procedure(pgNo: Integer) of object;
  85. TEndPageEvent = procedure(pgNo: Integer) of object;
  86. TBeginBandEvent = procedure(Band: TfrBand) of object;
  87. TEndBandEvent = procedure(Band: TfrBand) of object;
  88. TProgressEvent = procedure(n: Integer) of object;
  89. TBeginColumnEvent = procedure(Band: TfrBand) of object;
  90. TPrintColumnEvent = procedure(ColNo: Integer; var Width: Integer) of object;
  91. TManualBuildEvent = procedure(Page: TfrPage) of object;
  92. TfrHighlightAttr = packed record
  93. FontStyle: Word;
  94. FontColor, FillColor: TColor;
  95. end;
  96. TfrPrnInfo = record // print info about page size, margins e.t.c
  97. PPgw, PPgh, Pgw, Pgh: Integer; // page width/height (printer/screen)
  98. POfx, POfy, Ofx, Ofy: Integer; // offset x/y
  99. PPw, PPh, Pw, Ph: Integer; // printable width/height
  100. end;
  101. PfrPageInfo = ^TfrPageInfo;
  102. TfrPageInfo = packed record // pages of a preview
  103. R: TRect;
  104. pgSize: Word;
  105. pgWidth, pgHeight: Integer;
  106. pgOr: TPrinterOrientation;
  107. pgMargins: Boolean;
  108. PrnInfo: TfrPrnInfo;
  109. Visible: Boolean;
  110. Stream: TMemoryStream;
  111. Page: TfrPage;
  112. end;
  113. PfrBandRec = ^TfrBandRec;
  114. TfrBandRec = packed record
  115. Band: TfrBand;
  116. Action: TfrBandRecType;
  117. end;
  118. TfrView = class(TObject)
  119. private
  120. procedure P1Click(Sender: TObject);
  121. protected
  122. SaveX, SaveY, SaveDX, SaveDY: Integer;
  123. SaveFW: Single;
  124. BaseName: String;
  125. Canvas: TCanvas;
  126. DRect: TRect;
  127. gapx, gapy: Integer;
  128. Memo1: TStringList;
  129. FDataSet: TfrTDataSet;
  130. FField: String;
  131. olddy: Integer;
  132. StreamMode: (smDesigning, smPrinting);
  133. procedure ShowBackGround; virtual;
  134. procedure ShowFrame; virtual;
  135. procedure BeginDraw(ACanvas: TCanvas);
  136. procedure GetBlob(b: TfrTField); virtual;
  137. procedure OnHook(View: TfrView); virtual;
  138. public
  139. Parent: TfrBand;
  140. Name: String;
  141. ID: Integer;
  142. Typ: Byte;
  143. Selected: Boolean;
  144. OriginalRect: TRect;
  145. ScaleX, ScaleY: Double; // used for scaling objects in preview
  146. OffsX, OffsY: Integer; //
  147. IsPrinting: Boolean;
  148. x, y, dx, dy: Integer;
  149. Flags: Word;
  150. FrameTyp: Word;
  151. FrameWidth: Single;
  152. FrameColor: TColor;
  153. FrameStyle: Word;
  154. FillColor: TColor;
  155. Format: Integer;
  156. FormatStr: String;
  157. Visible: WordBool;
  158. Memo, Script: TStringList;
  159. constructor Create; virtual;
  160. destructor Destroy; override;
  161. procedure Assign(From: TfrView); virtual;
  162. procedure CalcGaps; virtual;
  163. procedure RestoreCoord; virtual;
  164. procedure Draw(Canvas: TCanvas); virtual; abstract;
  165. procedure Print(Stream: TStream); virtual;
  166. procedure ExportData; virtual;
  167. procedure LoadFromStream(Stream: TStream); virtual;
  168. procedure SaveToStream(Stream: TStream); virtual;
  169. procedure SaveToFR3Stream(Stream: TStream); virtual;
  170. procedure Resized; virtual;
  171. procedure DefinePopupMenu(Popup: TPopupMenu); virtual;
  172. function GetClipRgn(rt: TfrRgnType): HRGN; virtual;
  173. procedure CreateUniqueName;
  174. procedure SetBounds(Left, Top, Width, Height: Integer);
  175. end;
  176. TfrStretcheable = class(TfrView)
  177. protected
  178. ActualHeight: Integer;
  179. DrawMode: TfrDrawMode;
  180. function CalcHeight: Integer; virtual; abstract;
  181. function MinHeight: Integer; virtual; abstract;
  182. function RemainHeight: Integer; virtual; abstract;
  183. end;
  184. TfrMemoView = class(TfrStretcheable)
  185. private
  186. FFont: TFont;
  187. procedure P1Click(Sender: TObject);
  188. procedure P2Click(Sender: TObject);
  189. procedure P3Click(Sender: TObject);
  190. procedure P4Click(Sender: TObject);
  191. procedure P5Click(Sender: TObject);
  192. procedure SetFont(Value: TFont);
  193. protected
  194. Streaming: Boolean;
  195. TextHeight: Integer;
  196. CurStrNo: Integer;
  197. Exporting: Boolean;
  198. procedure ExpandVariables;
  199. procedure AssignFont(Canvas: TCanvas);
  200. procedure WrapMemo;
  201. procedure ShowMemo;
  202. function CalcWidth(Memo: TStringList): Integer;
  203. function CalcHeight: Integer; override;
  204. function MinHeight: Integer; override;
  205. function RemainHeight: Integer; override;
  206. procedure GetBlob(b: TfrTField); override;
  207. public
  208. Adjust: Integer;
  209. Highlight: TfrHighlightAttr;
  210. HighlightStr: String;
  211. LineSpacing, CharacterSpacing: Integer;
  212. constructor Create; override;
  213. destructor Destroy; override;
  214. procedure Assign(From: TfrView); override;
  215. procedure Draw(Canvas: TCanvas); override;
  216. procedure Print(Stream: TStream); override;
  217. procedure ExportData; override;
  218. procedure LoadFromStream(Stream: TStream); override;
  219. procedure SaveToStream(Stream: TStream); override;
  220. procedure SaveToFR3Stream(Stream: TStream); override;
  221. procedure DefinePopupMenu(Popup: TPopupMenu); override;
  222. property Font: TFont read FFont write SetFont;
  223. end;
  224. TfrBandView = class(TfrView)
  225. private
  226. procedure P1Click(Sender: TObject);
  227. procedure P2Click(Sender: TObject);
  228. procedure P3Click(Sender: TObject);
  229. procedure P4Click(Sender: TObject);
  230. procedure P5Click(Sender: TObject);
  231. procedure P6Click(Sender: TObject);
  232. function GetBandType: TfrBandType;
  233. procedure SetBandType(const Value: TfrBandType);
  234. public
  235. constructor Create; override;
  236. procedure Draw(Canvas: TCanvas); override;
  237. procedure DefinePopupMenu(Popup: TPopupMenu); override;
  238. function GetClipRgn(rt: TfrRgnType): HRGN; override;
  239. procedure SaveToFR3Stream(Stream: TStream); override;
  240. property BandType: TfrBandType read GetBandType write SetBandType;
  241. property DataSet: String read FormatStr write FormatStr;
  242. property GroupCondition: String read FormatStr write FormatStr;
  243. end;
  244. TfrSubReportView = class(TfrView)
  245. public
  246. SubPage: Integer;
  247. constructor Create; override;
  248. procedure Assign(From: TfrView); override;
  249. procedure Draw(Canvas: TCanvas); override;
  250. procedure LoadFromStream(Stream: TStream); override;
  251. procedure SaveToStream(Stream: TStream); override;
  252. procedure SaveToFR3Stream(Stream: TStream); override;
  253. procedure DefinePopupMenu(Popup: TPopupMenu); override;
  254. end;
  255. TfrPictureView = class(TfrView)
  256. private
  257. procedure P1Click(Sender: TObject);
  258. procedure P2Click(Sender: TObject);
  259. protected
  260. procedure GetBlob(b: TfrTField); override;
  261. public
  262. Picture: TPicture;
  263. constructor Create; override;
  264. destructor Destroy; override;
  265. procedure Assign(From: TfrView); override;
  266. procedure Draw(Canvas: TCanvas); override;
  267. procedure LoadFromStream(Stream: TStream); override;
  268. procedure SaveToStream(Stream: TStream); override;
  269. procedure SaveToFR3Stream(Stream: TStream); override;
  270. procedure DefinePopupMenu(Popup: TPopupMenu); override;
  271. end;
  272. TfrLineView = class(TfrView)
  273. public
  274. constructor Create; override;
  275. procedure Draw(Canvas: TCanvas); override;
  276. procedure DefinePopupMenu(Popup: TPopupMenu); override;
  277. function GetClipRgn(rt: TfrRgnType): HRGN; override;
  278. procedure SaveToFR3Stream(Stream: TStream); override;
  279. end;
  280. TfrBand = class(TObject)
  281. private
  282. Parent: TfrPage;
  283. View: TfrView;
  284. Flags: Word;
  285. Next, Prev: TfrBand;
  286. SubIndex, MaxY: Integer;
  287. EOFReached: Boolean;
  288. EOFArr: Array[0..31] of Boolean;
  289. Positions: Array[TfrDatasetPosition] of Integer;
  290. LastGroupValue: Variant;
  291. HeaderBand, FooterBand, LastBand: TfrBand;
  292. Values: TStringList;
  293. Count: Integer;
  294. DisableInit: Boolean;
  295. CalculatedHeight: Integer;
  296. procedure InitDataSet(Desc: String);
  297. procedure DoError;
  298. function CalcHeight: Integer;
  299. procedure StretchObjects(MaxHeight: Integer);
  300. procedure UnStretchObjects;
  301. procedure DrawObject(t: TfrView);
  302. procedure PrepareSubReports;
  303. procedure DoSubReports;
  304. function DrawObjects: Boolean;
  305. procedure DrawCrossCell(Parnt: TfrBand; CurX: Integer);
  306. procedure DrawCross;
  307. function CheckPageBreak(y, dy: Integer; PBreak: Boolean): Boolean;
  308. procedure DrawPageBreak;
  309. function HasCross: Boolean;
  310. function DoCalcHeight: Integer;
  311. procedure DoDraw;
  312. function Draw: Boolean;
  313. procedure InitValues;
  314. procedure DoAggregate;
  315. public
  316. x, y, dx, dy, maxdy: Integer;
  317. Typ: TfrBandType;
  318. PrintIfSubsetEmpty, NewPageAfter, Stretched, PageBreak, Visible: Boolean;
  319. Objects: TList;
  320. Memo, Script: TStringList;
  321. DataSet: TfrDataSet;
  322. IsVirtualDS: Boolean;
  323. VCDataSet: TfrDataSet;
  324. IsVirtualVCDS: Boolean;
  325. GroupCondition: String;
  326. ForceNewPage, ForceNewColumn: Boolean;
  327. constructor Create(ATyp: TfrBandType; AParent: TfrPage);
  328. destructor Destroy; override;
  329. end;
  330. TfrValue = class
  331. public
  332. Typ: TfrValueType;
  333. OtherKind: Integer; // for vtOther - typ, for vtDBField - format
  334. DataSet: String; // for vtDBField
  335. Field: String; // here is an expression for vtOther
  336. DSet: TfrTDataSet;
  337. end;
  338. TfrValues = class(TPersistent)
  339. private
  340. FItems: TStringList;
  341. function GetValue(Index: Integer): TfrValue;
  342. public
  343. constructor Create; virtual;
  344. destructor Destroy; override;
  345. function AddValue: Integer;
  346. function FindVariable(const s: String): TfrValue;
  347. procedure ReadBinaryData(Stream: TStream);
  348. procedure WriteBinaryData(Stream: TStream);
  349. procedure Clear;
  350. property Items: TStringList read FItems write FItems;
  351. property Objects[Index: Integer]: TfrValue read GetValue;
  352. end;
  353. TfrPage = class(TObject)
  354. private
  355. Bands: Array[TfrBandType] of TfrBand;
  356. Skip, InitFlag: Boolean;
  357. CurColumn, LastStaticColumnY, XAdjust: Integer;
  358. List: TList;
  359. Mode: TfrPageMode;
  360. PlayFrom: Integer;
  361. LastBand: TfrBand;
  362. ColPos, CurPos: Integer;
  363. procedure InitReport;
  364. procedure DoneReport;
  365. procedure TossObjects;
  366. procedure PrepareObjects;
  367. procedure FormPage;
  368. procedure DoAggregate(a: Array of TfrBandType);
  369. procedure AddRecord(b: TfrBand; rt: TfrBandRecType);
  370. procedure ClearRecList;
  371. function PlayRecList: Boolean;
  372. procedure DrawPageFooters;
  373. function BandExists(b: TfrBand): Boolean;
  374. procedure AfterPrint;
  375. procedure LoadFromStream(Stream: TStream);
  376. procedure SaveToStream(Stream: TStream);
  377. procedure ShowBand(b: TfrBand);
  378. public
  379. pgSize, pgWidth, pgHeight: Integer;
  380. pgMargins: TRect;
  381. pgOr: TPrinterOrientation;
  382. PrintToPrevPage, UseMargins: WordBool;
  383. PrnInfo: TfrPrnInfo;
  384. ColCount, ColWidth, ColGap: Integer;
  385. Objects, RTObjects: TList;
  386. CurY, CurBottomY: Integer;
  387. constructor Create(ASize, AWidth, AHeight: Integer; AOr: TPrinterOrientation);
  388. destructor Destroy; override;
  389. function TopMargin: Integer;
  390. function BottomMargin: Integer;
  391. function LeftMargin: Integer;
  392. function RightMargin: Integer;
  393. procedure Clear;
  394. procedure Delete(Index: Integer);
  395. function FindObjectByID(ID: Integer): Integer;
  396. function FindObject(Name: String): TfrView;
  397. function FindRTObject(Name: String): TfrView;
  398. procedure ChangePaper(ASize, AWidth, AHeight: Integer; AOr: TPrinterOrientation);
  399. procedure ShowBandByName(s: String);
  400. procedure ShowBandByType(bt: TfrBandType);
  401. procedure NewPage;
  402. procedure NewColumn(Band: TfrBand);
  403. end;
  404. TfrPages = class(TObject)
  405. private
  406. FPages: TList;
  407. Parent: TfrReport;
  408. function GetCount: Integer;
  409. function GetPages(Index: Integer): TfrPage;
  410. public
  411. constructor Create(AParent: TfrReport);
  412. destructor Destroy; override;
  413. procedure Clear;
  414. procedure Add;
  415. procedure Delete(Index: Integer);
  416. procedure LoadFromStream(Stream: TStream);
  417. procedure SaveToStream(Stream: TStream);
  418. property Pages[Index: Integer]: TfrPage read GetPages; default;
  419. property Count: Integer read GetCount;
  420. end;
  421. TfrEMFPages = class(TObject)
  422. private
  423. FPages: TList;
  424. Parent: TfrReport;
  425. function GetCount: Integer;
  426. function GetPages(Index: Integer): PfrPageInfo;
  427. procedure ExportData(Index: Integer);
  428. procedure PageToObjects(Index: Integer);
  429. procedure ObjectsToPage(Index: Integer);
  430. public
  431. constructor Create(AParent: TfrReport);
  432. destructor Destroy; override;
  433. procedure Clear;
  434. procedure Draw(Index: Integer; Canvas: TCanvas; DrawRect: TRect);
  435. procedure Add(APage: TfrPage);
  436. procedure Insert(Index: Integer; APage: TfrPage);
  437. procedure Delete(Index: Integer);
  438. procedure LoadFromStream(AStream: TStream);
  439. procedure SaveToStream(AStream: TStream);
  440. property Pages[Index: Integer]: PfrPageInfo read GetPages; default;
  441. property Count: Integer read GetCount;
  442. end;
  443. TfrReport = class(TComponent)
  444. private
  445. FPages: TfrPages;
  446. FEMFPages: TfrEMFPages;
  447. FVars: TStrings;
  448. FVal: TfrValues;
  449. FDataset: TfrDataset;
  450. FGrayedButtons: Boolean;
  451. FReportType: TfrReportType;
  452. FTitle: String;
  453. FShowProgress: Boolean;
  454. FModalPreview: Boolean;
  455. FModifyPrepared: Boolean;
  456. FStoreInDFM: Boolean;
  457. FPreview: TfrPreview;
  458. FPreviewButtons: TfrPreviewButtons;
  459. FInitialZoom: TfrPreviewZoom;
  460. FOnBeginDoc: TBeginDocEvent;
  461. FOnEndDoc: TEndDocEvent;
  462. FOnBeginPage: TBeginPageEvent;
  463. FOnEndPage: TEndPageEvent;
  464. FOnBeginBand: TBeginBandEvent;
  465. FOnEndBand: TEndBandEvent;
  466. FOnGetValue: TDetailEvent;
  467. FOnEnterRect: TEnterRectEvent;
  468. FOnProgress: TProgressEvent;
  469. FOnFunction: TFunctionEvent;
  470. FOnBeginColumn: TBeginColumnEvent;
  471. FOnPrintColumn: TPrintColumnEvent;
  472. FOnManualBuild: TManualBuildEvent;
  473. FCurrentFilter: TfrExportFilter;
  474. FPageNumbers: String;
  475. FCopies: Integer;
  476. FCurPage: TfrPage;
  477. function FormatValue(V: Variant; Format: Integer;
  478. const FormatStr: String): String;
  479. procedure OnGetParsFunction(const name: String; p1, p2, p3: Variant;
  480. var val: String);
  481. procedure PrepareDataSets;
  482. procedure BuildBeforeModal(Sender: TObject);
  483. procedure ExportBeforeModal(Sender: TObject);
  484. procedure PrintBeforeModal(Sender: TObject);
  485. function DoPrepareReport: Boolean;
  486. procedure DoBuildReport; virtual;
  487. procedure DoPrintReport(PageNumbers: String; Copies: Integer);
  488. procedure SetPrinterTo(PrnName: String);
  489. procedure SetVars(Value: TStrings);
  490. protected
  491. procedure DefineProperties(Filer: TFiler); override;
  492. procedure ReadBinaryData(Stream: TStream);
  493. procedure WriteBinaryData(Stream: TStream);
  494. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  495. public
  496. CanRebuild: Boolean; // true, if report can be rebuilded
  497. Terminated: Boolean;
  498. PrintToDefault, DoublePass: WordBool;
  499. FinalPass: Boolean;
  500. FileName: String;
  501. FR3Stream: Boolean;
  502. constructor Create(AOwner: TComponent); override;
  503. destructor Destroy; override;
  504. // service methods
  505. function FindVariable(Variable: String): Integer;
  506. procedure GetVariableValue(const s: String; var v: Variant);
  507. procedure GetVarList(CatNo: Integer; List: TStrings);
  508. procedure GetCategoryList(List: TStrings);
  509. function FindObject(Name: String): TfrView;
  510. // internal events used through report building
  511. procedure InternalOnEnterRect(Memo: TStringList; View: TfrView);
  512. procedure InternalOnExportData(View: TfrView);
  513. procedure InternalOnExportText(x, y: Integer; const text: String; View: TfrView);
  514. procedure InternalOnGetValue(ParName: String; var ParValue: String);
  515. procedure InternalOnProgress(Percent: Integer);
  516. procedure InternalOnBeginColumn(Band: TfrBand);
  517. procedure InternalOnPrintColumn(ColNo: Integer; var ColWidth: Integer);
  518. procedure FillQueryParams;
  519. // load/save methods
  520. procedure LoadFromStream(Stream: TStream);
  521. procedure SaveToStream(Stream: TStream);
  522. procedure LoadFromFile(FName: String);
  523. procedure SaveToFile(FName: String);
  524. procedure SaveToFR3File(FName: String);
  525. {$IFDEF IBO}
  526. procedure LoadFromDB(Table: TIB_DataSet; DocN: Integer);
  527. procedure SaveToDB(Table: TIB_DataSet; DocN: Integer);
  528. {$ELSE}
  529. procedure LoadFromDB(Table: TDataSet; DocN: Integer);
  530. procedure SaveToDB(Table: TDataSet; DocN: Integer);
  531. {$ENDIF}
  532. procedure LoadTemplate(fname: String; comm: TStrings;
  533. Bmp: TBitmap; Load: Boolean);
  534. procedure SaveTemplate(fname: String; comm: TStrings; Bmp: TBitmap);
  535. procedure LoadPreparedReport(FName: String);
  536. procedure SavePreparedReport(FName: String);
  537. // report manipulation methods
  538. procedure DesignReport;
  539. function PrepareReport: Boolean;
  540. procedure ExportTo(Filter: TClass; FileName: String);
  541. procedure ShowReport;
  542. procedure ShowPreparedReport;
  543. procedure PrintPreparedReport(PageNumbers: String; Copies: Integer);
  544. function ChangePrinter(OldIndex, NewIndex: Integer): Boolean;
  545. procedure EditPreparedReport(PageIndex: Integer);
  546. //
  547. property Pages: TfrPages read FPages;
  548. property EMFPages: TfrEMFPages read FEMFPages write FEMFPages;
  549. property Variables: TStrings read FVars write SetVars;
  550. property Values: TfrValues read FVal write FVal;
  551. published
  552. property Dataset: TfrDataset read FDataset write FDataset;
  553. property GrayedButtons: Boolean read FGrayedButtons write FGrayedButtons default False;
  554. property InitialZoom: TfrPreviewZoom read FInitialZoom write FInitialZoom;
  555. property ModalPreview: Boolean read FModalPreview write FModalPreview default True;
  556. property ModifyPrepared: Boolean read FModifyPrepared write FModifyPrepared default True;
  557. property Preview: TfrPreview read FPreview write FPreview;
  558. property PreviewButtons: TfrPreviewButtons read FPreviewButtons write FPreviewButtons;
  559. property ReportType: TfrReportType read FReportType write FReportType default rtSimple;
  560. property ShowProgress: Boolean read FShowProgress write FShowProgress default True;
  561. property StoreInDFM: Boolean read FStoreInDFM write FStoreInDFM default False;
  562. property Title: String read FTitle write FTitle;
  563. property OnBeginDoc: TBeginDocEvent read FOnBeginDoc write FOnBeginDoc;
  564. property OnEndDoc: TEndDocEvent read FOnEndDoc write FOnEndDoc;
  565. property OnBeginPage: TBeginPageEvent read FOnBeginPage write FOnBeginPage;
  566. property OnEndPage: TEndPageEvent read FOnEndPage write FOnEndPage;
  567. property OnBeginBand: TBeginBandEvent read FOnBeginBand write FOnBeginBand;
  568. property OnEndBand: TEndBandEvent read FOnEndBand write FOnEndBand;
  569. property OnGetValue: TDetailEvent read FOnGetValue write FOnGetValue;
  570. property OnEnterRect: TEnterRectEvent read FOnEnterRect write FOnEnterRect;
  571. property OnUserFunction: TFunctionEvent read FOnFunction write FOnFunction;
  572. property OnProgress: TProgressEvent read FOnProgress write FOnProgress;
  573. property OnBeginColumn: TBeginColumnEvent read FOnBeginColumn write FOnBeginColumn;
  574. property OnPrintColumn: TPrintColumnEvent read FOnPrintColumn write FOnPrintColumn;
  575. property OnManualBuild: TManualBuildEvent read FOnManualBuild write FOnManualBuild;
  576. end;
  577. TfrCompositeReport = class(TfrReport)
  578. private
  579. procedure DoBuildReport; override;
  580. public
  581. Reports: TList;
  582. constructor Create(AOwner: TComponent); override;
  583. destructor Destroy; override;
  584. end;
  585. TfrReportDesigner = class(TForm)
  586. public
  587. Page: TfrPage;
  588. Modified: Boolean;
  589. procedure RegisterObject(ButtonBmp: TBitmap; const ButtonHint: String;
  590. ButtonTag: Integer); virtual; abstract;
  591. procedure RegisterTool(MenuCaption: String; ButtonBmp: TBitmap;
  592. OnClick: TNotifyEvent); virtual; abstract;
  593. procedure BeforeChange; virtual; abstract;
  594. procedure AfterChange; virtual; abstract;
  595. procedure RedrawPage; virtual; abstract;
  596. end;
  597. TfrDataManager = class(TObject)
  598. public
  599. procedure LoadFromStream(Stream: TStream); virtual; abstract;
  600. procedure SaveToStream(Stream: TStream); virtual; abstract;
  601. procedure BeforePreparing; virtual; abstract;
  602. procedure AfterPreparing; virtual; abstract;
  603. procedure PrepareDataSet(ds: TfrTDataSet); virtual; abstract;
  604. function ShowParamsDialog: Boolean; virtual; abstract;
  605. procedure AfterParamsDialog; virtual; abstract;
  606. end;
  607. TfrObjEditorForm = class(TForm)
  608. public
  609. procedure ShowEditor(t: TfrView); virtual;
  610. end;
  611. TfrExportFilter = class(TObject)
  612. protected
  613. Stream: TStream;
  614. Lines: TList;
  615. procedure ClearLines;
  616. public
  617. constructor Create(AStream: TStream); virtual;
  618. destructor Destroy; override;
  619. procedure OnBeginDoc; virtual;
  620. procedure OnEndDoc; virtual;
  621. procedure OnBeginPage; virtual;
  622. procedure OnEndPage; virtual;
  623. procedure OnData(x, y: Integer; View: TfrView); virtual;
  624. procedure OnText(x, y: Integer; const text: String; View: TfrView); virtual;
  625. end;
  626. TfrFunctionLibrary = class(TObject)
  627. public
  628. List: TStringList;
  629. constructor Create; virtual;
  630. destructor Destroy; override;
  631. function OnFunction(const FName: String; p1, p2, p3: Variant;
  632. var val: String): Boolean;
  633. procedure DoFunction(FNo: Integer; p1, p2, p3: Variant; var val: String);
  634. virtual; abstract;
  635. end;
  636. TfrCompressor = class(TObject)
  637. public
  638. Enabled: Boolean;
  639. procedure Compress(StreamIn, StreamOut: TStream); virtual;
  640. procedure DeCompress(StreamIn, StreamOut: TStream); virtual;
  641. end;
  642. function frCreateObject(Typ: Byte; const ClassName: String): TfrView;
  643. procedure frRegisterObject(ClassRef: TClass; ButtonBmp: TBitmap;
  644. const ButtonHint: String; EditorForm: TfrObjEditorForm);
  645. procedure frRegisterExportFilter(ClassRef: TClass;
  646. const FilterDesc, FilterExt: String);
  647. procedure frRegisterFunctionLibrary(ClassRef: TClass);
  648. procedure frRegisterTool(MenuCaption: String; ButtonBmp: TBitmap; OnClick: TNotifyEvent);
  649. function GetDefaultDataSet: TfrTDataSet;
  650. const
  651. frCurrentVersion = 23; // this is current version (2.3)
  652. frSpecCount = 9;
  653. frSpecFuncs: Array[0..frSpecCount - 1] of String = ('PAGE#', '',
  654. 'DATE', 'TIME', 'LINE#', 'LINETHROUGH#', 'COLUMN#', 'CURRENT#', 'TOTALPAGES');
  655. frColors: Array[0..15] of TColor =
  656. (clWhite, clBlack, clMaroon, clGreen, clOlive, clNavy, clPurple, clTeal,
  657. clGray, clSilver, clRed, clLime, clYellow, clBlue, clFuchsia, clAqua);
  658. type
  659. PfrTextRec = ^TfrTextRec;
  660. TfrTextRec = record
  661. Next: PfrTextRec;
  662. X: Integer;
  663. Text: String[255];
  664. FontName: String[32];
  665. FontSize, FontStyle, FontColor, FontCharset, FillColor: Integer;
  666. end;
  667. TfrAddInObjectInfo = record
  668. ClassRef: TClass;
  669. EditorForm: TfrObjEditorForm;
  670. ButtonBmp: TBitmap;
  671. ButtonHint: String;
  672. end;
  673. TfrExportFilterInfo = record
  674. ClassRef: TClass;
  675. FilterDesc, FilterExt: String;
  676. end;
  677. TfrFunctionInfo = record
  678. FunctionLibrary: TfrFunctionLibrary;
  679. end;
  680. TfrToolsInfo = record
  681. Caption: String;
  682. ButtonBmp: TBitmap;
  683. OnClick: TNotifyEvent;
  684. end;
  685. var
  686. frDesigner: TfrReportDesigner; // designer reference
  687. frDataManager: TfrDataManager; // data manager reference
  688. frParser: TfrParser; // parser reference
  689. frInterpretator: TfrInterpretator; // interpretator reference
  690. frVariables: TfrVariables; // report variables reference
  691. frCompressor: TfrCompressor; // compressor reference
  692. CurReport: TfrReport; // currently proceeded report
  693. MasterReport: TfrReport; // reference to main composite report
  694. CurView: TfrView; // currently proceeded view
  695. CurBand: TfrBand; // currently proceeded band
  696. CurPage: TfrPage; // currently proceeded page
  697. DocMode: (dmDesigning, dmPrinting); // current mode
  698. DisableDrawing: Boolean;
  699. frAddIns: Array[0..31] of TfrAddInObjectInfo; // add-in objects
  700. frAddInsCount: Integer;
  701. frFilters: Array[0..31] of TfrExportFilterInfo; // export filters
  702. frFiltersCount: Integer;
  703. frFunctions: Array[0..31] of TfrFunctionInfo; // function libraries
  704. frFunctionsCount: Integer;
  705. frTools: Array[0..31] of TfrToolsInfo; // tools
  706. frToolsCount: Integer;
  707. PageNo: Integer; // current page number in Building mode
  708. frCharset: 0..255;
  709. frBandNames: Array[0..21] of String;
  710. frSpecArr: Array[0..frSpecCount - 1] of String;
  711. frDateFormats, frTimeFormats: Array[0..3] of String;
  712. frVersion: Byte; // version of currently loaded report
  713. SMemo: TStringList; // temporary memo used during TfrView drawing
  714. ShowBandTitles: Boolean = True;
  715. (*
  716. FRE_COMPATIBLEREAD variable added for migrating from older versions
  717. of FreeReport and will be removed in next releases as soon as possible.
  718. *)
  719. {$IFDEF FREEREP2217READ}
  720. FRE_COMPATIBLE_READ: Boolean = False;
  721. {$ENDIF}
  722. implementation
  723. uses
  724. FR_Fmted, FR_Prntr, FR_Progr, FR_Utils, FR_Const
  725. {$IFDEF JPEG}, JPEG {$ENDIF};
  726. {$R FR_Lng1.RES}
  727. type
  728. TfrStdFunctionLibrary = class(TfrFunctionLibrary)
  729. public
  730. constructor Create; override;
  731. procedure DoFunction(FNo: Integer; p1, p2, p3: Variant; var val: String); override;
  732. end;
  733. TInterpretator = class(TfrInterpretator)
  734. public
  735. procedure GetValue(const Name: String; var Value: Variant); override;
  736. procedure SetValue(const Name: String; Value: Variant); override;
  737. procedure DoFunction(const name: String; p1, p2, p3: Variant;
  738. var val: String); override;
  739. end;
  740. var
  741. VHeight: Integer; // used for height calculation of TfrMemoView
  742. SBmp: TBitmap; // small bitmap used by TfrBandView drawing
  743. TempBmp: TBitmap; // temporary bitmap used by TfrMemoView
  744. CurDate, CurTime: TDateTime; // date/time of report starting
  745. CurValue: Variant; // used for highlighting
  746. AggrBand: TfrBand; // used for aggregate functions
  747. CurVariable: String;
  748. IsColumns: Boolean;
  749. SavedAllPages: Integer; // number of pages in entire report
  750. ErrorFlag: Boolean; // error occured through TfrView drawing
  751. ErrorStr: String; // error description
  752. SubValue: String; // used in GetValue event handler
  753. ObjID: Integer = 0;
  754. BoolStr: Array[0..3] of String;
  755. HookList: TList;
  756. // variables used through report building
  757. PrevY, PrevBottomY, ColumnXAdjust: Integer;
  758. Append, WasPF: Boolean;
  759. CompositeMode: Boolean;
  760. {----------------------------------------------------------------------------}
  761. function frCreateObject(Typ: Byte; const ClassName: String): TfrView;
  762. var
  763. i: Integer;
  764. begin
  765. Result := nil;
  766. case Typ of
  767. gtMemo: Result := TfrMemoView.Create;
  768. gtPicture: Result := TfrPictureView.Create;
  769. gtBand: Result := TfrBandView.Create;
  770. gtSubReport: Result := TfrSubReportView.Create;
  771. gtLine: Result := TfrLineView.Create;
  772. gtAddIn:
  773. begin
  774. for i := 0 to frAddInsCount - 1 do
  775. if frAddIns[i].ClassRef.ClassName = ClassName then
  776. begin
  777. Result := TfrView(frAddIns[i].ClassRef.NewInstance);
  778. Result.Create;
  779. Result.Typ := gtAddIn;
  780. break;
  781. end;
  782. if Result = nil then
  783. raise EClassNotFound.Create('Íå íàéäåí êëàññ ' + ClassName);
  784. end;
  785. end;
  786. if Result <> nil then
  787. begin
  788. Result.ID := ObjID;
  789. Inc(ObjID);
  790. end;
  791. end;
  792. procedure frRegisterObject(ClassRef: TClass; ButtonBmp: TBitmap;
  793. const ButtonHint: String; EditorForm: TfrObjEditorForm);
  794. begin
  795. frAddIns[frAddInsCount].ClassRef := ClassRef;
  796. frAddIns[frAddInsCount].EditorForm := EditorForm;
  797. frAddIns[frAddInsCount].ButtonBmp := ButtonBmp;
  798. frAddIns[frAddInsCount].ButtonHint := ButtonHint;
  799. if frDesigner <> nil then
  800. frDesigner.RegisterObject(ButtonBmp, ButtonHint,
  801. Integer(gtAddIn) + frAddInsCount);
  802. Inc(frAddInsCount);
  803. end;
  804. procedure frRegisterExportFilter(ClassRef: TClass;
  805. const FilterDesc, FilterExt: String);
  806. begin
  807. frFilters[frFiltersCount].ClassRef := ClassRef;
  808. frFilters[frFiltersCount].FilterDesc := FilterDesc;
  809. frFilters[frFiltersCount].FilterExt := FilterExt;
  810. Inc(frFiltersCount);
  811. end;
  812. procedure frRegisterFunctionLibrary(ClassRef: TClass);
  813. begin
  814. frFunctions[frFunctionsCount].FunctionLibrary :=
  815. TfrFunctionLibrary(ClassRef.NewInstance);
  816. frFunctions[frFunctionsCount].FunctionLibrary.Create;
  817. Inc(frFunctionsCount);
  818. end;
  819. procedure frRegisterTool(MenuCaption: String; ButtonBmp: TBitmap; OnClick: TNotifyEvent);
  820. begin
  821. frTools[frToolsCount].Caption := MenuCaption;
  822. frTools[frToolsCount].ButtonBmp := ButtonBmp;
  823. frTools[frToolsCount].OnClick := OnClick;
  824. if frDesigner <> nil then
  825. frDesigner.RegisterTool(MenuCaption, ButtonBmp, OnClick);
  826. Inc(frToolsCount);
  827. end;
  828. function Create90Font(Font: TFont): HFont;
  829. var
  830. F: TLogFont;
  831. begin
  832. GetObject(Font.Handle, SizeOf(TLogFont), @F);
  833. F.lfEscapement := 900;
  834. F.lfOrientation := 900;
  835. Result := CreateFontIndirect(F);
  836. end;
  837. function GetDefaultDataSet: TfrTDataSet;
  838. var
  839. Res: TfrDataset;
  840. begin
  841. Result := nil; Res := nil;
  842. if CurBand <> nil then
  843. case CurBand.Typ of
  844. btMasterData, btReportSummary, btMasterFooter,
  845. btGroupHeader, btGroupFooter:
  846. Res := CurPage.Bands[btMasterData].DataSet;
  847. btDetailData, btDetailFooter:
  848. Res := CurPage.Bands[btDetailData].DataSet;
  849. btSubDetailData, btSubDetailFooter:
  850. Res := CurPage.Bands[btSubDetailData].DataSet;
  851. btCrossData, btCrossFooter:
  852. Res := CurPage.Bands[btCrossData].DataSet;
  853. end;
  854. if (Res <> nil) and (Res is TfrDBDataset) then
  855. Result := TfrDBDataSet(Res).GetDataSet;
  856. end;
  857. function ReadString(Stream: TStream): String;
  858. begin
  859. if frVersion >= 23 then
  860. {$IFDEF FREEREP2217READ}
  861. Result := frReadString(Stream) // load in current format
  862. else
  863. if (frVersion = 22) and FRE_COMPATIBLE_READ then
  864. Result := frReadString2217(Stream) // load in bad format
  865. else
  866. {$ELSE}
  867. Result := frReadString(Stream) else
  868. {$ENDIF}
  869. Result := frReadString22(Stream);
  870. end;
  871. procedure ReadMemo(Stream: TStream; Memo: TStrings);
  872. begin
  873. if frVersion >= 23 then
  874. {$IFDEF FREEREP2217READ}
  875. frReadMemo(Stream, Memo) // load in current format
  876. else
  877. if (frVersion = 22) and FRE_COMPATIBLE_READ then
  878. Memo.Text := frReadString2217(Stream) // load in bad format
  879. else
  880. {$ELSE}
  881. frReadMemo(Stream, Memo) else
  882. {$ENDIF}
  883. frReadMemo22(Stream, Memo);
  884. end;
  885. procedure CreateDS(Desc: String; var DataSet: TfrDataSet; var IsVirtualDS: Boolean);
  886. begin
  887. if (Desc <> '') and (Desc[1] in ['1'..'9']) then
  888. begin
  889. DataSet := TfrUserDataSet.Create(nil);
  890. DataSet.RangeEnd := reCount;
  891. DataSet.RangeEndCount := StrToInt(Desc);
  892. IsVirtualDS := True;
  893. end
  894. else
  895. DataSet := frFindComponent(CurReport.Owner, Desc) as TfrDataSet;
  896. if DataSet <> nil then
  897. DataSet.Init;
  898. end;
  899. {----------------------------------------------------------------------------}
  900. constructor TfrView.Create;
  901. begin
  902. inherited Create;
  903. Parent := nil;
  904. Memo := TStringList.Create;
  905. Memo1 := TStringList.Create;
  906. Script := TStringList.Create;
  907. FrameWidth := 1;
  908. FrameColor := clBlack;
  909. FillColor := clNone;
  910. Format := 2*256 + Ord(DecimalSeparator);
  911. BaseName := 'View';
  912. Visible := True;
  913. StreamMode := smDesigning;
  914. ScaleX := 1; ScaleY := 1;
  915. OffsX := 0; OffsY := 0;
  916. Flags := flStretched;
  917. end;
  918. destructor TfrView.Destroy;
  919. begin
  920. Memo.Free;
  921. Memo1.Free;
  922. Script.Free;
  923. inherited Destroy;
  924. end;
  925. procedure TfrView.Assign(From: TfrView);
  926. begin
  927. Name := From.Name;
  928. Typ := From.Typ;
  929. Selected := From.Selected;
  930. x := From.x; y := From.y; dx := From.dx; dy := From.dy;
  931. Flags := From.Flags;
  932. FrameTyp := From.FrameTyp;
  933. FrameWidth := From.FrameWidth;
  934. FrameColor := From.FrameColor;
  935. FrameStyle := From.FrameStyle;
  936. FillColor := From.FillColor;
  937. Format := From.Format;
  938. FormatStr := From.FormatStr;
  939. Visible := From.Visible;
  940. Memo.Assign(From.Memo);
  941. Script.Assign(From.Script);
  942. end;
  943. procedure TfrView.CalcGaps;
  944. var
  945. bx, by, bx1, by1, wx1, wx2, wy1, wy2: Integer;
  946. begin
  947. SaveX := x; SaveY := y; SaveDX := dx; SaveDY := dy;
  948. SaveFW := FrameWidth;
  949. if DocMode = dmDesigning then
  950. begin
  951. ScaleX := 1; ScaleY := 1;
  952. OffsX := 0; OffsY := 0;
  953. end;
  954. x := Round(x * ScaleX) + OffsX;
  955. y := Round(y * ScaleY) + OffsY;
  956. dx := Round(dx * ScaleX);
  957. dy := Round(dy * ScaleY);
  958. wx1 := Round((FrameWidth * ScaleX - 1) / 2);
  959. wx2 := Round(FrameWidth * ScaleX / 2);
  960. wy1 := Round((FrameWidth * ScaleY - 1) / 2);
  961. wy2 := Round(FrameWidth * ScaleY / 2);
  962. FrameWidth := FrameWidth * ScaleX;
  963. gapx := wx2 + 2; gapy := wy2 div 2 + 1;
  964. bx := x;
  965. by := y;
  966. bx1 := Round((SaveX + SaveDX) * ScaleX + OffsX);
  967. by1 := Round((SaveY + SaveDY) * ScaleY + OffsY);
  968. if (FrameTyp and $1) <> 0 then Dec(bx1, wx2);
  969. if (FrameTyp and $2) <> 0 then Dec(by1, wy2);
  970. if (FrameTyp and $4) <> 0 then Inc(bx, wx1);
  971. if (FrameTyp and $8) <> 0 then Inc(by, wy1);
  972. DRect := Rect(bx, by, bx1 + 1, by1 + 1);
  973. end;
  974. procedure TfrView.RestoreCoord;
  975. begin
  976. x := SaveX;
  977. y := SaveY;
  978. dx := SaveDX;
  979. dy := SaveDY;
  980. FrameWidth := SaveFW;
  981. end;
  982. procedure TfrView.ShowBackground;
  983. var
  984. fp: TColor;
  985. begin
  986. if DisableDrawing then Exit;
  987. if (DocMode = dmPrinting) and (FillColor = clNone) then Exit;
  988. fp := FillColor;
  989. if (DocMode = dmDesigning) and (fp = clNone) then
  990. fp := clWhite;
  991. Canvas.Brush.Color := fp;
  992. if DocMode = dmDesigning then
  993. Canvas.FillRect(DRect) else
  994. Canvas.FillRect(Rect(x, y,
  995. // use calculating coords instead of dx, dy - for best view
  996. Round((SaveX + SaveDX) * ScaleX + OffsX), Round((SaveY + SaveDY) * ScaleY + OffsY)));
  997. end;
  998. procedure TfrView.ShowFrame;
  999. var
  1000. x1, y1: Integer;
  1001. procedure Line(x, y, dx, dy: Integer);
  1002. begin
  1003. Canvas.MoveTo(x, y);
  1004. Canvas.LineTo(x + dx, y + dy);
  1005. end;
  1006. procedure Line1(x, y, x1, y1: Integer);
  1007. var
  1008. i, w: Integer;
  1009. begin
  1010. if Canvas.Pen.Style = psSolid then
  1011. begin
  1012. if FrameStyle <> 5 then
  1013. begin
  1014. Canvas.MoveTo(x, y);
  1015. Canvas.LineTo(x1, y1);
  1016. end
  1017. else
  1018. begin
  1019. if x = x1 then
  1020. begin
  1021. Canvas.MoveTo(x - Round(FrameWidth), y);
  1022. Canvas.LineTo(x1 - Round(FrameWidth), y1);
  1023. Canvas.Pen.Color := FillColor;
  1024. Canvas.MoveTo(x, y);
  1025. Canvas.LineTo(x1, y1);
  1026. Canvas.Pen.Color := FrameColor;
  1027. Canvas.MoveTo(x + Round(FrameWidth), y);
  1028. Canvas.LineTo(x1 + Round(FrameWidth), y1);
  1029. end
  1030. else
  1031. begin
  1032. Canvas.MoveTo(x, y - Round(FrameWidth));
  1033. Canvas.LineTo(x1, y1 - Round(FrameWidth));
  1034. Canvas.Pen.Color := FillColor;
  1035. Canvas.MoveTo(x, y);
  1036. Canvas.LineTo(x1, y1);
  1037. Canvas.Pen.Color := FrameColor;
  1038. Canvas.MoveTo(x, y + Round(FrameWidth));
  1039. Canvas.LineTo(x1, y1 + Round(FrameWidth));
  1040. end;
  1041. end
  1042. end
  1043. else
  1044. begin
  1045. Canvas.Brush.Color := FillColor;
  1046. w := Canvas.Pen.Width;
  1047. Canvas.Pen.Width := 1;
  1048. if x = x1 then
  1049. for i := 0 to w - 1 do
  1050. begin
  1051. Canvas.MoveTo(x - w div 2 + i, y);
  1052. Canvas.LineTo(x - w div 2 + i, y1);
  1053. end
  1054. else
  1055. for i := 0 to w - 1 do
  1056. begin
  1057. Canvas.MoveTo(x, y - w div 2 + i);
  1058. Canvas.LineTo(x1, y - w div 2 + i);
  1059. end;
  1060. Canvas.Pen.Width := w;
  1061. end;
  1062. end;
  1063. begin
  1064. if DisableDrawing then Exit;
  1065. if (DocMode = dmPrinting) and ((FrameTyp and $F) = 0) then Exit;
  1066. with Canvas do
  1067. begin
  1068. Brush.Style := bsClear;
  1069. Pen.Style := psSolid;
  1070. if (dx > 0) and (dy > 0) and (DocMode = dmDesigning) then
  1071. begin
  1072. Pen.Color := clBlack;
  1073. Pen.Width := 1;
  1074. Line(x, y + 3, 0, -3); Line(x, y, 4, 0);
  1075. Line(x, y + dy - 3, 0, 3); Line(x, y + dy, 4, 0);
  1076. Line(x + dx - 3, y, 3, 0); Line(x + dx, y, 0, 4);
  1077. Line(x + dx - 3, y + dy, 3, 0); Line(x + dx, y + dy, 0, -4);
  1078. end;
  1079. Pen.Color := FrameColor;
  1080. Pen.Width := Round(FrameWidth);
  1081. if FrameStyle <> 5 then
  1082. Pen.Style := TPenStyle(FrameStyle);
  1083. // use calculating coords instead of dx, dy - for best view
  1084. x1 := Round((SaveX + SaveDX) * ScaleX + OffsX);
  1085. y1 := Round((SaveY + SaveDY) * ScaleY + OffsY);
  1086. if ((FrameTyp and $F) = $F) and (FrameStyle = 0) then
  1087. Rectangle(x, y, x1 + 1, y1 + 1)
  1088. else
  1089. begin
  1090. if (FrameTyp and $1) <> 0 then Line1(x1, y, x1, y1);
  1091. if (FrameTyp and $4) <> 0 then Line1(x, y, x, y1);
  1092. if (FrameTyp and $2) <> 0 then Line1(x, y1, x1, y1);
  1093. if (FrameTyp and $8) <> 0 then Line1(x, y, x1, y);
  1094. end;
  1095. end;
  1096. end;
  1097. procedure TfrView.BeginDraw(ACanvas: TCanvas);
  1098. begin
  1099. Canvas := ACanvas;
  1100. CurView := Self;
  1101. end;
  1102. procedure TfrView.Print(Stream: TStream);
  1103. begin
  1104. BeginDraw(Canvas);
  1105. Memo1.Assign(Memo);
  1106. CurReport.InternalOnEnterRect(Memo1, Self);
  1107. frInterpretator.DoScript(Script);
  1108. if not Visible then Exit;
  1109. Stream.Write(Typ, 1);
  1110. if Typ = gtAddIn then
  1111. frWriteString(Stream, ClassName);
  1112. SaveToStream(Stream);
  1113. end;
  1114. procedure TfrView.ExportData;
  1115. begin
  1116. CurReport.InternalOnExportData(Self);
  1117. end;
  1118. procedure TfrView.LoadFromStream(Stream: TStream);
  1119. var
  1120. w: Integer;
  1121. begin
  1122. with Stream do
  1123. begin
  1124. if StreamMode = smDesigning then
  1125. if frVersion >= 23 then
  1126. Name := ReadString(Stream) else
  1127. CreateUniqueName;
  1128. Read(x, 30); // this is equal to, but much faster:
  1129. { Read(x, 4); Read(y, 4); Read(dx, 4); Read(dy, 4);
  1130. Read(Flags, 2);
  1131. Read(FrameTyp, 2);
  1132. Read(FrameWidth, 4);
  1133. Read(FrameColor, 4);
  1134. Read(FrameStyle, 2);}
  1135. Read(FillColor, 4);
  1136. if StreamMode = smDesigning then
  1137. begin
  1138. Read(Format, 4);
  1139. FormatStr := ReadString(Stream);
  1140. end;
  1141. ReadMemo(Stream, Memo);
  1142. if (frVersion >= 23) and (StreamMode = smDesigning) then
  1143. begin
  1144. ReadMemo(Stream, Script);
  1145. Read(Visible, 2);
  1146. end;
  1147. w := PInteger(@FrameWidth)^;
  1148. if w <= 10 then
  1149. w := w * 1000;
  1150. FrameWidth := w / 1000;
  1151. end;
  1152. end;
  1153. procedure TfrView.SaveToStream(Stream: TStream);
  1154. var
  1155. w: Integer;
  1156. f: Single;
  1157. begin
  1158. f := FrameWidth;
  1159. if f <> Int(f) then
  1160. w := Round(FrameWidth * 1000) else
  1161. w := Round(f);
  1162. PInteger(@FrameWidth)^ := w;
  1163. with Stream do
  1164. begin
  1165. if StreamMode = smDesigning then
  1166. frWriteString(Stream, Name);
  1167. Write(x, 30); // this is equal to, but much faster:
  1168. { Write(x, 4); Write(y, 4); Write(dx, 4); Write(dy, 4);
  1169. Write(Flags, 2);
  1170. Write(FrameTyp, 2);
  1171. Write(FrameWidth, 4);
  1172. Write(FrameColor, 4);
  1173. Write(FrameStyle, 2);}
  1174. Write(FillColor, 4);
  1175. if StreamMode = smDesigning then
  1176. begin
  1177. Write(Format, 4);
  1178. frWriteString(Stream, FormatStr);
  1179. frWriteMemo(Stream, Memo);
  1180. end
  1181. else
  1182. frWriteMemo(Stream, Memo1);
  1183. if StreamMode = smDesigning then
  1184. begin
  1185. frWriteMemo(Stream, Script);
  1186. Write(Visible, 2);
  1187. end;
  1188. end;
  1189. FrameWidth := f;
  1190. end;
  1191. procedure TfrView.SaveToFR3Stream(Stream: TStream);
  1192. var
  1193. FTyp: Integer;
  1194. s: String;
  1195. procedure WriteStr(const s: String);
  1196. begin
  1197. Stream.Write(s[1], Length(s));
  1198. end;
  1199. begin
  1200. s := ClassName;
  1201. if Pos('Tfr', s) = 1 then
  1202. begin
  1203. Delete(s, 1, 3);
  1204. s := 'Tfrx' + s;
  1205. if CompareText(s, 'TfrxSubreportView') = 0 then
  1206. s := 'TfrxSubreport';
  1207. end;
  1208. WriteStr('<' + s + ' ');
  1209. WriteStr('Name="' + Name +
  1210. '" Left="' + IntToStr(x) + '" Top="' + IntToStr(y) +
  1211. '" Width="' + IntToStr(dx) + '" Height="' + IntToStr(dy) +
  1212. '" Color="' + IntToStr(FillColor) + '"');
  1213. if not Visible then
  1214. WriteStr(' Visible="False"');
  1215. FTyp := 0;
  1216. if (FrameTyp and frftLeft) <> 0 then
  1217. FTyp := FTyp or 1;
  1218. if (FrameTyp and frftRight) <> 0 then
  1219. FTyp := FTyp or 2;
  1220. if (FrameTyp and frftUp) <> 0 then
  1221. FTyp := FTyp or 4;
  1222. if (FrameTyp and frftDown) <> 0 then
  1223. FTyp := FTyp or 8;
  1224. WriteStr(' Frame.Typ="' + IntToStr(FTyp) +
  1225. '" Frame.Width="' + FloatToStr(FrameWidth) +
  1226. '" Frame.Color="' + IntToStr(FrameColor) +
  1227. '" Frame.Style="' + IntToStr(FrameStyle) +
  1228. '" GapX="' + IntToStr(gapx) + '" GapY="' + IntToStr(gapy) +
  1229. {'" TagStr="' + StrToXML(Tag) + }'" Memo.text="' + StrToXML(Memo.Text) + '"');
  1230. { ba := BandAlign;
  1231. if ba = baRest then
  1232. ba := baWidth
  1233. else if ba = baTop then
  1234. ba := baNone;
  1235. WriteStr(' Align="' + IntToStr(ba) + '"');}
  1236. if Script.Count > 0 then
  1237. WriteStr(' OnBeforePrint="' + Name + 'OnBeforePrint' +
  1238. '" OnClick="' + Name + 'OnBeforePrint' +
  1239. '" OnActivate="' + Name + 'OnBeforePrint"');
  1240. { RTyp := 0;
  1241. if ((Restrictions and frrfDontEditMemo) <> 0) or
  1242. ((Restrictions and frrfDontEditScript) <> 0) or
  1243. ((Restrictions and frrfDontEditContents) <> 0) or
  1244. ((Restrictions and frrfDontModify) <> 0) then
  1245. RTyp := RTyp or 1;
  1246. if (Restrictions and frrfDontSize) <> 0 then
  1247. RTyp := RTyp or 2;
  1248. if (Restrictions and frrfDontMove) <> 0 then
  1249. RTyp := RTyp or 4;
  1250. if (Restrictions and frrfDontDelete) <> 0 then
  1251. RTyp := RTyp or 8;
  1252. WriteStr(' Restrictions="' + IntToStr(RTyp) + '"');}
  1253. end;
  1254. procedure TfrView.Resized;
  1255. begin
  1256. end;
  1257. procedure TfrView.GetBlob(b: TfrTField);
  1258. begin
  1259. end;
  1260. procedure TfrView.OnHook(View: TfrView);
  1261. begin
  1262. end;
  1263. function TfrView.GetClipRgn(rt: TfrRgnType): HRGN;
  1264. var
  1265. bx, by, bx1, by1, w1, w2: Integer;
  1266. begin
  1267. if FrameStyle = 5 then
  1268. begin
  1269. w1 := Round(FrameWidth * 1.5);
  1270. w2 := Round((FrameWidth - 1) / 2 + FrameWidth);
  1271. end
  1272. else
  1273. begin
  1274. w1 := Round(FrameWidth / 2);
  1275. w2 := Round((FrameWidth - 1) / 2);
  1276. end;
  1277. bx := x; by := y; bx1 := x + dx + 1; by1 := y + dy + 1;
  1278. if (FrameTyp and $1) <> 0 then Inc(bx1, w2);
  1279. if (FrameTyp and $2) <> 0 then Inc(by1, w2);
  1280. if (FrameTyp and $4) <> 0 then Dec(bx, w1);
  1281. if (FrameTyp and $8) <> 0 then Dec(by, w1);
  1282. if rt = rtNormal then
  1283. Result := CreateRectRgn(bx, by, bx1, by1) else
  1284. Result := CreateRectRgn(bx - 10, by - 10, bx1 + 10, by1 + 10);
  1285. end;
  1286. procedure TfrView.CreateUniqueName;
  1287. var
  1288. i: Integer;
  1289. begin
  1290. Name := '';
  1291. for i := 1 to 10000 do
  1292. if CurReport.FindObject(BaseName + IntToStr(i)) = nil then
  1293. begin
  1294. Name := BaseName + IntToStr(i);
  1295. Exit;
  1296. end;
  1297. end;
  1298. procedure TfrView.SetBounds(Left, Top, Width, Height: Integer);
  1299. begin
  1300. x := Left;
  1301. y := Top;
  1302. dx := Width;
  1303. dy := Height;
  1304. end;
  1305. procedure TfrView.DefinePopupMenu(Popup: TPopupMenu);
  1306. var
  1307. m: TMenuItem;
  1308. begin
  1309. m := TMenuItem.Create(Popup);
  1310. m.Caption := '-';
  1311. Popup.Items.Add(m);
  1312. m := TMenuItem.Create(Popup);
  1313. m.Caption := LoadStr(SStretched);
  1314. m.OnClick := P1Click;
  1315. m.Checked := (Flags and flStretched) <> 0;
  1316. Popup.Items.Add(m);
  1317. end;
  1318. procedure TfrView.P1Click(Sender: TObject);
  1319. var
  1320. i: Integer;
  1321. t: TfrView;
  1322. begin
  1323. frDesigner.BeforeChange;
  1324. with Sender as TMenuItem do
  1325. begin
  1326. Checked := not Checked;
  1327. for i := 0 to frDesigner.Page.Objects.Count-1 do
  1328. begin
  1329. t := frDesigner.Page.Objects[i];
  1330. if t.Selected then
  1331. t.Flags := (t.Flags and not flStretched) + Word(Checked);
  1332. end;
  1333. end;
  1334. frDesigner.AfterChange;
  1335. end;
  1336. {----------------------------------------------------------------------------}
  1337. constructor TfrMemoView.Create;
  1338. begin
  1339. inherited Create;
  1340. Typ := gtMemo;
  1341. FFont := TFont.Create;
  1342. FFont.Name := 'Arial';
  1343. FFont.Size := 10;
  1344. FFont.Color := clBlack;
  1345. {$IFNDEF Delphi2}
  1346. FFont.Charset := frCharset;
  1347. {$ENDIF}
  1348. Highlight.FontColor := clBlack;
  1349. Highlight.FillColor := clWhite;
  1350. Highlight.FontStyle := 2; // fsBold
  1351. BaseName := 'Memo';
  1352. Flags := flStretched + flWordWrap;
  1353. LineSpacing := 2;
  1354. CharacterSpacing := 0;
  1355. end;
  1356. destructor TfrMemoView.Destroy;
  1357. begin
  1358. FFont.Free;
  1359. inherited Destroy;
  1360. end;
  1361. procedure TfrMemoView.SetFont(Value: TFont);
  1362. begin
  1363. FFont.Assign(Value);
  1364. end;
  1365. procedure TfrMemoView.Assign(From: TfrView);
  1366. begin
  1367. inherited Assign(From);
  1368. Font := TfrMemoView(From).Font;
  1369. Adjust := TfrMemoView(From).Adjust;
  1370. Highlight := TfrMemoView(From).Highlight;
  1371. HighlightStr := TfrMemoView(From).HighlightStr;
  1372. LineSpacing := TfrMemoView(From).LineSpacing;
  1373. end;
  1374. procedure TfrMemoView.ExpandVariables;
  1375. var
  1376. i: Integer;
  1377. s: String;
  1378. procedure GetData(var s: String);
  1379. var
  1380. i, j: Integer;
  1381. s1, s2: String;
  1382. begin
  1383. i := 1;
  1384. repeat
  1385. while (i < Length(s)) and (s[i] <> '[') do Inc(i);
  1386. s1 := GetBrackedVariable(s, i, j);
  1387. if i <> j then
  1388. begin
  1389. Delete(s, i, j - i + 1);
  1390. s2 := '';
  1391. CurReport.InternalOnGetValue(s1, s2);
  1392. Insert(s2, s, i);
  1393. Inc(i, Length(s2));
  1394. j := 0;
  1395. end;
  1396. until i = j;
  1397. end;
  1398. begin
  1399. Memo1.Clear;
  1400. for i := 0 to Memo.Count - 1 do
  1401. begin
  1402. s := Memo[i];
  1403. if Length(s) > 0 then
  1404. begin
  1405. GetData(s);
  1406. Memo1.Text := Memo1.Text + s;
  1407. end
  1408. else
  1409. Memo1.Add('');
  1410. end;
  1411. end;
  1412. procedure TfrMemoView.AssignFont(Canvas: TCanvas);
  1413. begin
  1414. with Canvas do
  1415. begin
  1416. Brush.Style := bsClear;
  1417. Font := Self.Font;
  1418. if not IsPrinting then
  1419. Font.Height := -Round(Font.Size * 96 / 72 * ScaleY);
  1420. end;
  1421. end;
  1422. type
  1423. TWordBreaks = string;
  1424. const
  1425. gl: set of Char = ['À', 'Å', '¨', 'È', 'Î', 'Ó', 'Û', 'Ý', 'Þ', 'ß'];
  1426. r_sogl: set of Char = ['Ú', 'Ü'];
  1427. spaces: set of Char = [' ', '.', ',', '-'];
  1428. function BreakWord(s: String): TWordBreaks;
  1429. var
  1430. i: Integer;
  1431. CanBreak: Boolean;
  1432. begin
  1433. Result := '';
  1434. s := AnsiUpperCase(s);
  1435. if Length(s) > 4 then
  1436. begin
  1437. i := 2;
  1438. repeat
  1439. CanBreak := False;
  1440. if s[i] in gl then
  1441. begin
  1442. if (s[i + 1] in gl) or (s[i + 2] in gl) then CanBreak := True;
  1443. end
  1444. else
  1445. begin
  1446. if not (s[i + 1] in gl) and not (s[i + 1] in r_sogl) and
  1447. (s[i + 2] in gl) then
  1448. CanBreak := True;
  1449. end;
  1450. if CanBreak then
  1451. Result := Result + Chr(i);
  1452. Inc(i);
  1453. until i > Length(s) - 2;
  1454. end;
  1455. end;
  1456. procedure TfrMemoView.WrapMemo;
  1457. var
  1458. size, size1, maxwidth: Integer;
  1459. b: TWordBreaks;
  1460. WCanvas: TCanvas;
  1461. procedure OutLine(const str: String);
  1462. var
  1463. n, w: Word;
  1464. begin
  1465. n := Length(str);
  1466. if (n > 0) and (str[n] = #1) then
  1467. w := WCanvas.TextWidth(Copy(str, 1, n - 1)) else
  1468. w := WCanvas.TextWidth(str);
  1469. SMemo.Add(str + Chr(w div 256) + Chr(w mod 256));
  1470. Inc(size, size1);
  1471. end;
  1472. procedure WrapLine(const s: String);
  1473. var
  1474. i, cur, beg, last: Integer;
  1475. WasBreak, CRLF: Boolean;
  1476. begin
  1477. CRLF := False;
  1478. for i := 1 to Length(s) do
  1479. if s[i] in [#10, #13] then
  1480. begin
  1481. CRLF := True;
  1482. break;
  1483. end;
  1484. last := 1; beg := 1;
  1485. if not CRLF and ((Length(s) <= 1) or (WCanvas.TextWidth(s) <= maxwidth)) then
  1486. OutLine(s + #1)
  1487. else
  1488. begin
  1489. cur := 1;
  1490. while cur <= Length(s) do
  1491. begin
  1492. if s[cur] in [#10, #13] then
  1493. begin
  1494. OutLine(Copy(s, beg, cur - beg) + #1);
  1495. while (cur < Length(s)) and (s[cur] in [#10, #13]) do Inc(cur);
  1496. beg := cur; last := beg;
  1497. if s[cur] in [#13, #10] then
  1498. Exit else
  1499. continue;
  1500. end;
  1501. if s[cur] <> ' ' then
  1502. if WCanvas.TextWidth(Copy(s, beg, cur - beg + 1)) > maxwidth then
  1503. begin
  1504. WasBreak := False;
  1505. if (Flags and flWordBreak) <> 0 then
  1506. begin
  1507. i := cur;
  1508. while (i <= Length(s)) and not (s[i] in spaces) do
  1509. Inc(i);
  1510. b := BreakWord(Copy(s, last + 1, i - last - 1));
  1511. if Length(b) > 0 then
  1512. begin
  1513. i := 1;
  1514. cur := last;
  1515. while (i <= Length(b)) and
  1516. (WCanvas.TextWidth(Copy(s, beg, last - beg + 1 + Ord(b[i])) + '-') <= maxwidth) do
  1517. begin
  1518. WasBreak := True;
  1519. cur := last + Ord(b[i]);
  1520. Inc(i);
  1521. end;
  1522. last := cur;
  1523. end;
  1524. end
  1525. else
  1526. if last = beg then last := cur;
  1527. if WasBreak then
  1528. OutLine(Copy(s, beg, last - beg + 1) + '-')
  1529. else if s[last] = ' ' then
  1530. OutLine(Copy(s, beg, last - beg)) else
  1531. OutLine(Copy(s, beg, last - beg + 1));
  1532. if ((Flags and flWordBreak) <> 0) and not WasBreak and (last = cur) then
  1533. begin
  1534. beg := cur + 1;
  1535. cur := Length(s);
  1536. break;
  1537. end;
  1538. if (Flags and flWordBreak) = 0 then
  1539. if last = cur then
  1540. begin
  1541. beg := cur;
  1542. break;
  1543. end;
  1544. beg := last + 1; last := beg;
  1545. end;
  1546. if s[cur] in spaces then last := cur;
  1547. Inc(cur);
  1548. end;
  1549. if beg <> cur then OutLine(Copy(s, beg, cur - beg + 1) + #1);
  1550. end;
  1551. end;
  1552. procedure OutMemo;
  1553. var
  1554. i: Integer;
  1555. begin
  1556. size := y + gapy;
  1557. size1 := -WCanvas.Font.Height + LineSpacing;
  1558. maxwidth := dx - gapx - gapx;
  1559. for i := 0 to Memo1.Count - 1 do
  1560. if (Flags and flWordWrap) <> 0 then
  1561. WrapLine(Memo1[i]) else
  1562. OutLine(Memo1[i] + #1);
  1563. VHeight := size - y + gapy;
  1564. TextHeight := size1;
  1565. end;
  1566. procedure OutMemo90;
  1567. var
  1568. i: Integer;
  1569. h, oldh: HFont;
  1570. begin
  1571. h := Create90Font(WCanvas.Font);
  1572. oldh := SelectObject(WCanvas.Handle, h);
  1573. size := x + gapx;
  1574. size1 := -WCanvas.Font.Height + LineSpacing;
  1575. maxwidth := dy - gapy - gapy;
  1576. for i := 0 to Memo1.Count - 1 do
  1577. if (Flags and flWordWrap) <> 0 then
  1578. WrapLine(Memo1[i]) else
  1579. OutLine(Memo1[i]);
  1580. SelectObject(WCanvas.Handle, oldh);
  1581. DeleteObject(h);
  1582. VHeight := size - x + gapx;
  1583. TextHeight := size1;
  1584. end;
  1585. begin
  1586. WCanvas := TempBmp.Canvas;
  1587. WCanvas.Font.Assign(Font);
  1588. WCanvas.Font.Height := -Round(Font.Size * 96 / 72);
  1589. SetTextCharacterExtra(WCanvas.Handle, CharacterSpacing);
  1590. SMemo.Clear;
  1591. if (Adjust and $4) <> 0 then OutMemo90 else OutMemo;
  1592. end;
  1593. var
  1594. DxArray: Array[0..2047] of Integer;
  1595. procedure TfrMemoView.ShowMemo;
  1596. var
  1597. DR: TRect;
  1598. ad, ox, oy: Integer;
  1599. GCP: TGCPRESULTS;
  1600. procedure OutMemo;
  1601. var
  1602. i, cury, th: Integer;
  1603. function OutLine(str: String): Boolean;
  1604. var
  1605. i, n, aw, nw, w, curx: Integer;
  1606. ParaEnd: Boolean;
  1607. begin
  1608. if not Streaming or (cury + th <= DR.Bottom) then
  1609. begin
  1610. n := Length(str);
  1611. w := Ord(str[n - 1]) * 256 + Ord(str[n]);
  1612. SetLength(str, n - 2);
  1613. ParaEnd := True;
  1614. if Length(str) > 0 then
  1615. if str[Length(str)] = #1 then
  1616. SetLength(str, Length(str) - 1) else
  1617. ParaEnd := False;
  1618. if Adjust <> 3 then
  1619. begin
  1620. FillChar(GCP, SizeOf(TGCPRESULTS), 0);
  1621. GCP.lStructSize := SizeOf(TGCPRESULTS);
  1622. GCP.lpDx := @DxArray[0];
  1623. GCP.nGlyphs := Length(str);
  1624. AssignFont(Canvas);
  1625. nw := Round(w * ScaleX); // needed width
  1626. while (Canvas.TextWidth(str) > nw) and
  1627. (Canvas.Font.Height < -1) do
  1628. Canvas.Font.Height := Canvas.Font.Height + 1;
  1629. aw := Canvas.TextWidth(str); // actual width
  1630. // preventing Win32 error when printing
  1631. if (aw <> nw) and not Exporting then
  1632. {$IFDEF VER180}
  1633. GetCharacterPlacement(Canvas.Handle, PChar(str), Length(str), nw, GCP, GCP_JUSTIFY + GCP_MAXEXTENT)
  1634. {$ELSE}
  1635. {$IFDEF VER150}
  1636. GetCharacterPlacement(Canvas.Handle, PChar(str), Length(str), nw, GCP, GCP_JUSTIFY + GCP_MAXEXTENT)
  1637. {$ELSE}
  1638. GetCharacterPlacement(Canvas.Handle, PChar(str), BOOL(Length(str)), BOOL(nw), GCP, GCP_JUSTIFY + GCP_MAXEXTENT)
  1639. {$ENDIF}
  1640. {$ENDIF}
  1641. else
  1642. GCP.lpDx := nil;
  1643. if Adjust = 0 then
  1644. curx := x + gapx
  1645. else if Adjust = 1 then
  1646. curx := x + dx - 1 - gapx - nw
  1647. else
  1648. curx := x + gapx + (dx - gapx - gapx - nw) div 2;
  1649. if not Exporting then
  1650. ExtTextOut(Canvas.Handle, curx, cury, ETO_CLIPPED, @DR,
  1651. PChar(str), Length(str), PInteger(GCP.lpDx))
  1652. end
  1653. else
  1654. begin
  1655. curx := x + gapx;
  1656. if not Exporting then
  1657. begin
  1658. n := 0;
  1659. for i := 1 to Length(str) do
  1660. if str[i] = ' ' then Inc(n);
  1661. if (n <> 0) and not ParaEnd then
  1662. SetTextJustification(Canvas.Handle,
  1663. dx - gapx - gapx - Canvas.TextWidth(str), n);
  1664. ExtTextOut(Canvas.Handle, curx, cury, ETO_CLIPPED, @DR,
  1665. PChar(str), Length(str), nil);
  1666. SetTextJustification(Canvas.Handle, 0, 0);
  1667. end;
  1668. end;
  1669. if Exporting then CurReport.InternalOnExportText(curx, cury, str, Self);
  1670. Inc(CurStrNo);
  1671. Result := False;
  1672. end
  1673. else Result := True;
  1674. cury := cury + th;
  1675. end;
  1676. begin
  1677. cury := y + gapy;
  1678. th := -Canvas.Font.Height + Round(LineSpacing * ScaleY);
  1679. CurStrNo := 0;
  1680. for i := 0 to Memo1.Count - 1 do
  1681. if OutLine(Memo1[i]) then
  1682. break;
  1683. end;
  1684. procedure OutMemo90;
  1685. var
  1686. i, th, curx: Integer;
  1687. h, oldh: HFont;
  1688. procedure OutLine(str: String);
  1689. var
  1690. i, n, cury: Integer;
  1691. ParaEnd: Boolean;
  1692. begin
  1693. SetLength(str, Length(str) - 2);
  1694. if str[Length(str)] = #1 then
  1695. begin
  1696. ParaEnd := True;
  1697. SetLength(str, Length(str) - 1);
  1698. end
  1699. else
  1700. ParaEnd := False;
  1701. cury := 0;
  1702. if Adjust = 4 then
  1703. cury := y + dy - gapy
  1704. else if Adjust = 5 then
  1705. cury := y + gapy + Canvas.TextWidth(str)
  1706. else if Adjust = 6 then
  1707. cury := y + dy - 1 - gapy - (dy - gapy - gapy - Canvas.TextWidth(str)) div 2
  1708. else if not Exporting then
  1709. begin
  1710. cury := y + dy - gapy;
  1711. n := 0;
  1712. for i := 1 to Length(str) do
  1713. if str[i] = ' ' then Inc(n);
  1714. if (n <> 0) and not ParaEnd then
  1715. SetTextJustification(Canvas.Handle,
  1716. dy - gapy - gapy - Canvas.TextWidth(str), n);
  1717. end;
  1718. if not Exporting then
  1719. begin
  1720. ExtTextOut(Canvas.Handle, curx, cury, ETO_CLIPPED, @DR,
  1721. PChar(str), Length(str), nil);
  1722. if Adjust <> 7 then
  1723. SetTextJustification(Canvas.Handle, 0, 0);
  1724. end;
  1725. if Exporting then CurReport.InternalOnExportText(curx, cury, str, Self);
  1726. Inc(CurStrNo);
  1727. curx := curx + th;
  1728. end;
  1729. begin
  1730. h := Create90Font(Canvas.Font);
  1731. oldh := SelectObject(Canvas.Handle,h);
  1732. curx := x + gapx;
  1733. th := -Canvas.Font.Height + Round(LineSpacing * ScaleY);
  1734. CurStrNo := 0;
  1735. for i := 0 to Memo1.Count - 1 do
  1736. OutLine(Memo1[i]);
  1737. SelectObject(Canvas.Handle, oldh);
  1738. DeleteObject(h);
  1739. end;
  1740. begin
  1741. AssignFont(Canvas);
  1742. SetTextCharacterExtra(Canvas.Handle, Round(CharacterSpacing * ScaleX));
  1743. DR := Rect(DRect.Left + 1, DRect.Top, DRect.Right - 2, DRect.Bottom - 1);
  1744. VHeight := Round(VHeight * ScaleY);
  1745. if (Adjust and $18) <> 0 then
  1746. begin
  1747. ad := Adjust;
  1748. ox := x; oy := y;
  1749. Adjust := Adjust and $7;
  1750. if (ad and $4) <> 0 then
  1751. begin
  1752. if (ad and $18) = $8 then
  1753. x := x + (dx - VHeight) div 2
  1754. else if (ad and $18) = $10 then
  1755. x := x + dx - VHeight;
  1756. OutMemo90;
  1757. end
  1758. else
  1759. begin
  1760. if (ad and $18) = $8 then
  1761. y := y + (dy - VHeight) div 2
  1762. else if (ad and $18) = $10 then
  1763. y := y + dy - VHeight;
  1764. OutMemo;
  1765. end;
  1766. Adjust := ad;
  1767. x := ox; y := oy;
  1768. end
  1769. else if (Adjust and $4) <> 0 then OutMemo90 else OutMemo;
  1770. end;
  1771. function TfrMemoView.CalcWidth(Memo: TStringList): Integer;
  1772. var
  1773. CalcRect: TRect;
  1774. s: String;
  1775. n: Integer;
  1776. begin
  1777. CalcRect := Rect(0, 0, dx, dy);
  1778. Canvas.Font.Assign(Font);
  1779. Canvas.Font.Height := -Round(Font.Size * 96 / 72);
  1780. s := Memo.Text;
  1781. n := Length(s);
  1782. if n > 2 then
  1783. if (s[n - 1] = #13) and (s[n] = #10) then
  1784. SetLength(s, n - 2);
  1785. SetTextCharacterExtra(Canvas.Handle, Round(CharacterSpacing * ScaleX));
  1786. DrawText(Canvas.Handle, PChar(s), Length(s), CalcRect, DT_CALCRECT);
  1787. Result := CalcRect.Right + Round(2 * FrameWidth) + 2;
  1788. end;
  1789. procedure TfrMemoView.Draw(Canvas: TCanvas);
  1790. var
  1791. NeedWrap: Boolean;
  1792. newdx: Integer;
  1793. OldScaleX, OldScaleY: Double;
  1794. begin
  1795. BeginDraw(Canvas);
  1796. if ((Flags and flAutoSize) <> 0) and (Memo.Count > 0) and
  1797. (DocMode <> dmDesigning) then
  1798. begin
  1799. newdx := CalcWidth(Memo);
  1800. if (Adjust and frtaRight) <> 0 then
  1801. begin
  1802. x := x + dx - newdx;
  1803. dx := newdx;
  1804. end
  1805. else
  1806. dx := newdx;
  1807. end;
  1808. Streaming := False;
  1809. Memo1.Assign(Memo);
  1810. OldScaleX := ScaleX; OldScaleY := ScaleY;
  1811. ScaleX := 1; ScaleY := 1;
  1812. CalcGaps;
  1813. ScaleX := OldScaleX; ScaleY := OldScaleY;
  1814. RestoreCoord;
  1815. if Memo1.Count > 0 then
  1816. begin
  1817. NeedWrap := Pos(#1, Memo1.Text) = 0;
  1818. if Memo1[Memo1.Count - 1] = #1 then
  1819. Memo1.Delete(Memo1.Count - 1);
  1820. if NeedWrap then
  1821. begin
  1822. WrapMemo;
  1823. Memo1.Assign(SMemo);
  1824. end;
  1825. end;
  1826. CalcGaps;
  1827. if not Exporting then ShowBackground;
  1828. if not Exporting then ShowFrame;
  1829. if Memo1.Count > 0 then
  1830. ShowMemo;
  1831. RestoreCoord;
  1832. end;
  1833. procedure TfrMemoView.Print(Stream: TStream);
  1834. var
  1835. s: String;
  1836. CanExpandVar: Boolean;
  1837. OldFont: TFont;
  1838. OldFill: Integer;
  1839. i: Integer;
  1840. begin
  1841. BeginDraw(TempBmp.Canvas);
  1842. Streaming := True;
  1843. if DrawMode = drAll then
  1844. frInterpretator.DoScript(Script);
  1845. CanExpandVar := True;
  1846. if (DrawMode = drAll) and (Assigned(CurReport.OnEnterRect) or
  1847. ((FDataSet <> nil) and frIsBlob(TfrTField(FDataSet.FindField(FField))))) then
  1848. begin
  1849. Memo1.Assign(Memo);
  1850. s := Memo1.Text;
  1851. CurReport.InternalOnEnterRect(Memo1, Self);
  1852. if s <> Memo1.Text then CanExpandVar := False;
  1853. end
  1854. else if DrawMode = drAfterCalcHeight then
  1855. CanExpandVar := False;
  1856. if DrawMode <> drPart then
  1857. if CanExpandVar then ExpandVariables;
  1858. if not Visible then
  1859. begin
  1860. DrawMode := drAll;
  1861. Exit;
  1862. end;
  1863. OldFont := TFont.Create;
  1864. OldFont.Assign(Font);
  1865. OldFill := FillColor;
  1866. if Length(HighlightStr) <> 0 then
  1867. if frParser.Calc(HighlightStr) <> 0 then
  1868. begin
  1869. Font.Style := frSetFontStyle(Highlight.FontStyle);
  1870. Font.Color := Highlight.FontColor;
  1871. FillColor := Highlight.FillColor;
  1872. end;
  1873. if DrawMode = drPart then
  1874. begin
  1875. CalcGaps;
  1876. ShowMemo;
  1877. SMemo.Assign(Memo1);
  1878. while Memo1.Count > CurStrNo do
  1879. Memo1.Delete(CurStrNo);
  1880. if Pos(#1, Memo1.Text) = 0 then
  1881. Memo1.Add(#1);
  1882. end;
  1883. Stream.Write(Typ, 1);
  1884. if Typ = gtAddIn then
  1885. frWriteString(Stream, ClassName);
  1886. SaveToStream(Stream);
  1887. if DrawMode = drPart then
  1888. begin
  1889. Memo1.Assign(SMemo);
  1890. for i := 0 to CurStrNo - 1 do
  1891. Memo1.Delete(0);
  1892. end;
  1893. Font.Assign(OldFont);
  1894. OldFont.Free;
  1895. FillColor := OldFill;
  1896. DrawMode := drAll;
  1897. end;
  1898. procedure TfrMemoView.ExportData;
  1899. begin
  1900. inherited;
  1901. Exporting := True;
  1902. Draw(TempBmp.Canvas);
  1903. Exporting := False;
  1904. end;
  1905. function TfrMemoView.CalcHeight: Integer;
  1906. var
  1907. s: String;
  1908. CanExpandVar: Boolean;
  1909. OldFont: TFont;
  1910. OldFill: Integer;
  1911. begin
  1912. Result := 0;
  1913. DrawMode := drAfterCalcHeight;
  1914. BeginDraw(TempBmp.Canvas);
  1915. frInterpretator.DoScript(Script);
  1916. if not Visible then Exit;
  1917. CanExpandVar := True;
  1918. Memo1.Assign(Memo);
  1919. s := Memo1.Text;
  1920. CurReport.InternalOnEnterRect(Memo1, Self);
  1921. if s <> Memo1.Text then CanExpandVar := False;
  1922. if CanExpandVar then ExpandVariables;
  1923. OldFont := TFont.Create;
  1924. OldFont.Assign(Font);
  1925. OldFill := FillColor;
  1926. if Length(HighlightStr) <> 0 then
  1927. if frParser.Calc(HighlightStr) <> 0 then
  1928. begin
  1929. Font.Style := frSetFontStyle(Highlight.FontStyle);
  1930. Font.Color := Highlight.FontColor;
  1931. FillColor := Highlight.FillColor;
  1932. end;
  1933. if ((Flags and flAutoSize) <> 0) and (Memo1.Count > 0) and
  1934. (DocMode <> dmDesigning) then
  1935. dx := CalcWidth(Memo1);
  1936. CalcGaps;
  1937. if Memo1.Count <> 0 then
  1938. begin
  1939. WrapMemo;
  1940. Result := VHeight;
  1941. end;
  1942. Font.Assign(OldFont);
  1943. OldFont.Free;
  1944. FillColor := OldFill;
  1945. end;
  1946. function TfrMemoView.MinHeight: Integer;
  1947. begin
  1948. Result := TextHeight;
  1949. end;
  1950. function TfrMemoView.RemainHeight: Integer;
  1951. begin
  1952. Result := Memo1.Count * TextHeight;
  1953. end;
  1954. procedure TfrMemoView.LoadFromStream(Stream: TStream);
  1955. var
  1956. w: Word;
  1957. i: Integer;
  1958. begin
  1959. inherited LoadFromStream(Stream);
  1960. Font.Name := ReadString(Stream);
  1961. with Stream do
  1962. begin
  1963. Read(i, 4);
  1964. Font.Size := i;
  1965. Read(w, 2);
  1966. Font.Style := frSetFontStyle(w);
  1967. Read(i, 4);
  1968. Font.Color := i;
  1969. Read(Adjust, 4);
  1970. Read(w, 2);
  1971. if frVersion < 23 then
  1972. w := frCharset;
  1973. {$IFNDEF Delphi2}
  1974. Font.Charset := w;
  1975. {$ENDIF}
  1976. if StreamMode = smDesigning then
  1977. begin
  1978. Read(Highlight, 10);
  1979. HighlightStr := ReadString(Stream);
  1980. end;
  1981. end;
  1982. if frVersion = 21 then
  1983. Flags := Flags or flWordWrap;
  1984. end;
  1985. procedure TfrMemoView.SaveToStream(Stream: TStream);
  1986. var
  1987. i: Integer;
  1988. w: Word;
  1989. begin
  1990. inherited SaveToStream(Stream);
  1991. frWriteString(Stream, Font.Name);
  1992. with Stream do
  1993. begin
  1994. i := Font.Size;
  1995. Write(i, 4);
  1996. w := frGetFontStyle(Font.Style);
  1997. Write(w, 2);
  1998. i := Font.Color;
  1999. Write(i, 4);
  2000. Write(Adjust, 4);
  2001. {$IFDEF Delphi2}
  2002. w := frCharset;
  2003. {$ELSE}
  2004. w := Font.Charset;
  2005. {$ENDIF}
  2006. Write(w, 2);
  2007. if StreamMode = smDesigning then
  2008. begin
  2009. Write(Highlight, 10);
  2010. frWriteString(Stream, HighlightStr);
  2011. end;
  2012. end;
  2013. end;
  2014. procedure TfrMemoView.SaveToFR3Stream(Stream: TStream);
  2015. var
  2016. fs: Integer;
  2017. f1, f2: Integer;
  2018. s: String;
  2019. procedure WriteStr(const s: String);
  2020. begin
  2021. Stream.Write(s[1], Length(s));
  2022. end;
  2023. begin
  2024. inherited;
  2025. if (Flags and flStretched) <> 0 then
  2026. WriteStr(' StretchMode="smMaxHeight"');
  2027. if (Flags and flWordWrap) = 0 then
  2028. WriteStr(' WordWrap="False"');
  2029. if (Flags and flAutoSize) <> 0 then
  2030. WriteStr(' AutoWidth="True"');
  2031. // if (Flags and flTextOnly) <> 0 then
  2032. // WriteStr(' AllowExpressions="False"');
  2033. // if (Flags and flSuppressRepeated) <> 0 then
  2034. // WriteStr(' SuppressRepeated="True"');
  2035. // if (Flags and flHideZeros) <> 0 then
  2036. // WriteStr(' HideZeros="True"');
  2037. // if (Flags and flUnderlines) <> 0 then
  2038. // WriteStr(' Underlines="True"');
  2039. // if (Flags and flRTLReading) <> 0 then
  2040. // WriteStr(' RTLReading="True"');
  2041. fs := 0;
  2042. if fsBold in Font.Style then
  2043. fs := fs or 1;
  2044. if fsItalic in Font.Style then
  2045. fs := fs or 2;
  2046. if fsUnderline in Font.Style then
  2047. fs := fs or 4;
  2048. if fsStrikeout in Font.Style then
  2049. fs := fs or 8;
  2050. WriteStr(' Font.Name="' + Font.Name +
  2051. '" Font.Height="' + IntToStr(Font.Height) +
  2052. '" Font.Color="' + IntToStr(Font.Color) +
  2053. '" Font.Style="' + IntToStr(fs) + '"');
  2054. WriteStr(' LineSpacing="' + IntToStr(LineSpacing) +
  2055. '" CharSpacing="' + IntToStr(CharacterSpacing) + '"');
  2056. if HighlightStr <> '' then
  2057. WriteStr(' Highlight.Condition="' + StrToXML(HighlightStr) +
  2058. '" Highlight.Font.Style="' + IntToStr(Highlight.FontStyle) +
  2059. '" Highlight.Font.Color="' + IntToStr(Highlight.FontColor) +
  2060. '" Highlight.Color="' + IntToStr(Highlight.FillColor) + '"');
  2061. { al := 0;
  2062. if ((Alignment and frtaRight) <> 0) and ((Alignment and frtaCenter) <> 0) then
  2063. al := 3
  2064. else if (Alignment and frtaRight) <> 0 then
  2065. al := 1
  2066. else if (Alignment and frtaCenter) <> 0 then
  2067. al := 2;
  2068. WriteStr(' HAlign="' + IntToStr(al) + '"');
  2069. al := 0;
  2070. if (Alignment and frtaMiddle) <> 0 then
  2071. al := 2
  2072. else if (Alignment and frtaDown) <> 0 then
  2073. al := 1;
  2074. WriteStr(' VAlign="' + IntToStr(al) + '"');
  2075. if (Alignment and frtaVertical) <> 0 then
  2076. WriteStr(' Rotation="90"');}
  2077. f1 := (Format div $01000000) and $0F;
  2078. f2 := (Format div $00010000) and $FF;
  2079. s := '';
  2080. case f1 of
  2081. 0: ;
  2082. 1:
  2083. begin
  2084. s := ' DisplayFormat.Kind="fkNumeric"';
  2085. s := s + ' DisplayFormat.DecimalSeparator="' + Chr(Format and $FF) + '"';
  2086. case f2 of
  2087. 0: s := s + ' DisplayFormat.FormatStr="%g"';
  2088. 1: s := s + ' DisplayFormat.FormatStr="%2.2f"';
  2089. 2: s := s + ' DisplayFormat.FormatStr="%2.2n"';
  2090. 3: s := s + ' DisplayFormat.FormatStr="%2.2m"';
  2091. 4: s := s + ' DisplayFormat.FormatStr="' + StrToXML(FormatStr) + '"';
  2092. end;
  2093. end;
  2094. 2:
  2095. begin
  2096. s := ' DisplayFormat.Kind="fkDateTime"';
  2097. if f2 = 4 then
  2098. s := s + ' DisplayFormat.FormatStr="' + StrToXML(FormatStr) + '"'
  2099. else if f2 = 3 then
  2100. s := s + ' DisplayFormat.FormatStr="dd mmmm yyyy"'
  2101. else
  2102. s := s + ' DisplayFormat.FormatStr="' + frDateFormats[f2] + '"'
  2103. end;
  2104. 3:
  2105. begin
  2106. s := ' DisplayFormat.Kind="fkDateTime"';
  2107. if f2 = 4 then
  2108. s := s + ' DisplayFormat.FormatStr="' + StrToXML(FormatStr) + '"' else
  2109. s := s + ' DisplayFormat.FormatStr="' + frTimeFormats[f2] + '"'
  2110. end;
  2111. 4:
  2112. begin
  2113. s := ' DisplayFormat.Kind="fkBoolean"';
  2114. if f2 = 4 then
  2115. s := s + ' DisplayFormat.FormatStr="' + StrToXML(FormatStr) + '"' else
  2116. s := s + ' DisplayFormat.FormatStr="' + BoolStr[f2] + '"'
  2117. end;
  2118. end;
  2119. if s <> '' then
  2120. WriteStr(s);
  2121. end;
  2122. procedure TfrMemoView.GetBlob(b: TfrTField);
  2123. begin
  2124. {$IFDEF IBO}
  2125. b.AssignTo(Memo1);
  2126. {$ELSE}
  2127. Memo1.Assign(b);
  2128. {$ENDIF}
  2129. end;
  2130. procedure TfrMemoView.DefinePopupMenu(Popup: TPopupMenu);
  2131. var
  2132. m: TMenuItem;
  2133. begin
  2134. m := TMenuItem.Create(Popup);
  2135. m.Caption := LoadStr(SVarFormat);
  2136. m.OnClick := P1Click;
  2137. Popup.Items.Add(m);
  2138. m := TMenuItem.Create(Popup);
  2139. m.Caption := LoadStr(SFont);
  2140. m.OnClick := P4Click;
  2141. Popup.Items.Add(m);
  2142. inherited DefinePopupMenu(Popup);
  2143. m := TMenuItem.Create(Popup);
  2144. m.Caption := LoadStr(SWordWrap);
  2145. m.OnClick := P2Click;
  2146. m.Checked := (Flags and flWordWrap) <> 0;
  2147. Popup.Items.Add(m);
  2148. if LoadStr(SWordBreak) <> '' then
  2149. begin
  2150. m := TMenuItem.Create(Popup);
  2151. m.Caption := LoadStr(SWordBreak);
  2152. m.OnClick := P3Click;
  2153. m.Enabled := (Flags and flWordWrap) <> 0;
  2154. if m.Enabled then
  2155. m.Checked := (Flags and flWordBreak) <> 0;
  2156. Popup.Items.Add(m);
  2157. end;
  2158. m := TMenuItem.Create(Popup);
  2159. m.Caption := LoadStr(SAutoSize);
  2160. m.OnClick := P5Click;
  2161. m.Checked := (Flags and flAutoSize) <> 0;
  2162. Popup.Items.Add(m);
  2163. end;
  2164. procedure TfrMemoView.P1Click(Sender: TObject);
  2165. var
  2166. t: TfrView;
  2167. i: Integer;
  2168. begin
  2169. frDesigner.BeforeChange;
  2170. frFmtForm := TfrFmtForm.Create(nil);
  2171. with frFmtForm do
  2172. begin
  2173. Format := Self.Format;
  2174. Edit1.Text := Self.FormatStr;
  2175. if ShowModal = mrOk then
  2176. for i := 0 to frDesigner.Page.Objects.Count - 1 do
  2177. begin
  2178. t := frDesigner.Page.Objects[i];
  2179. if t.Selected then
  2180. begin
  2181. (t as TfrMemoView).Format := Format;
  2182. (t as TfrMemoView).FormatStr := Edit1.Text;
  2183. end;
  2184. end;
  2185. end;
  2186. frFmtForm.Free;
  2187. end;
  2188. procedure TfrMemoView.P2Click(Sender: TObject);
  2189. var
  2190. i: Integer;
  2191. t: TfrView;
  2192. begin
  2193. frDesigner.BeforeChange;
  2194. with Sender as TMenuItem do
  2195. begin
  2196. Checked := not Checked;
  2197. for i := 0 to frDesigner.Page.Objects.Count - 1 do
  2198. begin
  2199. t := frDesigner.Page.Objects[i];
  2200. if t.Selected then
  2201. t.Flags := (t.Flags and not flWordWrap) + Word(Checked) * flWordWrap;
  2202. end;
  2203. end;
  2204. frDesigner.AfterChange;
  2205. end;
  2206. procedure TfrMemoView.P3Click(Sender: TObject);
  2207. var
  2208. i: Integer;
  2209. t: TfrView;
  2210. begin
  2211. frDesigner.BeforeChange;
  2212. with Sender as TMenuItem do
  2213. begin
  2214. Checked := not Checked;
  2215. for i := 0 to frDesigner.Page.Objects.Count - 1 do
  2216. begin
  2217. t := frDesigner.Page.Objects[i];
  2218. if t.Selected then
  2219. t.Flags := (t.Flags and not flWordBreak) + Word(Checked) * flWordBreak;
  2220. end;
  2221. end;
  2222. frDesigner.AfterChange;
  2223. end;
  2224. procedure TfrMemoView.P4Click(Sender: TObject);
  2225. var
  2226. t: TfrView;
  2227. i: Integer;
  2228. fd: TFontDialog;
  2229. begin
  2230. frDesigner.BeforeChange;
  2231. fd := TFontDialog.Create(nil);
  2232. with fd do
  2233. begin
  2234. Font.Assign(Self.Font);
  2235. if Execute then
  2236. for i := 0 to frDesigner.Page.Objects.Count - 1 do
  2237. begin
  2238. t := frDesigner.Page.Objects[i];
  2239. if t.Selected then
  2240. begin
  2241. if Font.Name <> Self.Font.Name then
  2242. TfrMemoView(t).Font.Name := Font.Name;
  2243. if Font.Size <> Self.Font.Size then
  2244. TfrMemoView(t).Font.Size := Font.Size;
  2245. if Font.Color <> Self.Font.Color then
  2246. TfrMemoView(t).Font.Color := Font.Color;
  2247. if Font.Style <> Self.Font.Style then
  2248. TfrMemoView(t).Font.Style := Font.Style;
  2249. {$IFNDEF Delphi2}
  2250. if Font.Charset <> Self.Font.Charset then
  2251. TfrMemoView(t).Font.Charset := Font.Charset;
  2252. {$ENDIF}
  2253. end;
  2254. end;
  2255. end;
  2256. fd.Free;
  2257. frDesigner.AfterChange;
  2258. end;
  2259. procedure TfrMemoView.P5Click(Sender: TObject);
  2260. var
  2261. i: Integer;
  2262. t: TfrView;
  2263. begin
  2264. frDesigner.BeforeChange;
  2265. with Sender as TMenuItem do
  2266. begin
  2267. Checked := not Checked;
  2268. for i := 0 to frDesigner.Page.Objects.Count - 1 do
  2269. begin
  2270. t := frDesigner.Page.Objects[i];
  2271. if t.Selected then
  2272. t.Flags := (t.Flags and not flAutoSize) + Word(Checked) * flAutoSize;
  2273. end;
  2274. end;
  2275. frDesigner.AfterChange;
  2276. end;
  2277. {----------------------------------------------------------------------------}
  2278. constructor TfrBandView.Create;
  2279. begin
  2280. inherited Create;
  2281. Typ := gtBand;
  2282. Format := 0;
  2283. BaseName := 'Band';
  2284. Flags := flBandOnFirstPage + flBandOnLastPage;
  2285. end;
  2286. procedure TfrBandView.Draw(Canvas: TCanvas);
  2287. var
  2288. h, oldh: HFont;
  2289. begin
  2290. FrameWidth := 1;
  2291. if TfrBandType(FrameTyp) in [btCrossHeader..btCrossFooter] then
  2292. begin
  2293. y := 0; dy := frDesigner.Page.PrnInfo.Pgh;
  2294. end
  2295. else
  2296. begin
  2297. x := 0; dx := frDesigner.Page.PrnInfo.Pgw;
  2298. end;
  2299. BeginDraw(Canvas);
  2300. CalcGaps;
  2301. with Canvas do
  2302. begin
  2303. Brush.Bitmap := SBmp;
  2304. FillRect(DRect);
  2305. Font.Name := 'Arial';
  2306. Font.Style := [];
  2307. Font.Size := 8;
  2308. Font.Color := clBlack;
  2309. Pen.Width := 1;
  2310. Pen.Color := clBtnFace;
  2311. Pen.Style := psSolid;
  2312. Brush.Style := bsClear;
  2313. Rectangle(x, y, x + dx + 1, y + dy + 1);
  2314. Brush.Color := clBtnFace;
  2315. if ShowBandTitles then
  2316. if TfrBandType(FrameTyp) in [btCrossHeader..btCrossFooter] then
  2317. begin
  2318. FillRect(Rect(x - 18, y, x, y + 100));
  2319. Pen.Color := clBtnShadow;
  2320. MoveTo(x - 18, y + 98); LineTo(x, y + 98);
  2321. Pen.Color := clBlack;
  2322. MoveTo(x - 18, y + 99); LineTo(x, y + 99);
  2323. Pen.Color := clBtnHighlight;
  2324. MoveTo(x - 18, y + 99); LineTo(x - 18, y);
  2325. h := Create90Font(Font);
  2326. oldh := SelectObject(Handle, h);
  2327. TextOut(x - 15, y + 94, frBandNames[FrameTyp]);
  2328. SelectObject(Handle, oldh);
  2329. DeleteObject(h);
  2330. end
  2331. else
  2332. begin
  2333. FillRect(Rect(x, y - 18, x + 100, y));
  2334. Pen.Color := clBtnShadow;
  2335. MoveTo(x + 98, y - 18); LineTo(x + 98, y);
  2336. Pen.Color := clBlack;
  2337. MoveTo(x + 99, y - 18); LineTo(x + 99, y);
  2338. TextOut(x + 4, y - 17, frBandNames[FrameTyp]);
  2339. end
  2340. else
  2341. begin
  2342. Brush.Style := bsClear;
  2343. if TfrBandType(FrameTyp) in [btCrossHeader..btCrossFooter] then
  2344. begin
  2345. h := Create90Font(Font);
  2346. oldh := SelectObject(Handle, h);
  2347. TextOut(x + 2, y + 94, frBandNames[FrameTyp]);
  2348. SelectObject(Handle, oldh);
  2349. DeleteObject(h);
  2350. end
  2351. else
  2352. TextOut(x + 4, y + 2, frBandNames[FrameTyp]);
  2353. end;
  2354. end;
  2355. end;
  2356. function TfrBandView.GetClipRgn(rt: TfrRgnType): HRGN;
  2357. var
  2358. R: HRGN;
  2359. begin
  2360. if not ShowBandTitles then
  2361. begin
  2362. Result := inherited GetClipRgn(rt);
  2363. Exit;
  2364. end;
  2365. if rt = rtNormal then
  2366. Result := CreateRectRgn(x, y, x + dx + 1, y + dy + 1) else
  2367. Result := CreateRectRgn(x - 10, y - 10, x + dx + 10, y + dy + 10);
  2368. if TfrBandType(FrameTyp) in [btCrossHeader..btCrossFooter] then
  2369. R := CreateRectRgn(x - 18, y, x, y + 100)
  2370. else
  2371. R := CreateRectRgn(x, y - 18, x + 100, y);
  2372. CombineRgn(Result, Result, R, RGN_OR);
  2373. DeleteObject(R);
  2374. end;
  2375. procedure TfrBandView.SaveToFR3Stream(Stream: TStream);
  2376. const
  2377. BandNames: array[TfrBandType] of String =
  2378. ('TfrxReportTitle', 'TfrxReportSummary',
  2379. 'TfrxPageHeader', 'TfrxPageFooter',
  2380. 'TfrxHeader', 'TfrxMasterData', 'TfrxFooter',
  2381. 'TfrxHeader', 'TfrxDetailData', 'TfrxFooter',
  2382. 'TfrxHeader', 'TfrxSubDetailData', 'TfrxFooter',
  2383. 'TfrxOverlay', 'TfrxColumnHeader', 'TfrxColumnFooter',
  2384. 'TfrxGroupHeader', 'TfrxGroupFooter',
  2385. '', '', '', '');
  2386. var
  2387. ds: TfrDataset;
  2388. procedure WriteStr(const s: String);
  2389. begin
  2390. Stream.Write(s[1], Length(s));
  2391. end;
  2392. begin
  2393. if BandNames[BandType] = '' then Exit;
  2394. WriteStr('<' + BandNames[BandType] + ' ');
  2395. WriteStr('Name="' + Name +
  2396. '" Top="' + IntToStr(y) +
  2397. '" Height="' + IntToStr(dy) +
  2398. // '" Columns="' + IntToStr(Columns) +
  2399. // '" ColumnWidth="' + IntToStr(ColumnWidth) +
  2400. // '" ColumnGap="' + IntToStr(ColumnGap) +
  2401. '"');
  2402. if not Visible then
  2403. WriteStr(' Visible="False"');
  2404. // if ChildBand <> '' then
  2405. // WriteStr(' Child="' + ChildBand + '"');
  2406. if (Flags and flStretched) <> 0 then
  2407. WriteStr(' Stretched="True"');
  2408. if (Flags and flBandNewPageAfter) <> 0 then
  2409. WriteStr(' StartNewPage="True"');
  2410. if (Flags and flBandPrintifSubsetEmpty) <> 0 then
  2411. WriteStr(' PrintIfDetailEmpty="True"');
  2412. if (Flags and flBandPageBreak) <> 0 then
  2413. WriteStr(' AllowSplit="True"');
  2414. if (Flags and flBandOnFirstPage) = 0 then
  2415. WriteStr(' PrintOnFirstPage="False"');
  2416. if (Flags and flBandOnLastPage) = 0 then
  2417. WriteStr(' PrintOnLastPage="False"');
  2418. if (Flags and flBandRepeatHeader) <> 0 then
  2419. WriteStr(' ReprintOnNewPage="True"');
  2420. if (Flags and flBandRepeatHeader) <> 0 then
  2421. WriteStr(' ReprintOnNewPage="True"');
  2422. // if (Flags and flBandPrintChildIfInvisible) <> 0 then
  2423. // WriteStr(' PrintChildIfInvisible="True"');
  2424. if Script.Count > 0 then
  2425. WriteStr(' OnBeforePrint="' + Name + 'OnBeforePrint"');
  2426. if BandType in [btMasterData, btDetailData, btSubDetailData] then
  2427. begin
  2428. ds := frFindComponent(CurReport.Owner, DataSet) as TfrDataSet;
  2429. if ds <> nil then
  2430. WriteStr(' DataSetName="' + StrToXML(ds.Name) + '"');
  2431. end;
  2432. if BandType = btGroupHeader then
  2433. WriteStr(' Condition="' + StrToXML(GroupCondition) + '"');
  2434. end;
  2435. procedure TfrBandView.DefinePopupMenu(Popup: TPopupMenu);
  2436. var
  2437. m: TMenuItem;
  2438. b: TfrBandType;
  2439. begin
  2440. b := TfrBandType(FrameTyp);
  2441. if b in [btReportTitle, btReportSummary, btPageHeader, btCrossHeader,
  2442. btMasterHeader..btSubDetailFooter, btGroupHeader, btGroupFooter] then
  2443. inherited DefinePopupMenu(Popup);
  2444. if b in [btReportTitle, btReportSummary, btMasterData, btDetailData,
  2445. btSubDetailData, btMasterFooter, btDetailFooter,
  2446. btSubDetailFooter, btGroupHeader] then
  2447. begin
  2448. m := TMenuItem.Create(Popup);
  2449. m.Caption := LoadStr(SFormNewPage);
  2450. m.OnClick := P1Click;
  2451. m.Checked := (Flags and flBandNewPageAfter) <> 0;
  2452. Popup.Items.Add(m);
  2453. end;
  2454. if b in [btMasterData, btDetailData] then
  2455. begin
  2456. m := TMenuItem.Create(Popup);
  2457. m.Caption := LoadStr(SPrintIfSubsetEmpty);
  2458. m.OnClick := P2Click;
  2459. m.Checked := (Flags and flBandPrintIfSubsetEmpty) <> 0;
  2460. Popup.Items.Add(m);
  2461. end;
  2462. if b in [btReportTitle, btReportSummary, btMasterHeader..btSubDetailFooter,
  2463. btGroupHeader, btGroupFooter] then
  2464. begin
  2465. m := TMenuItem.Create(Popup);
  2466. m.Caption := LoadStr(SBreaked);
  2467. m.OnClick := P3Click;
  2468. m.Checked := (Flags and flBandPageBreak) <> 0;
  2469. Popup.Items.Add(m);
  2470. end;
  2471. if b in [btPageHeader, btPageFooter] then
  2472. begin
  2473. m := TMenuItem.Create(Popup);
  2474. m.Caption := LoadStr(SOnFirstPage);
  2475. m.OnClick := P4Click;
  2476. m.Checked := (Flags and flBandOnFirstPage) <> 0;
  2477. Popup.Items.Add(m);
  2478. end;
  2479. if b = btPageFooter then
  2480. begin
  2481. m := TMenuItem.Create(Popup);
  2482. m.Caption := LoadStr(SOnLastPage);
  2483. m.OnClick := P5Click;
  2484. m.Checked := (Flags and flBandOnLastPage) <> 0;
  2485. Popup.Items.Add(m);
  2486. end;
  2487. if b in [btMasterHeader, btDetailHeader, btSubDetailHeader,
  2488. btCrossHeader, btGroupHeader] then
  2489. begin
  2490. m := TMenuItem.Create(Popup);
  2491. m.Caption := LoadStr(SRepeatHeader);
  2492. m.OnClick := P6Click;
  2493. m.Checked := (Flags and flBandRepeatHeader) <> 0;
  2494. Popup.Items.Add(m);
  2495. end;
  2496. end;
  2497. procedure TfrBandView.P1Click(Sender: TObject);
  2498. var
  2499. i: Integer;
  2500. t: TfrView;
  2501. begin
  2502. frDesigner.BeforeChange;
  2503. with Sender as TMenuItem do
  2504. begin
  2505. Checked := not Checked;
  2506. for i := 0 to frDesigner.Page.Objects.Count - 1 do
  2507. begin
  2508. t := frDesigner.Page.Objects[i];
  2509. if t.Selected then
  2510. t.Flags := (t.Flags and not flBandNewPageAfter) +
  2511. Word(Checked) * flBandNewPageAfter;
  2512. end;
  2513. end;
  2514. end;
  2515. procedure TfrBandView.P2Click(Sender: TObject);
  2516. var
  2517. i: Integer;
  2518. t: TfrView;
  2519. begin
  2520. frDesigner.BeforeChange;
  2521. with Sender as TMenuItem do
  2522. begin
  2523. Checked := not Checked;
  2524. for i := 0 to frDesigner.Page.Objects.Count - 1 do
  2525. begin
  2526. t := frDesigner.Page.Objects[i];
  2527. if t.Selected then
  2528. t.Flags := (t.Flags and not flBandPrintifSubsetEmpty) +
  2529. Word(Checked) * flBandPrintifSubsetEmpty;
  2530. end;
  2531. end;
  2532. end;
  2533. procedure TfrBandView.P3Click(Sender: TObject);
  2534. var
  2535. i: Integer;
  2536. t: TfrView;
  2537. begin
  2538. frDesigner.BeforeChange;
  2539. with Sender as TMenuItem do
  2540. begin
  2541. Checked := not Checked;
  2542. for i := 0 to frDesigner.Page.Objects.Count - 1 do
  2543. begin
  2544. t := frDesigner.Page.Objects[i];
  2545. if t.Selected then
  2546. t.Flags := (t.Flags and not flBandPageBreak) + Word(Checked) * flBandPageBreak;
  2547. end;
  2548. end;
  2549. end;
  2550. procedure TfrBandView.P4Click(Sender: TObject);
  2551. begin
  2552. frDesigner.BeforeChange;
  2553. with Sender as TMenuItem do
  2554. begin
  2555. Checked := not Checked;
  2556. Flags := (Flags and not flBandOnFirstPage) + Word(Checked) * flBandOnFirstPage;
  2557. end;
  2558. end;
  2559. procedure TfrBandView.P5Click(Sender: TObject);
  2560. begin
  2561. frDesigner.BeforeChange;
  2562. with Sender as TMenuItem do
  2563. begin
  2564. Checked := not Checked;
  2565. Flags := (Flags and not flBandOnLastPage) + Word(Checked) * flBandOnLastPage;
  2566. end;
  2567. end;
  2568. procedure TfrBandView.P6Click(Sender: TObject);
  2569. begin
  2570. frDesigner.BeforeChange;
  2571. with Sender as TMenuItem do
  2572. begin
  2573. Checked := not Checked;
  2574. Flags := (Flags and not flBandRepeatHeader) + Word(Checked) * flBandRepeatHeader;
  2575. end;
  2576. end;
  2577. function TfrBandView.GetBandType: TfrBandType;
  2578. begin
  2579. Result := TfrBandType(FrameTyp);
  2580. end;
  2581. procedure TfrBandView.SetBandType(const Value: TfrBandType);
  2582. begin
  2583. FrameTyp := Integer(Value);
  2584. end;
  2585. {----------------------------------------------------------------------------}
  2586. constructor TfrSubReportView.Create;
  2587. begin
  2588. inherited Create;
  2589. Typ := gtSubReport;
  2590. BaseName := 'SubReport';
  2591. end;
  2592. procedure TfrSubReportView.Assign(From: TfrView);
  2593. begin
  2594. inherited Assign(From);
  2595. SubPage := (From as TfrSubReportView).SubPage;
  2596. end;
  2597. procedure TfrSubReportView.Draw(Canvas: TCanvas);
  2598. begin
  2599. BeginDraw(Canvas);
  2600. FrameWidth := 1;
  2601. CalcGaps;
  2602. with Canvas do
  2603. begin
  2604. Font.Name := 'Arial';
  2605. Font.Style := [];
  2606. Font.Size := 8;
  2607. Font.Color := clBlack;
  2608. {$IFNDEF Delphi2}
  2609. Font.Charset := frCharset;
  2610. {$ENDIF}
  2611. Pen.Width := 1;
  2612. Pen.Color := clBlack;
  2613. Pen.Style := psSolid;
  2614. Brush.Color := clWhite;
  2615. Rectangle(x, y, x + dx + 1, y + dy + 1);
  2616. Brush.Style := bsClear;
  2617. TextRect(DRect, x + 2, y + 2, LoadStr(SSubReportOnPage) + ' ' +
  2618. IntToStr(SubPage + 1));
  2619. end;
  2620. RestoreCoord;
  2621. end;
  2622. procedure TfrSubReportView.SaveToFR3Stream(Stream: TStream);
  2623. procedure WriteStr(const s: String);
  2624. begin
  2625. Stream.Write(s[1], Length(s));
  2626. end;
  2627. begin
  2628. inherited;
  2629. WriteStr(' Page="Page' + IntToStr(SubPage + 1) + '"');
  2630. end;
  2631. procedure TfrSubReportView.DefinePopupMenu(Popup: TPopupMenu);
  2632. begin
  2633. // no specific items in popup menu
  2634. end;
  2635. procedure TfrSubReportView.LoadFromStream(Stream: TStream);
  2636. begin
  2637. inherited LoadFromStream(Stream);
  2638. Stream.Read(SubPage, 4);
  2639. end;
  2640. procedure TfrSubReportView.SaveToStream(Stream: TStream);
  2641. begin
  2642. inherited SaveToStream(Stream);
  2643. Stream.Write(SubPage, 4);
  2644. end;
  2645. {----------------------------------------------------------------------------}
  2646. constructor TfrPictureView.Create;
  2647. begin
  2648. inherited Create;
  2649. Typ := gtPicture;
  2650. Picture := TPicture.Create;
  2651. Flags := flStretched + flPictRatio;
  2652. BaseName := 'Picture';
  2653. end;
  2654. destructor TfrPictureView.Destroy;
  2655. begin
  2656. Picture.Free;
  2657. inherited Destroy;
  2658. end;
  2659. procedure TfrPictureView.Assign(From: TfrView);
  2660. begin
  2661. inherited Assign(From);
  2662. Picture.Assign(TfrPictureView(From).Picture);
  2663. end;
  2664. procedure TfrPictureView.Draw(Canvas: TCanvas);
  2665. var
  2666. r: TRect;
  2667. kx, ky: Double;
  2668. w, h, w1, h1: Integer;
  2669. procedure PrintBitmap(DestRect: TRect; Bitmap: TBitmap);
  2670. var
  2671. BitmapHeader: pBitmapInfo;
  2672. BitmapImage: Pointer;
  2673. HeaderSize: DWord;
  2674. ImageSize: DWord;
  2675. begin
  2676. GetDIBSizes(Bitmap.Handle, HeaderSize, ImageSize);
  2677. GetMem(BitmapHeader, HeaderSize);
  2678. GetMem(BitmapImage, ImageSize);
  2679. try
  2680. GetDIB(Bitmap.Handle, Bitmap.Palette, BitmapHeader^, BitmapImage^);
  2681. StretchDIBits(
  2682. Canvas.Handle,
  2683. DestRect.Left, DestRect.Top, // Destination Origin
  2684. DestRect.Right - DestRect.Left, // Destination Width
  2685. DestRect.Bottom - DestRect.Top, // Destination Height
  2686. 0, 0, // Source Origin
  2687. Bitmap.Width, Bitmap.Height, // Source Width & Height
  2688. BitmapImage,
  2689. TBitmapInfo(BitmapHeader^),
  2690. DIB_RGB_COLORS,
  2691. SRCCOPY)
  2692. finally
  2693. FreeMem(BitmapHeader);
  2694. FreeMem(BitmapImage)
  2695. end;
  2696. end;
  2697. begin
  2698. BeginDraw(Canvas);
  2699. CalcGaps;
  2700. with Canvas do
  2701. begin
  2702. ShowBackground;
  2703. if ((Picture.Graphic = nil) or Picture.Graphic.Empty) and (DocMode = dmDesigning) then
  2704. begin
  2705. Font.Name := 'Arial';
  2706. Font.Size := 8;
  2707. Font.Style := [];
  2708. Font.Color := clBlack;
  2709. {$IFNDEF Delphi2}
  2710. Font.Charset := frCharset;
  2711. {$ENDIF}
  2712. TextOut(x + 2, y + 2, LoadStr(SPicture));
  2713. end
  2714. else if not ((Picture.Graphic = nil) or Picture.Graphic.Empty) then
  2715. begin
  2716. if (Flags and flStretched) <> 0 then
  2717. begin
  2718. r := DRect;
  2719. if (Flags and flPictRatio) <> 0 then
  2720. begin
  2721. kx := dx / Picture.Width;
  2722. ky := dy / Picture.Height;
  2723. if kx < ky then
  2724. r := Rect(DRect.Left, DRect.Top,
  2725. DRect.Right, DRect.Top + Round(Picture.Height * kx))
  2726. else
  2727. r := Rect(DRect.Left, DRect.Top,
  2728. DRect.Left + Round(Picture.Width * ky), DRect.Bottom);
  2729. w := DRect.Right - DRect.Left;
  2730. h := DRect.Bottom - DRect.Top;
  2731. w1 := r.Right - r.Left;
  2732. h1 := r.Bottom - r.Top;
  2733. if (Flags and flPictCenter) <> 0 then
  2734. OffsetRect(r, (w - w1) div 2, (h - h1) div 2);
  2735. end;
  2736. if IsPrinting and (Picture.Graphic is TBitmap) then
  2737. PrintBitmap(r, Picture.Bitmap) else
  2738. StretchDraw(r, Picture.Graphic);
  2739. end
  2740. else
  2741. begin
  2742. r := DRect;
  2743. if (Flags and flPictCenter) <> 0 then
  2744. begin
  2745. w := DRect.Right - DRect.Left;
  2746. h := DRect.Bottom - DRect.Top;
  2747. OffsetRect(r, (w - Picture.Width) div 2, (h - Picture.Height) div 2);
  2748. end;
  2749. Draw(r.Left, r.Top, Picture.Graphic)
  2750. end;
  2751. end;
  2752. ShowFrame;
  2753. end;
  2754. RestoreCoord;
  2755. end;
  2756. const
  2757. pkNone = 0;
  2758. pkBitmap = 1;
  2759. pkMetafile = 2;
  2760. pkIcon = 3;
  2761. pkJPEG = 4;
  2762. procedure TfrPictureView.LoadFromStream(Stream: TStream);
  2763. var
  2764. b: Byte;
  2765. n: Integer;
  2766. Graphic: TGraphic;
  2767. begin
  2768. inherited LoadFromStream(Stream);
  2769. Stream.Read(b, 1);
  2770. Stream.Read(n, 4);
  2771. Graphic := nil;
  2772. case b of
  2773. pkBitmap: Graphic := TBitmap.Create;
  2774. pkMetafile: Graphic := TMetafile.Create;
  2775. pkIcon: Graphic := TIcon.Create;
  2776. {$IFDEF JPEG}
  2777. pkJPEG: Graphic := TJPEGImage.Create;
  2778. {$ENDIF}
  2779. end;
  2780. Picture.Graphic := Graphic;
  2781. if Graphic <> nil then
  2782. begin
  2783. Graphic.Free;
  2784. Picture.Graphic.LoadFromStream(Stream);
  2785. end;
  2786. Stream.Seek(n, soFromBeginning);
  2787. end;
  2788. procedure TfrPictureView.SaveToStream(Stream: TStream);
  2789. var
  2790. b: Byte;
  2791. n, o: Integer;
  2792. begin
  2793. inherited SaveToStream(Stream);
  2794. b := pkNone;
  2795. if Picture.Graphic <> nil then
  2796. if Picture.Graphic is TBitmap then
  2797. b := pkBitmap
  2798. else if Picture.Graphic is TMetafile then
  2799. b := pkMetafile
  2800. else if Picture.Graphic is TIcon then
  2801. b := pkIcon
  2802. {$IFDEF JPEG}
  2803. else if Picture.Graphic is TJPEGImage then
  2804. b := pkJPEG
  2805. {$ENDIF};
  2806. Stream.Write(b, 1);
  2807. n := Stream.Position;
  2808. Stream.Write(n, 4);
  2809. if b <> pkNone then
  2810. Picture.Graphic.SaveToStream(Stream);
  2811. o := Stream.Position;
  2812. Stream.Seek(n, soFromBeginning);
  2813. Stream.Write(o, 4);
  2814. Stream.Seek(0, soFromEnd);
  2815. end;
  2816. procedure TfrPictureView.GetBlob(b: TfrTField);
  2817. begin
  2818. if b.IsNull then
  2819. Picture.Assign(nil)
  2820. else
  2821. {$IFDEF IBO}
  2822. b.AssignTo(Picture);
  2823. {$ELSE}
  2824. Picture.Assign(b);
  2825. {$ENDIF}
  2826. end;
  2827. procedure TfrPictureView.SaveToFR3Stream(Stream: TStream);
  2828. var
  2829. ms: TMemoryStream;
  2830. ds: TfrTDataSet;
  2831. fld: TfrTField;
  2832. procedure WriteStr(const s: String);
  2833. begin
  2834. Stream.Write(s[1], Length(s));
  2835. end;
  2836. begin
  2837. inherited;
  2838. if Picture.Graphic <> nil then
  2839. begin
  2840. ms := TMemoryStream.Create;
  2841. Picture.Graphic.SaveToStream(ms);
  2842. WriteStr(' Picture.Propdata="' + frStreamToString(ms) + '"');
  2843. ms.Free;
  2844. end;
  2845. if Memo.Count <> 0 then
  2846. begin
  2847. frGetDataSetAndField(Memo[0], ds, fld);
  2848. if (ds <> nil) and (fld <> nil) then
  2849. WriteStr(' DataSet="' + ds.Owner.Name + '.' + ds.Name +
  2850. '" DataField="' + StrToXML(fld.FieldName) + '"');
  2851. end;
  2852. if (Flags and flStretched) = 0 then
  2853. WriteStr(' Stretched="False"');
  2854. if (Flags and flPictCenter) <> 0 then
  2855. WriteStr(' Center="True"');
  2856. if (Flags and flPictRatio) = 0 then
  2857. WriteStr(' KeepAspectRatio="False"');
  2858. end;
  2859. procedure TfrPictureView.DefinePopupMenu(Popup: TPopupMenu);
  2860. var
  2861. m: TMenuItem;
  2862. begin
  2863. inherited DefinePopupMenu(Popup);
  2864. m := TMenuItem.Create(Popup);
  2865. m.Caption := LoadStr(SPictureCenter);
  2866. m.OnClick := P1Click;
  2867. m.Checked := (Flags and flPictCenter) <> 0;
  2868. Popup.Items.Add(m);
  2869. m := TMenuItem.Create(Popup);
  2870. m.Caption := LoadStr(SKeepAspectRatio);
  2871. m.OnClick := P2Click;
  2872. m.Enabled := (Flags and flStretched) <> 0;
  2873. if m.Enabled then
  2874. m.Checked := (Flags and flPictRatio) <> 0;
  2875. Popup.Items.Add(m);
  2876. end;
  2877. procedure TfrPictureView.P1Click(Sender: TObject);
  2878. var
  2879. i: Integer;
  2880. t: TfrView;
  2881. begin
  2882. frDesigner.BeforeChange;
  2883. with Sender as TMenuItem do
  2884. begin
  2885. Checked := not Checked;
  2886. for i := 0 to frDesigner.Page.Objects.Count - 1 do
  2887. begin
  2888. t := frDesigner.Page.Objects[i];
  2889. if t.Selected then
  2890. t.Flags := (t.Flags and not flPictCenter) + Word(Checked) * flPictCenter;
  2891. end;
  2892. end;
  2893. frDesigner.AfterChange;
  2894. end;
  2895. procedure TfrPictureView.P2Click(Sender: TObject);
  2896. var
  2897. i: Integer;
  2898. t: TfrView;
  2899. begin
  2900. frDesigner.BeforeChange;
  2901. with Sender as TMenuItem do
  2902. begin
  2903. Checked := not Checked;
  2904. for i := 0 to frDesigner.Page.Objects.Count - 1 do
  2905. begin
  2906. t := frDesigner.Page.Objects[i];
  2907. if t.Selected then
  2908. t.Flags := (t.Flags and not flPictRatio) + Word(Checked) * flPictRatio;
  2909. end;
  2910. end;
  2911. frDesigner.AfterChange;
  2912. end;
  2913. {----------------------------------------------------------------------------}
  2914. constructor TfrLineView.Create;
  2915. begin
  2916. inherited Create;
  2917. Typ := gtLine;
  2918. FrameTyp := 4;
  2919. BaseName := 'Line';
  2920. end;
  2921. procedure TfrLineView.Draw(Canvas: TCanvas);
  2922. begin
  2923. BeginDraw(Canvas);
  2924. if dx > dy then
  2925. begin
  2926. dy := 0;
  2927. FrameTyp := 8;
  2928. end
  2929. else
  2930. begin
  2931. dx := 0;
  2932. FrameTyp := 4;
  2933. end;
  2934. CalcGaps;
  2935. ShowFrame;
  2936. RestoreCoord;
  2937. end;
  2938. procedure TfrLineView.DefinePopupMenu(Popup: TPopupMenu);
  2939. begin
  2940. // no specific items in popup menu
  2941. end;
  2942. function TfrLineView.GetClipRgn(rt: TfrRgnType): HRGN;
  2943. var
  2944. bx, by, bx1, by1, dd: Integer;
  2945. begin
  2946. bx := x; by := y; bx1 := x + dx + 1; by1 := y + dy + 1;
  2947. if FrameStyle <> 5 then
  2948. dd := Round(FrameWidth / 2) else
  2949. dd := Round(FrameWidth * 1.5);
  2950. if FrameTyp = 4 then
  2951. begin
  2952. Dec(bx, dd);
  2953. Inc(bx1, dd);
  2954. end
  2955. else
  2956. begin
  2957. Dec(by, dd);
  2958. Inc(by1, dd);
  2959. end;
  2960. if rt = rtNormal then
  2961. Result := CreateRectRgn(bx, by, bx1, by1) else
  2962. Result := CreateRectRgn(bx - 10, by - 10, bx1 + 10, by1 + 10);
  2963. end;
  2964. procedure TfrLineView.SaveToFR3Stream(Stream: TStream);
  2965. procedure WriteStr(const s: String);
  2966. begin
  2967. Stream.Write(s[1], Length(s));
  2968. end;
  2969. begin
  2970. inherited;
  2971. if (Flags and flStretched) = 0 then
  2972. WriteStr(' Stretched="False"');
  2973. end;
  2974. {----------------------------------------------------------------------------}
  2975. constructor TfrBand.Create(ATyp: TfrBandType; AParent: TfrPage);
  2976. begin
  2977. inherited Create;
  2978. Typ := ATyp;
  2979. Parent := AParent;
  2980. Objects := TList.Create;
  2981. Memo := TStringList.Create;
  2982. Script := TStringList.Create;
  2983. Values := TStringList.Create;
  2984. Next := nil;
  2985. Positions[psLocal] := 1;
  2986. Positions[psGlobal] := 1;
  2987. Visible := True;
  2988. end;
  2989. destructor TfrBand.Destroy;
  2990. begin
  2991. if Next <> nil then
  2992. Next.Free;
  2993. Objects.Free;
  2994. Memo.Free;
  2995. Script.Free;
  2996. Values.Free;
  2997. if DataSet <> nil then
  2998. DataSet.Exit;
  2999. if IsVirtualDS then
  3000. DataSet.Free;
  3001. if VCDataSet <> nil then
  3002. VCDataSet.Exit;
  3003. if IsVirtualVCDS then
  3004. VCDataSet.Free;
  3005. inherited Destroy;
  3006. end;
  3007. procedure TfrBand.InitDataSet(Desc: String);
  3008. begin
  3009. if Typ = btGroupHeader then
  3010. GroupCondition := Desc
  3011. else
  3012. if Pos(';', Desc) = 0 then
  3013. CreateDS(Desc, DataSet, IsVirtualDS);
  3014. if (Typ = btMasterData) and (Dataset = nil) and
  3015. (CurReport.ReportType = rtSimple) then
  3016. DataSet := CurReport.Dataset;
  3017. end;
  3018. procedure TfrBand.DoError;
  3019. var
  3020. i: Integer;
  3021. begin
  3022. ErrorFlag := True;
  3023. ErrorStr := LoadStr(SErrorOccured);
  3024. for i := 0 to CurView.Memo.Count - 1 do
  3025. ErrorStr := ErrorStr + #13 + CurView.Memo[i];
  3026. ErrorStr := ErrorStr + #13 + LoadStr(SDoc) + ' ' + CurReport.Name +
  3027. #13 + LoadStr(SBand) + ' ' + frBandNames[Integer(CurView.Parent.Typ)];
  3028. MasterReport.Terminated := True;
  3029. end;
  3030. function TfrBand.CalcHeight: Integer;
  3031. var
  3032. Bnd: TfrBand;
  3033. DS: TfrDataSet;
  3034. ddx: Integer;
  3035. function DoCalcHeight(CheckAll: Boolean): Integer;
  3036. var
  3037. i, h: Integer;
  3038. t: TfrView;
  3039. begin
  3040. CurBand := Self;
  3041. AggrBand := Self;
  3042. Result := dy;
  3043. for i := 0 to Objects.Count - 1 do
  3044. begin
  3045. t := Objects[i];
  3046. t.olddy := t.dy;
  3047. if t is TfrStretcheable then
  3048. if (t.Parent = Self) or CheckAll then
  3049. begin
  3050. h := TfrStretcheable(t).CalcHeight + t.y;
  3051. if h > Result then
  3052. Result := h;
  3053. if CheckAll then
  3054. TfrStretcheable(t).DrawMode := drAll;
  3055. end
  3056. end;
  3057. end;
  3058. begin
  3059. Result := dy;
  3060. if HasCross and (Typ <> btPageFooter) then
  3061. begin
  3062. Parent.ColPos := 1;
  3063. CurReport.InternalOnBeginColumn(Self);
  3064. if Parent.BandExists(Parent.Bands[btCrossData]) then
  3065. begin
  3066. Bnd := Parent.Bands[btCrossData];
  3067. if Bnd.DataSet <> nil then
  3068. DS := Bnd.DataSet else
  3069. DS := VCDataSet;
  3070. DS.First;
  3071. while not DS.Eof do
  3072. begin
  3073. ddx := 0;
  3074. CurReport.InternalOnPrintColumn(Parent.ColPos, ddx);
  3075. CalculatedHeight := DoCalcHeight(True);
  3076. if CalculatedHeight > Result then
  3077. Result := CalculatedHeight;
  3078. Inc(Parent.ColPos);
  3079. DS.Next;
  3080. if MasterReport.Terminated then break;
  3081. end;
  3082. end;
  3083. end
  3084. else
  3085. Result := DoCalcHeight(False);
  3086. CalculatedHeight := Result;
  3087. end;
  3088. procedure TfrBand.StretchObjects(MaxHeight: Integer);
  3089. var
  3090. i: Integer;
  3091. t: TfrView;
  3092. begin
  3093. for i := 0 to Objects.Count - 1 do
  3094. begin
  3095. t := Objects[i];
  3096. if (t is TfrStretcheable) or (t is TfrLineView) then
  3097. if (t.Flags and flStretched) <> 0 then
  3098. t.dy := MaxHeight - t.y;
  3099. end;
  3100. end;
  3101. procedure TfrBand.UnStretchObjects;
  3102. var
  3103. i: Integer;
  3104. t: TfrView;
  3105. begin
  3106. for i := 0 to Objects.Count - 1 do
  3107. begin
  3108. t := Objects[i];
  3109. t.dy := t.olddy;
  3110. end;
  3111. end;
  3112. procedure TfrBand.DrawObject(t: TfrView);
  3113. var
  3114. ox,oy: Integer;
  3115. begin
  3116. CurPage := Parent;
  3117. CurBand := Self;
  3118. AggrBand := Self;
  3119. try
  3120. if (t.Parent = Self) and not DisableDrawing then
  3121. begin
  3122. ox := t.x; Inc(t.x, Parent.XAdjust - Parent.LeftMargin);
  3123. oy := t.y; Inc(t.y, y);
  3124. t.Print(MasterReport.EMFPages[PageNo].Stream);
  3125. t.x := ox; t.y := oy;
  3126. if (t is TfrMemoView) and
  3127. (TfrMemoView(t).DrawMode in [drAll, drAfterCalcHeight]) then
  3128. Parent.AfterPrint;
  3129. end;
  3130. except
  3131. on exception do DoError;
  3132. end;
  3133. end;
  3134. procedure TfrBand.PrepareSubReports;
  3135. var
  3136. i: Integer;
  3137. t: TfrView;
  3138. Page: TfrPage;
  3139. begin
  3140. for i := SubIndex to Objects.Count - 1 do
  3141. begin
  3142. t := Objects[i];
  3143. Page := CurReport.Pages[(t as TfrSubReportView).SubPage];
  3144. Page.Mode := pmBuildList;
  3145. Page.FormPage;
  3146. Page.CurY := y + t.y;
  3147. Page.CurBottomY := Parent.CurBottomY;
  3148. Page.XAdjust := Parent.XAdjust + t.x;
  3149. Page.ColCount := 1;
  3150. Page.PlayFrom := 0;
  3151. EOFArr[i - SubIndex] := False;
  3152. end;
  3153. Parent.LastBand := nil;
  3154. end;
  3155. procedure TfrBand.DoSubReports;
  3156. var
  3157. i: Integer;
  3158. t: TfrView;
  3159. Page: TfrPage;
  3160. begin
  3161. repeat
  3162. if not EOFReached then
  3163. for i := SubIndex to Objects.Count - 1 do
  3164. begin
  3165. t := Objects[i];
  3166. Page := CurReport.Pages[(t as TfrSubReportView).SubPage];
  3167. Page.CurY := Parent.CurY;
  3168. Page.CurBottomY := Parent.CurBottomY;
  3169. end;
  3170. EOFReached := True;
  3171. MaxY := Parent.CurY;
  3172. for i := SubIndex to Objects.Count - 1 do
  3173. if not EOFArr[i - SubIndex] then
  3174. begin
  3175. t := Objects[i];
  3176. Page := CurReport.Pages[(t as TfrSubReportView).SubPage];
  3177. if Page.PlayRecList then
  3178. EOFReached := False
  3179. else
  3180. begin
  3181. EOFArr[i - SubIndex] := True;
  3182. if Page.CurY > MaxY then MaxY := Page.CurY;
  3183. end;
  3184. end;
  3185. if not EOFReached then
  3186. begin
  3187. if Parent.Skip then
  3188. begin
  3189. Parent.LastBand := Self;
  3190. Exit;
  3191. end
  3192. else
  3193. Parent.NewPage;
  3194. end;
  3195. until EOFReached or MasterReport.Terminated;
  3196. for i := SubIndex to Objects.Count - 1 do
  3197. begin
  3198. t := Objects[i];
  3199. Page := CurReport.Pages[(t as TfrSubReportView).SubPage];
  3200. Page.ClearRecList;
  3201. end;
  3202. Parent.CurY := MaxY;
  3203. Parent.LastBand := nil;
  3204. end;
  3205. function TfrBand.DrawObjects: Boolean;
  3206. var
  3207. i: Integer;
  3208. t: TfrView;
  3209. begin
  3210. Result := False;
  3211. for i := 0 to Objects.Count - 1 do
  3212. begin
  3213. t := Objects[i];
  3214. if t.Typ = gtSubReport then
  3215. begin
  3216. SubIndex := i;
  3217. Result := True;
  3218. PrepareSubReports;
  3219. DoSubReports;
  3220. break;
  3221. end;
  3222. DrawObject(t);
  3223. if MasterReport.Terminated then break;
  3224. end;
  3225. end;
  3226. procedure TfrBand.DrawCrossCell(Parnt: TfrBand; CurX: Integer);
  3227. var
  3228. i, sfx, sfy: Integer;
  3229. t: TfrView;
  3230. begin
  3231. if DisableDrawing then Exit;
  3232. try
  3233. for i := 0 to Objects.Count - 1 do
  3234. begin
  3235. t := Objects[i];
  3236. if Parnt.Objects.IndexOf(t) <> -1 then
  3237. begin
  3238. sfx := t.x; Inc(t.x, CurX);
  3239. sfy := t.y; Inc(t.y, Parnt.y);
  3240. t.Parent := Parnt;
  3241. t.Print(MasterReport.EMFPages[PageNo].Stream);
  3242. if (t is TfrMemoView) and
  3243. (TfrMemoView(t).DrawMode in [drAll, drAfterCalcHeight]) then
  3244. Parent.AfterPrint;
  3245. t.Parent := Self;
  3246. t.x := sfx;
  3247. t.y := sfy;
  3248. end;
  3249. end;
  3250. except
  3251. on exception do DoError;
  3252. end;
  3253. end;
  3254. procedure TfrBand.DrawCross;
  3255. var
  3256. Bnd: TfrBand;
  3257. sfpage: Integer;
  3258. CurX, ddx: Integer;
  3259. DS: TfrDataSet;
  3260. procedure CheckColumnPageBreak(ddx: Integer);
  3261. var
  3262. sfy: Integer;
  3263. b: TfrBand;
  3264. begin
  3265. if CurX + ddx > Parent.RightMargin then
  3266. begin
  3267. Inc(ColumnXAdjust, CurX - Parent.LeftMargin);
  3268. CurX := Parent.LeftMargin;
  3269. Inc(PageNo);
  3270. if PageNo >= MasterReport.EMFPages.Count then
  3271. begin
  3272. MasterReport.EMFPages.Add(Parent);
  3273. sfy := Parent.CurY;
  3274. Parent.ShowBand(Parent.Bands[btOverlay]);
  3275. Parent.CurY := Parent.TopMargin;
  3276. if (sfPage <> 0) or
  3277. ((Parent.Bands[btPageHeader].Flags and flBandOnFirstPage) <> 0) then
  3278. Parent.ShowBand(Parent.Bands[btPageHeader]);
  3279. Parent.CurY := sfy;
  3280. CurReport.InternalOnProgress(PageNo);
  3281. end;
  3282. if Parent.BandExists(Parent.Bands[btCrossHeader]) then
  3283. if (Parent.Bands[btCrossHeader].Flags and flBandRepeatHeader) <> 0 then
  3284. begin
  3285. b := Parent.Bands[btCrossHeader];
  3286. b.DrawCrossCell(Self, Parent.LeftMargin);
  3287. CurX := Parent.LeftMargin + b.dx;
  3288. end;
  3289. end;
  3290. end;
  3291. begin
  3292. ColumnXAdjust := 0;
  3293. Parent.ColPos := 1;
  3294. CurX := 0;
  3295. sfpage := PageNo;
  3296. if Typ = btPageFooter then Exit;
  3297. IsColumns := True;
  3298. CurReport.InternalOnBeginColumn(Self);
  3299. if Parent.BandExists(Parent.Bands[btCrossHeader]) then
  3300. begin
  3301. Bnd := Parent.Bands[btCrossHeader];
  3302. Bnd.DrawCrossCell(Self, Bnd.x);
  3303. CurX := Bnd.x + Bnd.dx;
  3304. end;
  3305. if Parent.BandExists(Parent.Bands[btCrossData]) then
  3306. begin
  3307. Bnd := Parent.Bands[btCrossData];
  3308. if CurX = 0 then CurX := Bnd.x;
  3309. if Bnd.DataSet <> nil then
  3310. DS := Bnd.DataSet else
  3311. DS := VCDataSet;
  3312. if DS <> nil then
  3313. begin
  3314. DS.First;
  3315. while not DS.Eof do
  3316. begin
  3317. ddx := Bnd.dx;
  3318. CurReport.InternalOnPrintColumn(Parent.ColPos, ddx);
  3319. CheckColumnPageBreak(ddx);
  3320. Bnd.DrawCrossCell(Self, CurX);
  3321. if Typ in [btMasterData, btDetailData, btSubdetailData] then
  3322. Parent.DoAggregate([btPageFooter, btMasterFooter, btDetailFooter,
  3323. btSubDetailFooter, btGroupFooter, btCrossFooter, btReportSummary]);
  3324. Inc(CurX, ddx);
  3325. Inc(Parent.ColPos);
  3326. DS.Next;
  3327. if MasterReport.Terminated then break;
  3328. end;
  3329. end;
  3330. end;
  3331. if Parent.BandExists(Parent.Bands[btCrossFooter]) then
  3332. begin
  3333. Bnd := Parent.Bands[btCrossFooter];
  3334. if CurX = 0 then CurX := Bnd.x;
  3335. CheckColumnPageBreak(Bnd.dx);
  3336. AggrBand := Bnd;
  3337. Bnd.DrawCrossCell(Self, CurX);
  3338. Bnd.InitValues;
  3339. end;
  3340. PageNo := sfpage;
  3341. ColumnXAdjust := 0;
  3342. IsColumns := False;
  3343. end;
  3344. function TfrBand.CheckPageBreak(y, dy: Integer; PBreak: Boolean): Boolean;
  3345. begin
  3346. Result := False;
  3347. with Parent do
  3348. if y + Bands[btColumnFooter].dy + dy > CurBottomY then
  3349. begin
  3350. if not PBreak then
  3351. NewColumn(Self);
  3352. Result := True;
  3353. end;
  3354. end;
  3355. procedure TfrBand.DrawPageBreak;
  3356. var
  3357. i: Integer;
  3358. dy, oldy, olddy, maxy: Integer;
  3359. t: TfrView;
  3360. Flag: Boolean;
  3361. procedure CorrY(t: TfrView; dy: Integer);
  3362. var
  3363. i: Integer;
  3364. t1: TfrView;
  3365. begin
  3366. for i := 0 to Objects.Count - 1 do
  3367. begin
  3368. t1 := Objects[i];
  3369. if t1 <> t then
  3370. if (t1.y > t.y + t.dy) and (t1.x >= t.x) and (t1.x <= t.x + t.dx) then
  3371. Inc(t1.y, dy);
  3372. end;
  3373. end;
  3374. begin
  3375. for i := 0 to Objects.Count - 1 do
  3376. begin
  3377. t := Objects[i];
  3378. t.Selected := True;
  3379. t.OriginalRect := Rect(t.x, t.y, t.dx, t.dy);
  3380. end;
  3381. if not CheckPageBreak(y, maxdy, True) then
  3382. DrawObjects
  3383. else
  3384. begin
  3385. for i := 0 to Objects.Count - 1 do
  3386. begin
  3387. t := Objects[i];
  3388. if t is TfrStretcheable then
  3389. TfrStretcheable(t).ActualHeight := 0;
  3390. if t is TfrMemoView then
  3391. begin
  3392. TfrMemoView(t).CalcHeight; // wraps a memo onto separate lines
  3393. t.Memo1.Assign(SMemo);
  3394. end;
  3395. end;
  3396. repeat
  3397. dy := Parent.CurBottomY - Parent.Bands[btColumnFooter].dy - y - 2;
  3398. maxy := 0;
  3399. for i := 0 to Objects.Count - 1 do
  3400. begin
  3401. t := Objects[i];
  3402. if t.Selected then
  3403. if (t.y >= 0) and (t.y < dy) then
  3404. if (t.y + t.dy < dy) then
  3405. begin
  3406. if maxy < t.y + t.dy then maxy := t.y + t.dy;
  3407. DrawObject(t);
  3408. t.Selected := False;
  3409. end
  3410. else
  3411. begin
  3412. if t is TfrStretcheable then
  3413. begin
  3414. olddy := t.dy;
  3415. t.dy := dy - t.y + 1;
  3416. Inc(TfrStretcheable(t).ActualHeight, t.dy);
  3417. if t.dy > TfrStretcheable(t).MinHeight then
  3418. begin
  3419. TfrStretcheable(t).DrawMode := drPart;
  3420. DrawObject(t);
  3421. end;
  3422. t.dy := olddy;
  3423. end
  3424. else
  3425. t.y := dy
  3426. end
  3427. else if t is TfrStretcheable then
  3428. if (t.y < 0) and (t.y + t.dy >= 0) then
  3429. if t.y + t.dy < dy then
  3430. begin
  3431. oldy := t.y; olddy := t.dy;
  3432. t.dy := t.y + t.dy;
  3433. t.y := 0;
  3434. if t.dy > TfrStretcheable(t).MinHeight div 2 then
  3435. begin
  3436. t.dy := TfrStretcheable(t).RemainHeight + t.gapy * 2 + 1;
  3437. Inc(TfrStretcheable(t).ActualHeight, t.dy - 1);
  3438. if maxy < t.y + t.dy then
  3439. maxy := t.y + t.dy;
  3440. TfrStretcheable(t).DrawMode := drPart;
  3441. DrawObject(t);
  3442. end;
  3443. t.y := oldy; t.dy := olddy;
  3444. CorrY(t, TfrStretcheable(t).ActualHeight - t.dy);
  3445. t.Selected := False;
  3446. end
  3447. else
  3448. begin
  3449. oldy := t.y; olddy := t.dy;
  3450. t.y := 0; t.dy := dy;
  3451. Inc(TfrStretcheable(t).ActualHeight, t.dy);
  3452. TfrStretcheable(t).DrawMode := drPart;
  3453. DrawObject(t);
  3454. t.y := oldy; t.dy := olddy;
  3455. end;
  3456. end;
  3457. Flag := False;
  3458. for i := 0 to Objects.Count - 1 do
  3459. begin
  3460. t := Objects[i];
  3461. if t.Selected then Flag := True;
  3462. Dec(t.y, dy);
  3463. end;
  3464. if Flag then CheckPageBreak(y, 10000, False);
  3465. y := Parent.CurY;
  3466. if MasterReport.Terminated then break;
  3467. until not Flag;
  3468. maxdy := maxy;
  3469. end;
  3470. for i := 0 to Objects.Count - 1 do
  3471. begin
  3472. t := Objects[i];
  3473. t.y := t.OriginalRect.Top;
  3474. t.dy := t.OriginalRect.Bottom;
  3475. end;
  3476. Inc(Parent.CurY, maxdy);
  3477. end;
  3478. function TfrBand.HasCross: Boolean;
  3479. var
  3480. i: Integer;
  3481. t: TfrView;
  3482. begin
  3483. Result := False;
  3484. for i := 0 to Objects.Count - 1 do
  3485. begin
  3486. t := Objects[i];
  3487. if t.Parent <> Self then
  3488. begin
  3489. Result := True;
  3490. break;
  3491. end;
  3492. end;
  3493. end;
  3494. procedure TfrBand.DoDraw;
  3495. var
  3496. sfy, sh: Integer;
  3497. UseY, WasSub: Boolean;
  3498. begin
  3499. if Objects.Count = 0 then Exit;
  3500. sfy := y;
  3501. UseY := not (Typ in [btPageFooter, btOverlay, btNone]);
  3502. if UseY then y := Parent.CurY;
  3503. if Stretched then
  3504. begin
  3505. sh := CalculatedHeight;
  3506. // sh := CalcHeight;
  3507. if sh > dy then StretchObjects(sh);
  3508. maxdy := sh;
  3509. if not PageBreak then CheckPageBreak(y, sh, False);
  3510. y := Parent.CurY;
  3511. WasSub := False;
  3512. if PageBreak then
  3513. begin
  3514. DrawPageBreak;
  3515. sh := 0;
  3516. end
  3517. else
  3518. begin
  3519. WasSub := DrawObjects;
  3520. if HasCross then DrawCross;
  3521. end;
  3522. UnStretchObjects;
  3523. if not WasSub then Inc(Parent.CurY, sh);
  3524. end
  3525. else
  3526. begin
  3527. if UseY then
  3528. begin
  3529. if not PageBreak then CheckPageBreak(y, dy, False);
  3530. y := Parent.CurY;
  3531. end;
  3532. if PageBreak then
  3533. begin
  3534. maxdy := CalculatedHeight;
  3535. // maxdy := CalcHeight;
  3536. DrawPageBreak;
  3537. end
  3538. else
  3539. begin
  3540. WasSub := DrawObjects;
  3541. if HasCross then DrawCross;
  3542. if UseY and not WasSub then Inc(Parent.CurY, dy);
  3543. end;
  3544. end;
  3545. y := sfy;
  3546. if Typ in [btMasterData, btDetailData, btSubDetailData] then
  3547. Parent.DoAggregate([btPageFooter, btMasterFooter, btDetailFooter,
  3548. btSubDetailFooter, btGroupFooter, btReportSummary]);
  3549. end;
  3550. function TfrBand.DoCalcHeight: Integer;
  3551. var
  3552. b: TfrBand;
  3553. begin
  3554. if (Typ in [btMasterData, btDetailData, btSubDetailData]) and
  3555. (Next <> nil) and (Next.Dataset = nil) then
  3556. begin
  3557. b := Self;
  3558. Result := 0;
  3559. repeat
  3560. Result := Result + b.CalcHeight;
  3561. b := b.Next;
  3562. until b = nil;
  3563. end
  3564. else
  3565. begin
  3566. Result := dy;
  3567. CalculatedHeight := dy;
  3568. if Stretched then Result := CalcHeight;
  3569. end;
  3570. end;
  3571. function TfrBand.Draw: Boolean;
  3572. var
  3573. b: TfrBand;
  3574. begin
  3575. Result := False;
  3576. CurView := View;
  3577. CurBand := Self;
  3578. AggrBand := Self;
  3579. CalculatedHeight := -1;
  3580. ForceNewPage := False;
  3581. ForceNewColumn := False;
  3582. if Assigned(CurReport.FOnBeginBand) then
  3583. CurReport.FOnBeginBand(Self);
  3584. frInterpretator.DoScript(Script);
  3585. // new page was requested in script
  3586. if ForceNewPage then
  3587. begin
  3588. Parent.CurColumn := Parent.ColCount - 1;
  3589. Parent.NewColumn(Self);
  3590. end;
  3591. if ForceNewColumn then
  3592. Parent.NewColumn(Self);
  3593. if Visible then
  3594. begin
  3595. if Typ = btColumnHeader then
  3596. Parent.LastStaticColumnY := Parent.CurY;
  3597. if Typ = btPageFooter then
  3598. y := Parent.CurBottomY;
  3599. if Objects.Count > 0 then
  3600. begin
  3601. if not (Typ in [btPageFooter, btOverlay, btNone]) then
  3602. if (Parent.CurY + DoCalcHeight > Parent.CurBottomY) and not PageBreak then
  3603. begin
  3604. Result := True;
  3605. if Parent.Skip then
  3606. Exit else
  3607. CheckPageBreak(0, 10000, False);
  3608. end;
  3609. EOFReached := True;
  3610. // dealing with multiple bands
  3611. if (Typ in [btMasterData, btDetailData, btSubDetailData]) and
  3612. (Next <> nil) and (Next.Dataset = nil) and (DataSet <> nil) then
  3613. begin
  3614. b := Self;
  3615. repeat
  3616. b.DoDraw;
  3617. b := b.Next;
  3618. until b = nil;
  3619. end
  3620. else
  3621. begin
  3622. DoDraw;
  3623. if not (Typ in [btMasterData, btDetailData, btSubDetailData, btGroupHeader]) and
  3624. NewPageAfter then
  3625. Parent.NewPage;
  3626. end;
  3627. if not EOFReached then Result := True;
  3628. end;
  3629. end
  3630. // if band is not visible, just performing aggregate calculations
  3631. // relative to it
  3632. else if Typ in [btMasterData, btDetailData, btSubDetailData] then
  3633. Parent.DoAggregate([btPageFooter, btMasterFooter, btDetailFooter,
  3634. btSubDetailFooter, btGroupFooter, btReportSummary]);
  3635. // check if multiple pagefooters (in cross-tab report) - resets last of them
  3636. if not DisableInit then
  3637. if (Typ <> btPageFooter) or (PageNo = MasterReport.EMFPages.Count - 1) then
  3638. InitValues;
  3639. if Assigned(CurReport.FOnEndBand) then
  3640. CurReport.FOnEndBand(Self);
  3641. end;
  3642. procedure TfrBand.InitValues;
  3643. var
  3644. b: TfrBand;
  3645. begin
  3646. if Typ = btGroupHeader then
  3647. begin
  3648. b := Self;
  3649. while b <> nil do
  3650. begin
  3651. if b.FooterBand <> nil then
  3652. begin
  3653. b.FooterBand.Values.Clear;
  3654. b.FooterBand.Count := 0;
  3655. end;
  3656. b.LastGroupValue := frParser.Calc(b.GroupCondition);
  3657. b := b.Next;
  3658. end;
  3659. end
  3660. else
  3661. begin
  3662. Values.Clear;
  3663. Count := 0;
  3664. end
  3665. end;
  3666. procedure TfrBand.DoAggregate;
  3667. var
  3668. i: Integer;
  3669. t: TfrView;
  3670. s: String;
  3671. v: Boolean;
  3672. begin
  3673. for i := 0 to Values.Count - 1 do
  3674. begin
  3675. s := Values[i];
  3676. Values[i] := Copy(s, 1, Pos('=', s) - 1) + '=0' + Copy(s, Pos('=', s) + 2, 255);
  3677. end;
  3678. v := Visible;
  3679. Visible := False;
  3680. AggrBand := Self;
  3681. for i := 0 to Objects.Count - 1 do
  3682. begin
  3683. t := Objects[i];
  3684. CurView := t;
  3685. if t is TfrMemoView then
  3686. TfrMemoView(t).ExpandVariables;
  3687. end;
  3688. Visible := v;
  3689. Inc(Count);
  3690. end;
  3691. {----------------------------------------------------------------------------}
  3692. type
  3693. TfrBandParts = (bpHeader, bpData, bpFooter);
  3694. const
  3695. MAXBNDS = 3;
  3696. Bnds: Array[1..MAXBNDS, TfrBandParts] of TfrBandType =
  3697. ((btMasterHeader, btMasterData, btMasterFooter),
  3698. (btDetailHeader, btDetailData, btDetailFooter),
  3699. (btSubDetailHeader, btSubDetailData, btSubDetailFooter));
  3700. constructor TfrPage.Create(ASize, AWidth, AHeight: Integer;
  3701. AOr: TPrinterOrientation);
  3702. begin
  3703. inherited Create;
  3704. List := TList.Create;
  3705. Objects := TList.Create;
  3706. RTObjects := TList.Create;
  3707. ChangePaper(ASize, AWidth, AHeight, AOr);
  3708. PrintToPrevPage := False;
  3709. UseMargins := True;
  3710. end;
  3711. destructor TfrPage.Destroy;
  3712. begin
  3713. Clear;
  3714. Objects.Free;
  3715. RTObjects.Free;
  3716. List.Free;
  3717. inherited Destroy;
  3718. end;
  3719. procedure TfrPage.ChangePaper(ASize, AWidth, AHeight: Integer;
  3720. AOr: TPrinterOrientation);
  3721. begin
  3722. try
  3723. Prn.SetPrinterInfo(ASize, AWidth, AHeight, AOr);
  3724. Prn.FillPrnInfo(PrnInfo);
  3725. except
  3726. on exception do
  3727. begin
  3728. Prn.SetPrinterInfo($100, AWidth, AHeight, AOr);
  3729. Prn.FillPrnInfo(PrnInfo);
  3730. end;
  3731. end;
  3732. pgSize := Prn.PaperSize;
  3733. pgWidth := Prn.PaperWidth;
  3734. pgHeight := Prn.PaperHeight;
  3735. pgOr := Prn.Orientation;
  3736. end;
  3737. procedure TfrPage.Clear;
  3738. begin
  3739. while Objects.Count > 0 do
  3740. Delete(0);
  3741. end;
  3742. procedure TfrPage.Delete(Index: Integer);
  3743. begin
  3744. TfrView(Objects[Index]).Free;
  3745. Objects.Delete(Index);
  3746. end;
  3747. function TfrPage.FindObjectByID(ID: Integer): Integer;
  3748. var
  3749. i: Integer;
  3750. begin
  3751. Result := -1;
  3752. for i := 0 to Objects.Count - 1 do
  3753. if TfrView(Objects[i]).ID = ID then
  3754. begin
  3755. Result := i;
  3756. break;
  3757. end;
  3758. end;
  3759. function TfrPage.FindObject(Name: String): TfrView;
  3760. var
  3761. i: Integer;
  3762. begin
  3763. Result := nil;
  3764. for i := 0 to Objects.Count - 1 do
  3765. if AnsiCompareText(TfrView(Objects[i]).Name, Name) = 0 then
  3766. begin
  3767. Result := Objects[i];
  3768. Exit;
  3769. end;
  3770. end;
  3771. function TfrPage.FindRTObject(Name: String): TfrView;
  3772. var
  3773. i: Integer;
  3774. begin
  3775. Result := nil;
  3776. for i := 0 to RTObjects.Count - 1 do
  3777. if AnsiCompareText(TfrView(RTObjects[i]).Name, Name) = 0 then
  3778. begin
  3779. Result := RTObjects[i];
  3780. Exit;
  3781. end;
  3782. end;
  3783. procedure TfrPage.InitReport;
  3784. var
  3785. b: TfrBandType;
  3786. begin
  3787. for b := btReportTitle to btNone do
  3788. Bands[b] := TfrBand.Create(b, Self);
  3789. while RTObjects.Count > 0 do
  3790. begin
  3791. TfrView(RTObjects[0]).Free;
  3792. RTObjects.Delete(0);
  3793. end;
  3794. TossObjects;
  3795. InitFlag := True;
  3796. CurPos := 1; ColPos := 1;
  3797. end;
  3798. procedure TfrPage.DoneReport;
  3799. var
  3800. b: TfrBandType;
  3801. begin
  3802. if InitFlag then
  3803. begin
  3804. for b := btReportTitle to btNone do
  3805. Bands[b].Free;
  3806. while RTObjects.Count > 0 do
  3807. begin
  3808. TfrView(RTObjects[0]).Free;
  3809. RTObjects.Delete(0);
  3810. end;
  3811. end;
  3812. InitFlag := False;
  3813. end;
  3814. function TfrPage.TopMargin: Integer;
  3815. begin
  3816. if UseMargins then
  3817. if pgMargins.Top = 0 then
  3818. Result := PrnInfo.Ofy else
  3819. Result := pgMargins.Top
  3820. else
  3821. Result := 0;
  3822. end;
  3823. function TfrPage.BottomMargin: Integer;
  3824. begin
  3825. with PrnInfo do
  3826. if UseMargins then
  3827. if pgMargins.Bottom = 0 then
  3828. Result := Ofy + Ph else
  3829. Result := Pgh - pgMargins.Bottom
  3830. else
  3831. Result := Pgh;
  3832. if (DocMode <> dmDesigning) and BandExists(Bands[btPageFooter]) then
  3833. Result := Result - Bands[btPageFooter].dy;
  3834. end;
  3835. function TfrPage.LeftMargin: Integer;
  3836. begin
  3837. if UseMargins then
  3838. if pgMargins.Left = 0 then
  3839. Result := PrnInfo.Ofx else
  3840. Result := pgMargins.Left
  3841. else
  3842. Result := 0;
  3843. end;
  3844. function TfrPage.RightMargin: Integer;
  3845. begin
  3846. with PrnInfo do
  3847. if UseMargins then
  3848. if pgMargins.Right = 0 then
  3849. Result := Ofx + Pw else
  3850. Result := Pgw - pgMargins.Right
  3851. else
  3852. Result := Pgw;
  3853. end;
  3854. procedure TfrPage.TossObjects;
  3855. var
  3856. i, j, n, last, miny: Integer;
  3857. b: TfrBandType;
  3858. bt, t: TfrView;
  3859. Bnd, Bnd1: TfrBand;
  3860. FirstBand, Flag: Boolean;
  3861. BArr: Array[0..31] of TfrBand;
  3862. s: String;
  3863. begin
  3864. for i := 0 to Objects.Count - 1 do
  3865. begin
  3866. bt := Objects[i];
  3867. t := frCreateObject(bt.Typ, bt.ClassName);
  3868. t.Assign(bt);
  3869. t.StreamMode := smPrinting;
  3870. RTObjects.Add(t);
  3871. if (t.Flags and flWantHook) <> 0 then
  3872. HookList.Add(t);
  3873. end;
  3874. for i := 0 to RTObjects.Count - 1 do // select all objects exclude bands
  3875. begin
  3876. t := RTObjects[i];
  3877. t.Selected := t.Typ <> gtBand;
  3878. t.Parent := nil;
  3879. frInterpretator.PrepareScript(t.Script, t.Script, SMemo);
  3880. if t.Typ = gtSubReport then
  3881. CurReport.Pages[(t as TfrSubReportView).SubPage].Skip := True;
  3882. end;
  3883. Flag := False;
  3884. for i := 0 to RTObjects.Count - 1 do // search for btCrossXXX bands
  3885. begin
  3886. bt := RTObjects[i];
  3887. if (bt.Typ = gtBand) and
  3888. (TfrBandType(bt.FrameTyp) in [btCrossHeader..btCrossFooter]) then
  3889. with Bands[TfrBandType(bt.FrameTyp)] do
  3890. begin
  3891. Memo.Assign(bt.Memo);
  3892. Script.Assign(bt.Script);
  3893. x := bt.x; dx := bt.dx;
  3894. InitDataSet(bt.FormatStr);
  3895. View := bt;
  3896. Flags := bt.Flags;
  3897. Visible := bt.Visible;
  3898. bt.Parent := Bands[TfrBandType(bt.FrameTyp)];
  3899. Flag := True;
  3900. end;
  3901. end;
  3902. if Flag then // fill a ColumnXXX bands at first
  3903. for b := btCrossHeader to btCrossFooter do
  3904. begin
  3905. Bnd := Bands[b];
  3906. for i := 0 to RTObjects.Count - 1 do
  3907. begin
  3908. t := RTObjects[i];
  3909. if t.Selected then
  3910. if (t.x >= Bnd.x) and (t.x + t.dx <= Bnd.x + Bnd.dx) then
  3911. begin
  3912. t.x := t.x - Bnd.x;
  3913. t.Parent := Bnd;
  3914. Bnd.Objects.Add(t);
  3915. end;
  3916. end;
  3917. end;
  3918. for b := btReportTitle to btGroupFooter do // fill other bands
  3919. begin
  3920. FirstBand := True;
  3921. Bnd := Bands[b];
  3922. BArr[0] := Bnd;
  3923. Last := 1;
  3924. for i := 0 to RTObjects.Count - 1 do // search for specified band
  3925. begin
  3926. bt := RTObjects[i];
  3927. if (bt.Typ = gtBand) and (bt.FrameTyp = Integer(b)) then
  3928. begin
  3929. if not FirstBand then
  3930. begin
  3931. Bnd.Next := TfrBand.Create(b,Self);
  3932. Bnd := Bnd.Next;
  3933. BArr[Last] := Bnd;
  3934. Inc(Last);
  3935. end;
  3936. FirstBand := False;
  3937. Bnd.Memo.Assign(bt.Memo);
  3938. Bnd.Script.Assign(bt.Script);
  3939. Bnd.y := bt.y;
  3940. Bnd.dy := bt.dy;
  3941. Bnd.View := bt;
  3942. Bnd.Flags := bt.Flags;
  3943. Bnd.Visible := bt.Visible;
  3944. bt.Parent := Bnd;
  3945. with bt as TfrBandView, Bnd do
  3946. begin
  3947. InitDataSet(FormatStr);
  3948. Stretched := (Flags and flStretched) <> 0;
  3949. PrintIfSubsetEmpty := (Flags and flBandPrintIfSubsetEmpty) <> 0;
  3950. if Skip then
  3951. begin
  3952. NewPageAfter := False;
  3953. PageBreak := False;
  3954. end
  3955. else
  3956. begin
  3957. NewPageAfter := (Flags and flBandNewPageAfter) <> 0;
  3958. PageBreak := (Flags and flBandPageBreak) <> 0;
  3959. end;
  3960. end;
  3961. for j := 0 to RTObjects.Count - 1 do // placing objects over band
  3962. begin
  3963. t := RTObjects[j];
  3964. if (t.Parent = nil) and (t.Typ <> gtSubReport) then
  3965. if t.Selected then
  3966. if (t.y >= Bnd.y) and (t.y <= Bnd.y + Bnd.dy) then
  3967. begin
  3968. t.Parent := Bnd;
  3969. t.y := t.y - Bnd.y;
  3970. t.Selected := False;
  3971. Bnd.Objects.Add(t);
  3972. end;
  3973. end;
  3974. for j := 0 to RTObjects.Count - 1 do // placing ColumnXXX objects over band
  3975. begin
  3976. t := RTObjects[j];
  3977. if t.Parent <> nil then
  3978. if t.Selected then
  3979. if (t.y >= Bnd.y) and (t.y <= Bnd.y + Bnd.dy) then
  3980. begin
  3981. t.y := t.y - Bnd.y;
  3982. t.Selected := False;
  3983. Bnd.Objects.Add(t);
  3984. end;
  3985. end;
  3986. for j := 0 to RTObjects.Count - 1 do // placing subreports over band
  3987. begin
  3988. t := RTObjects[j];
  3989. if (t.Parent = nil) and (t.Typ = gtSubReport) then
  3990. if t.Selected then
  3991. if (t.y >= Bnd.y) and (t.y <= Bnd.y + Bnd.dy) then
  3992. begin
  3993. t.Parent := Bnd;
  3994. t.y := t.y - Bnd.y;
  3995. t.Selected := False;
  3996. Bnd.Objects.Add(t);
  3997. end;
  3998. end;
  3999. end;
  4000. end;
  4001. for i := 0 to Last - 1 do // sorting bands
  4002. begin
  4003. miny := BArr[i].y; n := i;
  4004. for j := i + 1 to Last - 1 do
  4005. if BArr[j].y < miny then
  4006. begin
  4007. miny := BArr[j].y;
  4008. n := j;
  4009. end;
  4010. Bnd := BArr[i]; BArr[i] := BArr[n]; BArr[n] := Bnd;
  4011. end;
  4012. Bnd := BArr[0]; Bands[b] := Bnd;
  4013. Bnd.Prev := nil;
  4014. for i := 1 to Last - 1 do // finally ordering
  4015. begin
  4016. Bnd.Next := BArr[i];
  4017. Bnd := Bnd.Next;
  4018. Bnd.Prev := BArr[i - 1];
  4019. end;
  4020. Bnd.Next := nil;
  4021. Bands[b].LastBand := Bnd;
  4022. end;
  4023. for i := 0 to RTObjects.Count - 1 do // place other objects on btNone band
  4024. begin
  4025. t := RTObjects[i];
  4026. if t.Selected then
  4027. begin
  4028. t.Parent := Bands[btNone];
  4029. Bands[btNone].y := 0;
  4030. Bands[btNone].Objects.Add(t);
  4031. end;
  4032. end;
  4033. for i := 1 to MAXBNDS do // connect header & footer to each data-band
  4034. begin
  4035. Bnd := Bands[Bnds[i, bpHeader]];
  4036. while Bnd <> nil do
  4037. begin
  4038. Bnd1 := Bands[Bnds[i, bpData]];
  4039. while Bnd1 <> nil do
  4040. begin
  4041. if Bnd1.y > Bnd.y + Bnd.dy then break;
  4042. Bnd1 := Bnd1.Next;
  4043. end;
  4044. if (Bnd1 <> nil) and (Bnd1.HeaderBand = nil) then
  4045. Bnd1.HeaderBand := Bnd;
  4046. Bnd := Bnd.Next;
  4047. end;
  4048. Bnd := Bands[Bnds[i, bpFooter]];
  4049. while Bnd <> nil do
  4050. begin
  4051. Bnd1 := Bands[Bnds[i, bpData]];
  4052. while Bnd1 <> nil do
  4053. begin
  4054. if Bnd1.y + Bnd1.dy > Bnd.y then
  4055. begin
  4056. Bnd1 := Bnd1.Prev;
  4057. break;
  4058. end;
  4059. if Bnd1.Next = nil then break;
  4060. Bnd1 := Bnd1.Next;
  4061. end;
  4062. if (Bnd1 <> nil) and (Bnd1.FooterBand = nil) then
  4063. Bnd1.FooterBand := Bnd;
  4064. Bnd := Bnd.Next;
  4065. end;
  4066. end;
  4067. Bnd := Bands[btGroupHeader].LastBand;
  4068. Bnd1 := Bands[btGroupFooter];
  4069. repeat
  4070. Bnd.FooterBand := Bnd1;
  4071. Bnd := Bnd.Prev;
  4072. Bnd1 := Bnd1.Next;
  4073. until (Bnd = nil) or (Bnd1 = nil);
  4074. if BandExists(Bands[btCrossData]) and (Pos(';', Bands[btCrossData].View.FormatStr) <> 0) then
  4075. begin
  4076. s := Bands[btCrossData].View.FormatStr;
  4077. i := 1;
  4078. while i < Length(s) do
  4079. begin
  4080. j := i;
  4081. while s[j] <> '=' do Inc(j);
  4082. n := j;
  4083. while s[n] <> ';' do Inc(n);
  4084. for b := btMasterHeader to btGroupFooter do
  4085. begin
  4086. Bnd := Bands[b];
  4087. while Bnd <> nil do
  4088. begin
  4089. if Bnd.View <> nil then
  4090. if AnsiCompareText(Bnd.View.Name, Copy(s, i, j - i)) = 0 then
  4091. CreateDS(Copy(s, j + 1, n - j - 1), Bnd.VCDataSet, Bnd.IsVirtualVCDS);
  4092. Bnd := Bnd.Next;
  4093. end;
  4094. end;
  4095. i := n + 1;
  4096. end;
  4097. end;
  4098. if ColCount = 0 then ColCount := 1;
  4099. ColWidth := (RightMargin - LeftMargin) div ColCount;
  4100. end;
  4101. procedure TfrPage.PrepareObjects;
  4102. var
  4103. i, j: Integer;
  4104. t: TfrView;
  4105. Value: TfrValue;
  4106. s: String;
  4107. DSet: TfrTDataSet;
  4108. Field: TfrTField;
  4109. begin
  4110. CurPage := Self;
  4111. for i := 0 to RTObjects.Count - 1 do
  4112. begin
  4113. t := RTObjects[i];
  4114. t.FField := '';
  4115. if t.Memo.Count > 0 then
  4116. s := t.Memo[0];
  4117. j := Length(s);
  4118. if (j > 2) and (s[1] = '[') then
  4119. begin
  4120. while (j > 0) and (s[j] <> ']') do Dec(j);
  4121. s := Copy(s, 2, j - 2);
  4122. t.FDataSet := nil;
  4123. t.FField := '';
  4124. Value := CurReport.Values.FindVariable(s);
  4125. if Value = nil then
  4126. begin
  4127. CurBand := t.Parent;
  4128. DSet := GetDefaultDataset;
  4129. frGetDatasetAndField(s, DSet, Field);
  4130. if Field <> nil then
  4131. begin
  4132. t.FDataSet := DSet;
  4133. t.FField := Field.FieldName;
  4134. end;
  4135. end
  4136. else if Value.Typ = vtDBField then
  4137. if Value.DSet <> nil then
  4138. begin
  4139. t.FDataSet := Value.DSet;
  4140. t.FField := Value.Field;
  4141. end;
  4142. end;
  4143. end;
  4144. end;
  4145. procedure TfrPage.ShowBand(b: TfrBand);
  4146. begin
  4147. if b <> nil then
  4148. if Mode = pmBuildList then
  4149. AddRecord(b, rtShowBand) else
  4150. b.Draw;
  4151. end;
  4152. procedure TfrPage.ShowBandByName(s: String);
  4153. var
  4154. bt: TfrBandType;
  4155. b: TfrBand;
  4156. begin
  4157. for bt := btReportTitle to btNone do
  4158. begin
  4159. b := Bands[bt];
  4160. while b <> nil do
  4161. begin
  4162. if b.View <> nil then
  4163. if AnsiCompareText(b.View.Name, s) = 0 then
  4164. begin
  4165. b.Draw;
  4166. Exit;
  4167. end;
  4168. b := b.Next;
  4169. end;
  4170. end;
  4171. end;
  4172. procedure TfrPage.ShowBandByType(bt: TfrBandType);
  4173. var
  4174. b: TfrBand;
  4175. begin
  4176. b := Bands[bt];
  4177. if b <> nil then
  4178. b.Draw;
  4179. end;
  4180. procedure TfrPage.AddRecord(b: TfrBand; rt: TfrBandRecType);
  4181. var
  4182. p: PfrBandRec;
  4183. begin
  4184. GetMem(p, SizeOf(TfrBandRec));
  4185. p^.Band := b;
  4186. p^.Action := rt;
  4187. List.Add(p);
  4188. end;
  4189. procedure TfrPage.ClearRecList;
  4190. var
  4191. i: Integer;
  4192. begin
  4193. for i := 0 to List.Count - 1 do
  4194. FreeMem(PfrBandRec(List[i]), SizeOf(TfrBandRec));
  4195. List.Clear;
  4196. end;
  4197. function TfrPage.PlayRecList: Boolean;
  4198. var
  4199. p: PfrBandRec;
  4200. b: TfrBand;
  4201. begin
  4202. Result := False;
  4203. while PlayFrom < List.Count do
  4204. begin
  4205. p := List[PlayFrom];
  4206. b := p^.Band;
  4207. case p^.Action of
  4208. rtShowBand:
  4209. begin
  4210. if LastBand <> nil then
  4211. begin
  4212. LastBand.DoSubReports;
  4213. if LastBand <> nil then
  4214. begin
  4215. Result := True;
  4216. Exit;
  4217. end;
  4218. end
  4219. else
  4220. if b.Draw then
  4221. begin
  4222. Result := True;
  4223. Exit;
  4224. end;
  4225. end;
  4226. rtFirst:
  4227. begin
  4228. b.DataSet.First;
  4229. b.Positions[psLocal] := 1;
  4230. end;
  4231. rtNext:
  4232. begin
  4233. b.DataSet.Next;
  4234. Inc(CurPos);
  4235. Inc(b.Positions[psGlobal]);
  4236. Inc(b.Positions[psLocal]);
  4237. end;
  4238. end;
  4239. Inc(PlayFrom);
  4240. end;
  4241. end;
  4242. procedure TfrPage.DrawPageFooters;
  4243. begin
  4244. CurColumn := 0;
  4245. XAdjust := LeftMargin;
  4246. if (PageNo <> 0) or ((Bands[btPageFooter].Flags and flBandOnFirstPage) <> 0) then
  4247. while PageNo < MasterReport.EMFPages.Count do
  4248. begin
  4249. if not (Append and WasPF) then
  4250. begin
  4251. if (CurReport <> nil) and Assigned(CurReport.FOnEndPage) then
  4252. CurReport.FOnEndPage(PageNo);
  4253. if (MasterReport <> CurReport) and (MasterReport <> nil) and
  4254. Assigned(MasterReport.FOnEndPage) then
  4255. MasterReport.FOnEndPage(PageNo);
  4256. ShowBand(Bands[btPageFooter]);
  4257. end;
  4258. Inc(PageNo);
  4259. end;
  4260. PageNo := MasterReport.EMFPages.Count;
  4261. end;
  4262. procedure TfrPage.NewPage;
  4263. begin
  4264. CurReport.InternalOnProgress(PageNo + 1);
  4265. ShowBand(Bands[btColumnFooter]);
  4266. DrawPageFooters;
  4267. CurBottomY := BottomMargin;
  4268. MasterReport.EMFPages.Add(Self);
  4269. Append := False;
  4270. ShowBand(Bands[btOverlay]);
  4271. CurY := TopMargin;
  4272. ShowBand(Bands[btPageHeader]);
  4273. ShowBand(Bands[btColumnHeader]);
  4274. end;
  4275. procedure TfrPage.NewColumn(Band: TfrBand);
  4276. var
  4277. b: TfrBand;
  4278. begin
  4279. if CurColumn < ColCount - 1 then
  4280. begin
  4281. ShowBand(Bands[btColumnFooter]);
  4282. Inc(CurColumn);
  4283. Inc(XAdjust, ColWidth + ColGap);
  4284. CurY := LastStaticColumnY;
  4285. ShowBand(Bands[btColumnHeader]);
  4286. end
  4287. else
  4288. NewPage;
  4289. b := Bands[btGroupHeader];
  4290. if b <> nil then
  4291. while (b <> nil) and (b <> Band) do
  4292. begin
  4293. b.DisableInit := True;
  4294. if (b.Flags and flBandRepeatHeader) <> 0 then
  4295. ShowBand(b);
  4296. b.DisableInit := False;
  4297. b := b.Next;
  4298. end;
  4299. if Band.Typ in [btMasterData, btDetailData, btSubDetailData] then
  4300. if (Band.HeaderBand <> nil) and
  4301. ((Band.HeaderBand.Flags and flBandRepeatHeader) <> 0) then
  4302. ShowBand(Band.HeaderBand);
  4303. end;
  4304. procedure TfrPage.DoAggregate(a: Array of TfrBandType);
  4305. var
  4306. i: Integer;
  4307. procedure DoAggregate1(bt: TfrBandType);
  4308. var
  4309. b: TfrBand;
  4310. begin
  4311. b := Bands[bt];
  4312. while b <> nil do
  4313. begin
  4314. b.DoAggregate;
  4315. b := b.Next;
  4316. end;
  4317. end;
  4318. begin
  4319. for i := Low(a) to High(a) do
  4320. DoAggregate1(a[i]);
  4321. end;
  4322. procedure TfrPage.FormPage;
  4323. var
  4324. BndStack: Array[1..MAXBNDS * 3] of TfrBand;
  4325. MaxLevel, BndStackTop: Integer;
  4326. i, sfPage: Integer;
  4327. HasGroups: Boolean;
  4328. procedure AddToStack(b: TfrBand);
  4329. begin
  4330. if b <> nil then
  4331. begin
  4332. Inc(BndStackTop);
  4333. BndStack[BndStackTop] := b;
  4334. end;
  4335. end;
  4336. procedure ShowStack;
  4337. var
  4338. i: Integer;
  4339. begin
  4340. for i := 1 to BndStackTop do
  4341. if BandExists(BndStack[i]) then
  4342. ShowBand(BndStack[i]);
  4343. BndStackTop := 0;
  4344. end;
  4345. procedure DoLoop(Level: Integer);
  4346. var
  4347. WasPrinted: Boolean;
  4348. b, b1, b2: TfrBand;
  4349. procedure InitGroups(b: TfrBand);
  4350. begin
  4351. while b <> nil do
  4352. begin
  4353. Inc(b.Positions[psLocal]);
  4354. Inc(b.Positions[psGlobal]);
  4355. ShowBand(b);
  4356. b := b.Next;
  4357. end;
  4358. end;
  4359. begin
  4360. b := Bands[Bnds[Level, bpData]];
  4361. while (b <> nil) and (b.Dataset <> nil) do
  4362. begin
  4363. b.DataSet.First;
  4364. if Mode = pmBuildList then
  4365. AddRecord(b, rtFirst) else
  4366. b.Positions[psLocal] := 1;
  4367. b1 := Bands[btGroupHeader];
  4368. while b1 <> nil do
  4369. begin
  4370. b1.Positions[psLocal] := 0;
  4371. b1.Positions[psGlobal] := 0;
  4372. b1 := b1.Next;
  4373. end;
  4374. if not b.DataSet.Eof then
  4375. begin
  4376. if (Level = 1) and HasGroups then
  4377. InitGroups(Bands[btGroupHeader]);
  4378. if b.HeaderBand <> nil then
  4379. AddToStack(b.HeaderBand);
  4380. if b.FooterBand <> nil then
  4381. b.FooterBand.InitValues;
  4382. while not b.DataSet.Eof do
  4383. begin
  4384. Application.ProcessMessages;
  4385. if MasterReport.Terminated then break;
  4386. AddToStack(b);
  4387. WasPrinted := True;
  4388. if Level < MaxLevel then
  4389. begin
  4390. DoLoop(Level + 1);
  4391. if BndStackTop > 0 then
  4392. if b.PrintIfSubsetEmpty then
  4393. ShowStack
  4394. else
  4395. begin
  4396. Dec(BndStackTop);
  4397. WasPrinted := False;
  4398. end;
  4399. end
  4400. else ShowStack;
  4401. b.DataSet.Next;
  4402. if (Level = 1) and HasGroups then
  4403. begin
  4404. b1 := Bands[btGroupHeader];
  4405. while b1 <> nil do
  4406. begin
  4407. if (frParser.Calc(b1.GroupCondition) <> b1.LastGroupValue) or
  4408. b.Dataset.Eof then
  4409. begin
  4410. ShowBand(b.FooterBand);
  4411. b2 := Bands[btGroupHeader].LastBand;
  4412. while b2 <> b1 do
  4413. begin
  4414. ShowBand(b2.FooterBand);
  4415. b2.Positions[psLocal] := 0;
  4416. b2 := b2.Prev;
  4417. end;
  4418. ShowBand(b1.FooterBand);
  4419. if not b.DataSet.Eof then
  4420. begin
  4421. if b1.NewPageAfter then NewPage;
  4422. InitGroups(b1);
  4423. ShowBand(b.HeaderBand);
  4424. b.Positions[psLocal] := 0;
  4425. end;
  4426. break;
  4427. end;
  4428. b1 := b1.Next;
  4429. end;
  4430. end;
  4431. if Mode = pmBuildList then
  4432. AddRecord(b, rtNext)
  4433. else if WasPrinted then
  4434. begin
  4435. Inc(CurPos);
  4436. Inc(b.Positions[psGlobal]);
  4437. Inc(b.Positions[psLocal]);
  4438. if not b.DataSet.Eof and b.NewPageAfter then NewPage;
  4439. end;
  4440. if MasterReport.Terminated then break;
  4441. end;
  4442. if BndStackTop = 0 then
  4443. ShowBand(b.FooterBand) else
  4444. Dec(BndStackTop);
  4445. end;
  4446. b := b.Next;
  4447. end;
  4448. end;
  4449. begin
  4450. if Mode = pmNormal then
  4451. begin
  4452. if Append then
  4453. if PrevY = PrevBottomY then
  4454. begin
  4455. Append := False;
  4456. WasPF := False;
  4457. PageNo := MasterReport.EMFPages.Count;
  4458. end;
  4459. if Append and WasPF then
  4460. CurBottomY := PrevBottomY else
  4461. CurBottomY := BottomMargin;
  4462. CurColumn := 0;
  4463. XAdjust := LeftMargin;
  4464. if not Append then
  4465. begin
  4466. MasterReport.EMFPages.Add(Self);
  4467. CurY := TopMargin;
  4468. ShowBand(Bands[btOverlay]);
  4469. ShowBand(Bands[btNone]);
  4470. end
  4471. else
  4472. CurY := PrevY;
  4473. sfPage := PageNo;
  4474. ShowBand(Bands[btReportTitle]);
  4475. if PageNo = sfPage then // check if new page was formed
  4476. begin
  4477. if BandExists(Bands[btPageHeader]) and
  4478. ((Bands[btPageHeader].Flags and flBandOnFirstPage) <> 0) then
  4479. ShowBand(Bands[btPageHeader]);
  4480. ShowBand(Bands[btColumnHeader]);
  4481. end;
  4482. end;
  4483. BndStackTop := 0;
  4484. for i := 1 to MAXBNDS do
  4485. if BandExists(Bands[Bnds[i, bpData]]) then
  4486. MaxLevel := i;
  4487. HasGroups := Bands[btGroupHeader].Objects.Count > 0;
  4488. DoLoop(1);
  4489. if Mode = pmNormal then
  4490. begin
  4491. ShowBand(Bands[btColumnFooter]);
  4492. ShowBand(Bands[btReportSummary]);
  4493. PrevY := CurY;
  4494. PrevBottomY := CurBottomY;
  4495. if CurColumn > 0 then
  4496. PrevY := BottomMargin;
  4497. CurColumn := 0;
  4498. XAdjust := LeftMargin;
  4499. sfPage := PageNo;
  4500. WasPF := False;
  4501. if (Bands[btPageFooter].Flags and flBandOnLastPage) <> 0 then
  4502. begin
  4503. WasPF := BandExists(Bands[btPageFooter]);
  4504. if WasPF then DrawPageFooters;
  4505. end;
  4506. PageNo := sfPage + 1;
  4507. end;
  4508. end;
  4509. function TfrPage.BandExists(b: TfrBand): Boolean;
  4510. begin
  4511. Result := b.Objects.Count > 0;
  4512. end;
  4513. procedure TfrPage.AfterPrint;
  4514. var
  4515. i: Integer;
  4516. begin
  4517. for i := 0 to HookList.Count - 1 do
  4518. TfrView(HookList[i]).OnHook(CurView);
  4519. end;
  4520. procedure TfrPage.LoadFromStream(Stream: TStream);
  4521. var
  4522. b: Byte;
  4523. s: String[6];
  4524. begin
  4525. with Stream do
  4526. begin
  4527. Read(pgSize, 4);
  4528. Read(pgWidth, 4);
  4529. Read(pgHeight, 4);
  4530. Read(pgMargins, Sizeof(pgMargins));
  4531. Read(b, 1);
  4532. pgOr := TPrinterOrientation(b);
  4533. if frVersion < 23 then
  4534. Read(s[1], 6);
  4535. Read(PrintToPrevPage, 2);
  4536. Read(UseMargins, 2);
  4537. Read(ColCount, 4);
  4538. Read(ColGap, 4);
  4539. end;
  4540. ChangePaper(pgSize, pgWidth, pgHeight, pgOr);
  4541. end;
  4542. procedure TfrPage.SaveToStream(Stream: TStream);
  4543. var
  4544. b: Byte;
  4545. begin
  4546. with Stream do
  4547. begin
  4548. Write(pgSize, 4);
  4549. Write(pgWidth, 4);
  4550. Write(pgHeight, 4);
  4551. Write(pgMargins, Sizeof(pgMargins));
  4552. b := Byte(pgOr);
  4553. Write(b, 1);
  4554. Write(PrintToPrevPage, 2);
  4555. Write(UseMargins, 2);
  4556. Write(ColCount, 4);
  4557. Write(ColGap, 4);
  4558. end;
  4559. end;
  4560. {-----------------------------------------------------------------------}
  4561. constructor TfrPages.Create(AParent: TfrReport);
  4562. begin
  4563. inherited Create;
  4564. Parent := AParent;
  4565. FPages := TList.Create;
  4566. end;
  4567. destructor TfrPages.Destroy;
  4568. begin
  4569. Clear;
  4570. FPages.Free;
  4571. inherited Destroy;
  4572. end;
  4573. function TfrPages.GetCount: Integer;
  4574. begin
  4575. Result := FPages.Count;
  4576. end;
  4577. function TfrPages.GetPages(Index: Integer): TfrPage;
  4578. begin
  4579. Result := FPages[Index];
  4580. end;
  4581. procedure TfrPages.Clear;
  4582. var
  4583. i: Integer;
  4584. begin
  4585. for i := 0 to FPages.Count - 1 do
  4586. Pages[i].Free;
  4587. FPages.Clear;
  4588. end;
  4589. procedure TfrPages.Add;
  4590. begin
  4591. FPages.Add(TfrPage.Create(9, 0, 0, poPortrait));
  4592. end;
  4593. procedure TfrPages.Delete(Index: Integer);
  4594. begin
  4595. Pages[Index].Free;
  4596. FPages.Delete(Index);
  4597. end;
  4598. procedure TfrPages.LoadFromStream(Stream: TStream);
  4599. var
  4600. b: Byte;
  4601. t: TfrView;
  4602. s: String;
  4603. buf: String[8];
  4604. procedure AddObject(ot: Byte; clname: String);
  4605. begin
  4606. Stream.Read(b, 1);
  4607. Pages[b].Objects.Add(frCreateObject(ot, clname));
  4608. t := Pages[b].Objects.Items[Pages[b].Objects.Count - 1];
  4609. end;
  4610. begin
  4611. Clear;
  4612. Stream.Read(Parent.PrintToDefault, 2);
  4613. Stream.Read(Parent.DoublePass, 2);
  4614. Parent.SetPrinterTo(ReadString(Stream));
  4615. while Stream.Position < Stream.Size do
  4616. begin
  4617. Stream.Read(b, 1);
  4618. if b = $FF then // page info
  4619. begin
  4620. Add;
  4621. Pages[Count - 1].LoadFromStream(Stream);
  4622. end
  4623. else if b = $FE then // values
  4624. begin
  4625. Parent.FVal.ReadBinaryData(Stream);
  4626. ReadMemo(Stream, SMemo);
  4627. Parent.Variables.Assign(SMemo);
  4628. end
  4629. else if b = $FD then // datasets
  4630. begin
  4631. if frDataManager <> nil then
  4632. frDataManager.LoadFromStream(Stream);
  4633. break;
  4634. end
  4635. else
  4636. begin
  4637. if b > Integer(gtAddIn) then
  4638. begin
  4639. raise Exception.Create('');
  4640. break;
  4641. end;
  4642. s := '';
  4643. if b = gtAddIn then
  4644. begin
  4645. s := ReadString(Stream);
  4646. if AnsiUpperCase(s) = 'TFRFRAMEDMEMOVIEW' then
  4647. AddObject(gtMemo, '') else
  4648. AddObject(gtAddIn, s);
  4649. end
  4650. else
  4651. AddObject(b, '');
  4652. t.LoadFromStream(Stream);
  4653. if AnsiUpperCase(s) = 'TFRFRAMEDMEMOVIEW' then
  4654. Stream.Read(buf[1], 8);
  4655. end;
  4656. end;
  4657. end;
  4658. procedure TfrPages.SaveToStream(Stream: TStream);
  4659. var
  4660. b: Byte;
  4661. i, j: Integer;
  4662. t: TfrView;
  4663. begin
  4664. if CurReport.FR3Stream then
  4665. begin
  4666. SaveToFR3Stream(CurReport, Stream);
  4667. Exit;
  4668. end;
  4669. Stream.Write(Parent.PrintToDefault, 2);
  4670. Stream.Write(Parent.DoublePass, 2);
  4671. frWriteString(Stream, Prn.Printers[Prn.PrinterIndex]);
  4672. for i := 0 to Count - 1 do // adding pages at first
  4673. begin
  4674. b := $FF;
  4675. Stream.Write(b, 1); // page info
  4676. Pages[i].SaveToStream(Stream);
  4677. end;
  4678. for i := 0 to Count - 1 do
  4679. begin
  4680. for j := 0 to Pages[i].Objects.Count - 1 do // then adding objects
  4681. begin
  4682. t := Pages[i].Objects[j];
  4683. b := Byte(t.Typ);
  4684. Stream.Write(b, 1);
  4685. if t.Typ = gtAddIn then
  4686. frWriteString(Stream, t.ClassName);
  4687. Stream.Write(i, 1);
  4688. t.SaveToStream(Stream);
  4689. end;
  4690. end;
  4691. b := $FE;
  4692. Stream.Write(b, 1);
  4693. Parent.FVal.WriteBinaryData(Stream);
  4694. SMemo.Assign(Parent.Variables);
  4695. frWriteMemo(Stream, SMemo);
  4696. if frDataManager <> nil then
  4697. begin
  4698. b := $FD;
  4699. Stream.Write(b, 1);
  4700. frDataManager.SaveToStream(Stream);
  4701. end;
  4702. end;
  4703. {-----------------------------------------------------------------------}
  4704. constructor TfrEMFPages.Create(AParent: TfrReport);
  4705. begin
  4706. inherited Create;
  4707. Parent := AParent;
  4708. FPages := TList.Create;
  4709. end;
  4710. destructor TfrEMFPages.Destroy;
  4711. begin
  4712. Clear;
  4713. FPages.Free;
  4714. inherited Destroy;
  4715. end;
  4716. function TfrEMFPages.GetCount: Integer;
  4717. begin
  4718. Result := FPages.Count;
  4719. end;
  4720. function TfrEMFPages.GetPages(Index: Integer): PfrPageInfo;
  4721. begin
  4722. Result := FPages[Index];
  4723. end;
  4724. procedure TfrEMFPages.Clear;
  4725. begin
  4726. while FPages.Count > 0 do
  4727. Delete(0);
  4728. end;
  4729. procedure TfrEMFPages.Draw(Index: Integer; Canvas: TCanvas; DrawRect: TRect);
  4730. var
  4731. p: PfrPageInfo;
  4732. t: TfrView;
  4733. i: Integer;
  4734. sx, sy: Double;
  4735. v, IsPrinting: Boolean;
  4736. h: THandle;
  4737. begin
  4738. IsPrinting := Printer.Printing and (Canvas.Handle = Printer.Canvas.Handle);
  4739. DocMode := dmPrinting;
  4740. p := FPages[Index];
  4741. with p^ do
  4742. if Visible then
  4743. begin
  4744. if Page = nil then
  4745. ObjectsToPage(Index);
  4746. sx := (DrawRect.Right - DrawRect.Left) / PrnInfo.PgW;
  4747. sy := (DrawRect.Bottom - DrawRect.Top) / PrnInfo.PgH;
  4748. h := Canvas.Handle;
  4749. for i := 0 to Page.Objects.Count - 1 do
  4750. begin
  4751. t := Page.Objects[i];
  4752. v := True;
  4753. if not IsPrinting then
  4754. with t, DrawRect do
  4755. v := RectVisible(h, Rect(Round(x * sx) + Left - 10,
  4756. Round(y * sy) + Top - 10,
  4757. Round((x + dx) * sx) + Left + 10,
  4758. Round((y + dy) * sy) + Top + 10));
  4759. if v then
  4760. begin
  4761. t.ScaleX := sx; t.ScaleY := sy;
  4762. t.OffsX := DrawRect.Left; t.OffsY := DrawRect.Top;
  4763. t.IsPrinting := IsPrinting;
  4764. t.Draw(Canvas);
  4765. end;
  4766. end;
  4767. end
  4768. else
  4769. begin
  4770. Page.Free;
  4771. Page := nil;
  4772. end;
  4773. end;
  4774. procedure TfrEMFPages.ExportData(Index: Integer);
  4775. var
  4776. p: PfrPageInfo;
  4777. b: Byte;
  4778. t: TfrView;
  4779. s: String;
  4780. begin
  4781. p := FPages[Index];
  4782. with p^ do
  4783. begin
  4784. Stream.Position := 0;
  4785. Stream.Read(frVersion, 1);
  4786. while Stream.Position < Stream.Size do
  4787. begin
  4788. Stream.Read(b, 1);
  4789. if b = gtAddIn then
  4790. s := ReadString(Stream) else
  4791. s := '';
  4792. t := frCreateObject(b, s);
  4793. t.StreamMode := smPrinting;
  4794. t.LoadFromStream(Stream);
  4795. t.ExportData;
  4796. t.Free;
  4797. end;
  4798. end;
  4799. end;
  4800. procedure TfrEMFPages.ObjectsToPage(Index: Integer);
  4801. var
  4802. p: PfrPageInfo;
  4803. b: Byte;
  4804. t: TfrView;
  4805. s: String;
  4806. begin
  4807. p := FPages[Index];
  4808. with p^ do
  4809. begin
  4810. if Page <> nil then
  4811. Page.Free;
  4812. Page := TfrPage.Create(pgSize, pgWidth, pgHeight, pgOr);
  4813. Stream.Position := 0;
  4814. Stream.Read(frVersion, 1);
  4815. while Stream.Position < Stream.Size do
  4816. begin
  4817. Stream.Read(b, 1);
  4818. if b = gtAddIn then
  4819. s := ReadString(Stream) else
  4820. s := '';
  4821. t := frCreateObject(b, s);
  4822. t.StreamMode := smPrinting;
  4823. t.LoadFromStream(Stream);
  4824. t.StreamMode := smDesigning;
  4825. Page.Objects.Add(t);
  4826. end;
  4827. end;
  4828. end;
  4829. procedure TfrEMFPages.PageToObjects(Index: Integer);
  4830. var
  4831. i: Integer;
  4832. p: PfrPageInfo;
  4833. t: TfrView;
  4834. begin
  4835. p := FPages[Index];
  4836. with p^ do
  4837. begin
  4838. Stream.Clear;
  4839. frVersion := frCurrentVersion;
  4840. Stream.Write(frVersion, 1);
  4841. for i := 0 to Page.Objects.Count - 1 do
  4842. begin
  4843. t := Page.Objects[i];
  4844. t.StreamMode := smPrinting;
  4845. Stream.Write(t.Typ, 1);
  4846. if t.Typ = gtAddIn then
  4847. frWriteString(Stream, t.ClassName);
  4848. t.Memo1.Assign(t.Memo);
  4849. t.SaveToStream(Stream);
  4850. end;
  4851. end;
  4852. end;
  4853. procedure TfrEMFPages.Insert(Index: Integer; APage: TfrPage);
  4854. var
  4855. p: PfrPageInfo;
  4856. begin
  4857. GetMem(p, SizeOf(TfrPageInfo));
  4858. FillChar(p^, SizeOf(TfrPageInfo), 0);
  4859. if Index >= FPages.Count then
  4860. FPages.Add(p) else
  4861. FPages.Insert(Index, p);
  4862. with p^ do
  4863. begin
  4864. Stream := TMemoryStream.Create;
  4865. frVersion := frCurrentVersion;
  4866. Stream.Write(frVersion, 1);
  4867. pgSize := APage.pgSize;
  4868. pgWidth := APage.pgWidth;
  4869. pgHeight := APage.pgHeight;
  4870. pgOr := APage.pgOr;
  4871. pgMargins := APage.UseMargins;
  4872. PrnInfo := APage.PrnInfo;
  4873. end;
  4874. end;
  4875. procedure TfrEMFPages.Add(APage: TfrPage);
  4876. begin
  4877. Insert(FPages.Count, APage);
  4878. if (CurReport <> nil) and Assigned(CurReport.FOnBeginPage) then
  4879. CurReport.FOnBeginPage(PageNo);
  4880. if (MasterReport <> CurReport) and (MasterReport <> nil) and
  4881. Assigned(MasterReport.FOnBeginPage) then
  4882. MasterReport.FOnBeginPage(PageNo);
  4883. end;
  4884. procedure TfrEMFPages.Delete(Index: Integer);
  4885. begin
  4886. if Pages[Index]^.Page <> nil then Pages[Index]^.Page.Free;
  4887. if Pages[Index]^.Stream <> nil then Pages[Index]^.Stream.Free;
  4888. FreeMem(Pages[Index], SizeOf(TfrPageInfo));
  4889. FPages.Delete(Index);
  4890. end;
  4891. procedure TfrEMFPages.LoadFromStream(AStream: TStream);
  4892. var
  4893. i, o, c: Integer;
  4894. b, compr: Byte;
  4895. p: PfrPageInfo;
  4896. s: TMemoryStream;
  4897. procedure ReadVersion22;
  4898. var
  4899. Pict: TfrPictureView;
  4900. begin
  4901. frReadMemo22(AStream, SMemo);
  4902. if SMemo.Count > 0 then
  4903. Parent.SetPrinterTo(SMemo[0]);
  4904. AStream.Read(c, 4);
  4905. i := 0;
  4906. repeat
  4907. AStream.Read(o, 4);
  4908. GetMem(p, SizeOf(TfrPageInfo));
  4909. FillChar(p^, SizeOf(TfrPageInfo), 0);
  4910. FPages.Add(p);
  4911. with p^ do
  4912. begin
  4913. AStream.Read(pgSize, 2);
  4914. AStream.Read(pgWidth, 4);
  4915. AStream.Read(pgHeight, 4);
  4916. AStream.Read(b, 1);
  4917. pgOr := TPrinterOrientation(b);
  4918. AStream.Read(b, 1);
  4919. pgMargins := Boolean(b);
  4920. Prn.SetPrinterInfo(pgSize, pgWidth, pgHeight, pgOr);
  4921. Prn.FillPrnInfo(PrnInfo);
  4922. Pict := TfrPictureView.Create;
  4923. Pict.SetBounds(0, 0, PrnInfo.PgW, PrnInfo.PgH);
  4924. Pict.Picture.Metafile.LoadFromStream(AStream);
  4925. Stream := TMemoryStream.Create;
  4926. b := frCurrentVersion;
  4927. Stream.Write(b, 1);
  4928. Pict.StreamMode := smPrinting;
  4929. Stream.Write(Pict.Typ, 1);
  4930. Pict.SaveToStream(Stream);
  4931. Pict.Free;
  4932. end;
  4933. AStream.Seek(o, soFromBeginning);
  4934. Inc(i);
  4935. until i >= c;
  4936. end;
  4937. begin
  4938. Clear;
  4939. AStream.Read(compr, 1);
  4940. if not (compr in [0, 1, 255]) then
  4941. begin
  4942. AStream.Seek(0, soFromBeginning);
  4943. ReadVersion22;
  4944. Exit;
  4945. end;
  4946. Parent.SetPrinterTo(frReadString(AStream));
  4947. AStream.Read(c, 4);
  4948. i := 0;
  4949. repeat
  4950. AStream.Read(o, 4);
  4951. GetMem(p, SizeOf(TfrPageInfo));
  4952. FillChar(p^, SizeOf(TfrPageInfo), #0);
  4953. FPages.Add(p);
  4954. with p^ do
  4955. begin
  4956. AStream.Read(pgSize, 2);
  4957. AStream.Read(pgWidth, 4);
  4958. AStream.Read(pgHeight, 4);
  4959. AStream.Read(b, 1);
  4960. pgOr := TPrinterOrientation(b);
  4961. AStream.Read(b, 1);
  4962. pgMargins := Boolean(b);
  4963. if compr <> 0 then
  4964. begin
  4965. s := TMemoryStream.Create;
  4966. s.CopyFrom(AStream, o - AStream.Position);
  4967. Stream := TMemoryStream.Create;
  4968. frCompressor.DeCompress(s, Stream);
  4969. s.Free;
  4970. end
  4971. else
  4972. begin
  4973. Stream := TMemoryStream.Create;
  4974. Stream.CopyFrom(AStream, o - AStream.Position);
  4975. end;
  4976. Prn.SetPrinterInfo(pgSize, pgWidth, pgHeight, pgOr);
  4977. Prn.FillPrnInfo(PrnInfo);
  4978. end;
  4979. AStream.Seek(o, soFromBeginning);
  4980. Inc(i);
  4981. until i >= c;
  4982. end;
  4983. procedure TfrEMFPages.SaveToStream(AStream: TStream);
  4984. var
  4985. i, o, n: Integer;
  4986. b: Byte;
  4987. s: TMemoryStream;
  4988. begin
  4989. b := Byte(frCompressor.Enabled);
  4990. AStream.Write(b, 1);
  4991. frWriteString(AStream, Prn.Printers[Prn.PrinterIndex]);
  4992. n := Count;
  4993. AStream.Write(n, 4);
  4994. i := 0;
  4995. repeat
  4996. o := AStream.Position;
  4997. AStream.Write(o, 4); // dummy write
  4998. with Pages[i]^ do
  4999. begin
  5000. AStream.Write(pgSize, 2);
  5001. AStream.Write(pgWidth, 4);
  5002. AStream.Write(pgHeight, 4);
  5003. b := Byte(pgOr);
  5004. AStream.Write(b, 1);
  5005. b := Byte(pgMargins);
  5006. AStream.Write(b, 1);
  5007. Stream.Position := 0;
  5008. if frCompressor.Enabled then
  5009. begin
  5010. s := TMemoryStream.Create;
  5011. frCompressor.Compress(Stream, s);
  5012. AStream.CopyFrom(s, s.Size);
  5013. s.Free;
  5014. end
  5015. else
  5016. AStream.CopyFrom(Stream, Stream.Size);
  5017. end;
  5018. n := AStream.Position;
  5019. AStream.Seek(o, soFromBeginning);
  5020. AStream.Write(n, 4);
  5021. AStream.Seek(0, soFromEnd);
  5022. Inc(i);
  5023. until i >= Count;
  5024. end;
  5025. {-----------------------------------------------------------------------}
  5026. constructor TfrValues.Create;
  5027. begin
  5028. inherited Create;
  5029. FItems := TStringList.Create;
  5030. end;
  5031. destructor TfrValues.Destroy;
  5032. begin
  5033. Clear;
  5034. FItems.Free;
  5035. inherited Destroy;
  5036. end;
  5037. procedure TfrValues.WriteBinaryData(Stream: TStream);
  5038. var
  5039. i, n: Integer;
  5040. procedure WriteStr(s: String);
  5041. var
  5042. n: Byte;
  5043. begin
  5044. n := Length(s);
  5045. Stream.Write(n, 1);
  5046. Stream.Write(s[1], n);
  5047. end;
  5048. begin
  5049. with Stream do
  5050. begin
  5051. n := FItems.Count;
  5052. WriteBuffer(n, SizeOf(n));
  5053. for i := 0 to n - 1 do
  5054. with Objects[i] do
  5055. begin
  5056. WriteBuffer(Typ, SizeOf(Typ));
  5057. WriteBuffer(OtherKind, SizeOf(OtherKind));
  5058. WriteStr(DataSet);
  5059. WriteStr(Field);
  5060. WriteStr(FItems[i]);
  5061. end;
  5062. end;
  5063. end;
  5064. procedure TfrValues.ReadBinaryData(Stream: TStream);
  5065. var
  5066. i, j, n: Integer;
  5067. function ReadStr: String;
  5068. var
  5069. n: Byte;
  5070. begin
  5071. Stream.Read(n, 1);
  5072. SetLength(Result, n);
  5073. Stream.Read(Result[1], n);
  5074. end;
  5075. begin
  5076. Clear;
  5077. FItems.Sorted := False;
  5078. with Stream do
  5079. begin
  5080. ReadBuffer(n, SizeOf(n));
  5081. for i := 0 to n - 1 do
  5082. begin
  5083. j := AddValue;
  5084. with Objects[j] do
  5085. begin
  5086. ReadBuffer(Typ, SizeOf(Typ));
  5087. ReadBuffer(OtherKind, SizeOf(OtherKind));
  5088. DataSet := ReadStr;
  5089. Field := ReadStr;
  5090. FItems[j] := ReadStr;
  5091. end;
  5092. end;
  5093. end;
  5094. end;
  5095. function TfrValues.GetValue(Index: Integer): TfrValue;
  5096. begin
  5097. Result := TfrValue(FItems.Objects[Index]);
  5098. end;
  5099. function TfrValues.AddValue: Integer;
  5100. begin
  5101. Result := FItems.AddObject('', TfrValue.Create);
  5102. end;
  5103. procedure TfrValues.Clear;
  5104. var
  5105. i: Integer;
  5106. begin
  5107. for i := 0 to FItems.Count - 1 do
  5108. TfrValue(FItems.Objects[i]).Free;
  5109. FItems.Clear;
  5110. end;
  5111. function TfrValues.FindVariable(const s: String): TfrValue;
  5112. var
  5113. i: Integer;
  5114. begin
  5115. Result := nil;
  5116. i := FItems.IndexOf(s);
  5117. if i <> -1 then
  5118. Result := Objects[i];
  5119. end;
  5120. {----------------------------------------------------------------------------}
  5121. constructor TfrReport.Create(AOwner: TComponent);
  5122. begin
  5123. inherited Create(AOwner);
  5124. FPages := TfrPages.Create(Self);
  5125. FEMFPages := TfrEMFPages.Create(Self);
  5126. FVars := TStringList.Create;
  5127. FVal := TfrValues.Create;
  5128. FShowProgress := True;
  5129. FModalPreview := True;
  5130. FModifyPrepared := True;
  5131. FPreviewButtons := [pbZoom, pbLoad, pbSave, pbPrint, pbFind, pbHelp, pbExit];
  5132. FInitialZoom := pzDefault;
  5133. FileName := LoadStr(SUntitled);
  5134. end;
  5135. destructor TfrReport.Destroy;
  5136. begin
  5137. FVal.Free;
  5138. FVars.Free;
  5139. FEMFPages.Free;
  5140. FEMFPages := nil;
  5141. FPages.Free;
  5142. inherited Destroy;
  5143. end;
  5144. procedure TfrReport.DefineProperties(Filer: TFiler);
  5145. begin
  5146. inherited DefineProperties(Filer);
  5147. Filer.DefineBinaryProperty('ReportForm', ReadBinaryData, WriteBinaryData, True);
  5148. end;
  5149. procedure TfrReport.WriteBinaryData(Stream: TStream);
  5150. var
  5151. n: Integer;
  5152. Stream1: TMemoryStream;
  5153. begin
  5154. n := frCurrentVersion;
  5155. Stream.Write(n, 4);
  5156. if FStoreInDFM then
  5157. begin
  5158. Stream1 := TMemoryStream.Create;
  5159. SaveToStream(Stream1);
  5160. Stream1.Position := 0;
  5161. n := Stream1.Size;
  5162. Stream.Write(n, 4);
  5163. Stream.CopyFrom(Stream1, n);
  5164. Stream1.Free;
  5165. end;
  5166. end;
  5167. procedure TfrReport.ReadBinaryData(Stream: TStream);
  5168. var
  5169. n: Integer;
  5170. Stream1: TMemoryStream;
  5171. begin
  5172. Stream.Read(n, 4); // version
  5173. if FStoreInDFM then
  5174. begin
  5175. Stream.Read(n, 4);
  5176. Stream1 := TMemoryStream.Create;
  5177. Stream1.CopyFrom(Stream, n);
  5178. Stream1.Position := 0;
  5179. LoadFromStream(Stream1);
  5180. Stream1.Free;
  5181. end;
  5182. end;
  5183. procedure TfrReport.Notification(AComponent: TComponent; Operation: TOperation);
  5184. begin
  5185. inherited Notification(AComponent, Operation);
  5186. if (Operation = opRemove) and (AComponent = Dataset) then
  5187. Dataset := nil;
  5188. if (Operation = opRemove) and (AComponent = Preview) then
  5189. Preview := nil;
  5190. end;
  5191. // report building events
  5192. procedure TfrReport.InternalOnProgress(Percent: Integer);
  5193. begin
  5194. if Assigned(FOnProgress) then
  5195. FOnProgress(Percent)
  5196. else if FShowProgress then
  5197. with frProgressForm do
  5198. begin
  5199. if (MasterReport.DoublePass and MasterReport.FinalPass) or
  5200. (FCurrentFilter <> nil) then
  5201. Label1.Caption := FirstCaption + ' ' + IntToStr(Percent) + ' ' +
  5202. LoadStr(SFrom) + ' ' + IntToStr(SavedAllPages)
  5203. else
  5204. Label1.Caption := FirstCaption + ' ' + IntToStr(Percent);
  5205. Application.ProcessMessages;
  5206. end;
  5207. end;
  5208. procedure TfrReport.InternalOnGetValue(ParName: String; var ParValue: String);
  5209. var
  5210. i, j, Format: Integer;
  5211. FormatStr: String;
  5212. begin
  5213. SubValue := '';
  5214. Format := CurView.Format;
  5215. FormatStr := CurView.FormatStr;
  5216. i := Pos(' #', ParName);
  5217. if i <> 0 then
  5218. begin
  5219. FormatStr := Copy(ParName, i + 2, Length(ParName) - i - 1);
  5220. ParName := Copy(ParName, 1, i - 1);
  5221. if FormatStr[1] in ['0'..'9', 'N', 'n'] then
  5222. begin
  5223. if FormatStr[1] in ['0'..'9'] then
  5224. FormatStr := 'N' + FormatStr;
  5225. Format := $01000000;
  5226. if FormatStr[2] in ['0'..'9'] then
  5227. Format := Format + $00010000;
  5228. i := Length(FormatStr);
  5229. while i > 1 do
  5230. begin
  5231. if FormatStr[i] in ['.', ',', '-'] then
  5232. begin
  5233. Format := Format + Ord(FormatStr[i]);
  5234. FormatStr[i] := '.';
  5235. if FormatStr[2] in ['0'..'9'] then
  5236. begin
  5237. Inc(i);
  5238. j := i;
  5239. while (i <= Length(FormatStr)) and (FormatStr[i] in ['0'..'9']) do
  5240. Inc(i);
  5241. Format := Format + 256 * StrToInt(Copy(FormatStr, j, i - j));
  5242. end;
  5243. break;
  5244. end;
  5245. Dec(i);
  5246. end;
  5247. if not (FormatStr[2] in ['0'..'9']) then
  5248. begin
  5249. FormatStr := Copy(FormatStr, 2, 255);
  5250. Format := Format + $00040000;
  5251. end;
  5252. end
  5253. else if FormatStr[1] in ['D', 'T', 'd', 't'] then
  5254. begin
  5255. Format := $02040000;
  5256. FormatStr := Copy(FormatStr, 2, 255);
  5257. end
  5258. else if FormatStr[1] in ['B', 'b'] then
  5259. begin
  5260. Format := $04040000;
  5261. FormatStr := Copy(FormatStr, 2, 255);
  5262. end;
  5263. end;
  5264. CurVariable := ParName;
  5265. CurValue := 0;
  5266. GetVariableValue(ParName, CurValue);
  5267. ParValue := FormatValue(CurValue, Format, FormatStr);
  5268. end;
  5269. procedure TfrReport.InternalOnEnterRect(Memo: TStringList; View: TfrView);
  5270. begin
  5271. with View do
  5272. if (FDataSet <> nil) and frIsBlob(TfrTField(FDataSet.FindField(FField))) then
  5273. GetBlob(TfrTField(FDataSet.FindField(FField)));
  5274. if Assigned(FOnEnterRect) then FOnEnterRect(Memo, View);
  5275. end;
  5276. procedure TfrReport.InternalOnExportData(View: TfrView);
  5277. begin
  5278. FCurrentFilter.OnData(View.x, View.y, View);
  5279. end;
  5280. procedure TfrReport.InternalOnExportText(x, y: Integer; const text: String;
  5281. View: TfrView);
  5282. begin
  5283. FCurrentFilter.OnText(x, y, text, View);
  5284. end;
  5285. procedure TfrReport.InternalOnBeginColumn(Band: TfrBand);
  5286. begin
  5287. if Assigned(FOnBeginColumn) then FOnBeginColumn(Band);
  5288. end;
  5289. procedure TfrReport.InternalOnPrintColumn(ColNo: Integer; var ColWidth: Integer);
  5290. begin
  5291. if Assigned(FOnPrintColumn) then FOnPrintColumn(ColNo, ColWidth);
  5292. end;
  5293. function TfrReport.FormatValue(V: Variant; Format: Integer;
  5294. const FormatStr: String): String;
  5295. var
  5296. f1, f2: Integer;
  5297. c: Char;
  5298. s: String;
  5299. begin
  5300. if (TVarData(v).VType = varEmpty) or (v = Null) then
  5301. begin
  5302. Result := ' ';
  5303. Exit;
  5304. end;
  5305. c := DecimalSeparator;
  5306. f1 := (Format div $01000000) and $0F;
  5307. f2 := (Format div $00010000) and $FF;
  5308. try
  5309. case f1 of
  5310. 0: Result := v;
  5311. 1:
  5312. begin
  5313. DecimalSeparator := Chr(Format and $FF);
  5314. case f2 of
  5315. 0: Result := FormatFloat('###.##', v);
  5316. 1: Result := FloatToStrF(v, ffFixed, 15, (Format div $0100) and $FF);
  5317. 2: Result := FormatFloat('#,###.##', v);
  5318. 3: Result := FloatToStrF(v, ffNumber, 15, (Format div $0100) and $FF);
  5319. 4: Result := FormatFloat(FormatStr, v);
  5320. end;
  5321. end;
  5322. 2: if f2 = 4 then
  5323. Result := FormatDateTime(FormatStr, v) else
  5324. Result := FormatDateTime(frDateFormats[f2], v);
  5325. 3: if f2 = 4 then
  5326. Result := FormatDateTime(FormatStr, v) else
  5327. Result := FormatDateTime(frTimeFormats[f2], v);
  5328. 4:
  5329. begin
  5330. if f2 = 4 then
  5331. s := FormatStr else
  5332. s := BoolStr[f2];
  5333. if Integer(v) = 0 then
  5334. Result := Copy(s, 1, Pos(';', s) - 1) else
  5335. Result := Copy(s, Pos(';', s) + 1, 255);
  5336. end;
  5337. end;
  5338. except
  5339. on exception do Result := v;
  5340. end;
  5341. DecimalSeparator := c;
  5342. end;
  5343. procedure TfrReport.GetVariableValue(const s: String; var v: Variant);
  5344. var
  5345. Value: TfrValue;
  5346. D: TfrTDataSet;
  5347. F: TfrTField;
  5348. function MasterBand: TfrBand;
  5349. begin
  5350. Result := CurBand;
  5351. if Result.DataSet = nil then
  5352. while Result.Prev <> nil do
  5353. Result := Result.Prev;
  5354. end;
  5355. begin
  5356. TVarData(v).VType := varEmpty;
  5357. if Assigned(FOnGetValue) then FOnGetValue(s, v);
  5358. if TVarData(v).VType = varEmpty then
  5359. begin
  5360. Value := Values.FindVariable(s);
  5361. if Value <> nil then
  5362. with Value do
  5363. case Typ of
  5364. vtNotAssigned:
  5365. v := '';
  5366. vtDBField:
  5367. begin
  5368. F := TfrTField(DSet.FindField(Field));
  5369. if not F.DataSet.Active then
  5370. F.DataSet.Open;
  5371. if Assigned(F.OnGetText) then
  5372. v := F.DisplayText else
  5373. v := F.AsVariant;
  5374. end;
  5375. vtFRVar:
  5376. v := frParser.Calc(Field);
  5377. vtOther:
  5378. if OtherKind = 1 then
  5379. v := frParser.Calc(Field) else
  5380. v := frParser.Calc(frSpecFuncs[OtherKind]);
  5381. end
  5382. else
  5383. begin
  5384. D := GetDefaultDataSet;
  5385. frGetDataSetAndField(s, D, F);
  5386. if F <> nil then
  5387. begin
  5388. if not F.DataSet.Active then
  5389. F.DataSet.Open;
  5390. if Assigned(F.OnGetText) then
  5391. v := F.DisplayText else
  5392. v := F.AsVariant
  5393. end
  5394. else if s = 'VALUE' then
  5395. v := CurValue
  5396. else if s = frSpecFuncs[0] then
  5397. v := PageNo + 1
  5398. else if s = frSpecFuncs[2] then
  5399. v := CurDate
  5400. else if s = frSpecFuncs[3] then
  5401. v := CurTime
  5402. else if s = frSpecFuncs[4] then
  5403. v := MasterBand.Positions[psLocal]
  5404. else if s = frSpecFuncs[5] then
  5405. v := MasterBand.Positions[psGlobal]
  5406. else if s = frSpecFuncs[6] then
  5407. v := CurPage.ColPos
  5408. else if s = frSpecFuncs[7] then
  5409. v := CurPage.CurPos
  5410. else if s = frSpecFuncs[8] then
  5411. v := SavedAllPages
  5412. else
  5413. begin
  5414. if frVariables.IndexOf(s) <> -1 then
  5415. begin
  5416. v := frVariables[s];
  5417. Exit;
  5418. end;
  5419. if s <> SubValue then
  5420. begin
  5421. SubValue := s;
  5422. v := frParser.Calc(s);
  5423. SubValue := '';
  5424. end
  5425. else raise(EParserError.Create('Undefined symbol "' + SubValue + '"'));
  5426. end;
  5427. end;
  5428. end;
  5429. end;
  5430. procedure TfrReport.OnGetParsFunction(const name: String; p1, p2, p3: Variant;
  5431. var val: String);
  5432. var
  5433. i: Integer;
  5434. begin
  5435. val := '0';
  5436. for i := 0 to frFunctionsCount - 1 do
  5437. if frFunctions[i].FunctionLibrary.OnFunction(name, p1, p2, p3, val) then
  5438. exit;
  5439. if AggrBand.Visible then
  5440. if Assigned(FOnFunction) then FOnFunction(name, p1, p2, p3, val);
  5441. end;
  5442. // load/save methods
  5443. procedure TfrReport.LoadFromStream(Stream: TStream);
  5444. begin
  5445. CurReport := Self;
  5446. Stream.Read(frVersion, 1);
  5447. if frVersion < 21 then
  5448. begin
  5449. frVersion := 21;
  5450. Stream.Position := 0;
  5451. end;
  5452. if frVersion <= frCurrentVersion then
  5453. try
  5454. {$IFDEF FREEREP2217READ}
  5455. if FRE_COMPATIBLE_READ and (frVersion = 23) then
  5456. frVersion := 22;
  5457. {$ENDIF}
  5458. Pages.LoadFromStream(Stream);
  5459. except
  5460. Pages.Clear;
  5461. Pages.Add;
  5462. MessageBox(0, PChar(LoadStr(SFRFError)), PChar(LoadStr(SError)),
  5463. mb_Ok + mb_IconError);
  5464. end
  5465. else
  5466. MessageBox(0, PChar(SFRFError), PChar(LoadStr(SError)),
  5467. mb_Ok + mb_IconError);
  5468. end;
  5469. procedure TfrReport.SaveToStream(Stream: TStream);
  5470. begin
  5471. CurReport := Self;
  5472. if FR3Stream then
  5473. begin
  5474. Pages.SaveToStream(Stream);
  5475. Exit;
  5476. end;
  5477. frVersion := frCurrentVersion;
  5478. Stream.Write(frVersion, 1);
  5479. Pages.SaveToStream(Stream);
  5480. end;
  5481. procedure TfrReport.LoadFromFile(FName: String);
  5482. var
  5483. Stream: TFileStream;
  5484. begin
  5485. Stream := TFileStream.Create(FName, fmOpenRead);
  5486. LoadFromStream(Stream);
  5487. Stream.Free;
  5488. FileName := FName;
  5489. end;
  5490. procedure TfrReport.SaveToFile(FName: String);
  5491. var
  5492. Stream: TFileStream;
  5493. begin
  5494. Stream := TFileStream.Create(FName, fmCreate);
  5495. SaveToStream(Stream);
  5496. Stream.Free;
  5497. end;
  5498. procedure TfrReport.SaveToFR3File(FName: String);
  5499. var
  5500. Stream: TFileStream;
  5501. begin
  5502. Stream := TFileStream.Create(ChangeFileExt(FName, '.fr3'), fmCreate);
  5503. try
  5504. FR3Stream := True;
  5505. SaveToStream(Stream);
  5506. finally
  5507. FR3Stream := False;
  5508. Stream.Free;
  5509. end;
  5510. end;
  5511. {$IFDEF IBO}
  5512. procedure TfrReport.LoadFromDB(Table: TIB_DataSet; DocN: Integer);
  5513. {$ELSE}
  5514. procedure TfrReport.LoadFromDB(Table: TDataSet; DocN: Integer);
  5515. {$ENDIF}
  5516. var
  5517. Stream: TMemoryStream;
  5518. begin
  5519. Table.First;
  5520. while not Table.Eof do
  5521. begin
  5522. if Table.Fields[0].AsInteger = DocN then
  5523. begin
  5524. Stream := TMemoryStream.Create;
  5525. {$IFDEF IBO}
  5526. TfrTBlobField(Table.Fields[1]).AssignTo(Stream);
  5527. {$ELSE}
  5528. TfrTBlobField(Table.Fields[1]).SaveToStream(Stream);
  5529. {$ENDIF}
  5530. Stream.Position := 0;
  5531. LoadFromStream(Stream);
  5532. Stream.Free;
  5533. Exit;
  5534. end;
  5535. Table.Next;
  5536. end;
  5537. end;
  5538. {$IFDEF IBO}
  5539. procedure TfrReport.SaveToDB(Table: TIB_DataSet; DocN: Integer);
  5540. {$ELSE}
  5541. procedure TfrReport.SaveToDB(Table: TDataSet; DocN: Integer);
  5542. {$ENDIF}
  5543. var
  5544. Stream: TMemoryStream;
  5545. Found: Boolean;
  5546. begin
  5547. Found := False;
  5548. Table.First;
  5549. while not Table.Eof do
  5550. begin
  5551. if Table.Fields[0].AsInteger = DocN then
  5552. begin
  5553. Found := True;
  5554. break;
  5555. end;
  5556. Table.Next;
  5557. end;
  5558. if Found then
  5559. Table.Edit else
  5560. Table.Append;
  5561. Table.Fields[0].AsInteger := DocN;
  5562. Stream := TMemoryStream.Create;
  5563. SaveToStream(Stream);
  5564. Stream.Position := 0;
  5565. {$IFDEF IBO}
  5566. TfrTBlobField(Table.Fields[1]).Assign(Stream);
  5567. {$ELSE}
  5568. TfrTBlobField(Table.Fields[1]).LoadFromStream(Stream);
  5569. {$ENDIF}
  5570. Stream.Free;
  5571. Table.Post;
  5572. end;
  5573. procedure TfrReport.LoadPreparedReport(FName: String);
  5574. var
  5575. Stream: TFileStream;
  5576. begin
  5577. Stream := TFileStream.Create(FName, fmOpenRead);
  5578. EMFPages.LoadFromStream(Stream);
  5579. Stream.Free;
  5580. CanRebuild := False;
  5581. end;
  5582. procedure TfrReport.SavePreparedReport(FName: String);
  5583. var
  5584. Stream: TFileStream;
  5585. begin
  5586. Stream := TFileStream.Create(FName, fmCreate);
  5587. EMFPages.SaveToStream(Stream);
  5588. Stream.Free;
  5589. end;
  5590. procedure TfrReport.LoadTemplate(FName: String; comm: TStrings;
  5591. Bmp: TBitmap; Load: Boolean);
  5592. var
  5593. Stream: TFileStream;
  5594. b: Byte;
  5595. fb: TBitmap;
  5596. fm: TStringList;
  5597. pos: Integer;
  5598. begin
  5599. fb := TBitmap.Create;
  5600. fm := TStringList.Create;
  5601. Stream := TFileStream.Create(FName, fmOpenRead);
  5602. if Load then
  5603. begin
  5604. ReadMemo(Stream, fm);
  5605. Stream.Read(pos, 4);
  5606. Stream.Read(b, 1);
  5607. if b <> 0 then
  5608. fb.LoadFromStream(Stream);
  5609. Stream.Position := pos;
  5610. Pages.LoadFromStream(Stream);
  5611. end
  5612. else
  5613. begin
  5614. ReadMemo(Stream, Comm);
  5615. Stream.Read(pos, 4);
  5616. Bmp.Assign(nil);
  5617. Stream.Read(b, 1);
  5618. if b <> 0 then
  5619. Bmp.LoadFromStream(Stream);
  5620. end;
  5621. fm.Free; fb.Free;
  5622. Stream.Free;
  5623. end;
  5624. procedure TfrReport.SaveTemplate(FName: String; Comm: TStrings; Bmp: TBitmap);
  5625. var
  5626. Stream: TFileStream;
  5627. b: Byte;
  5628. pos, lpos: Integer;
  5629. begin
  5630. Stream := TFileStream.Create(FName, fmCreate);
  5631. frWriteMemo(Stream, Comm);
  5632. b := 0;
  5633. pos := Stream.Position;
  5634. lpos := 0;
  5635. Stream.Write(lpos, 4);
  5636. if Bmp.Empty then
  5637. Stream.Write(b, 1)
  5638. else
  5639. begin
  5640. b := 1;
  5641. Stream.Write(b, 1);
  5642. Bmp.SaveToStream(Stream);
  5643. end;
  5644. lpos := Stream.Position;
  5645. Stream.Position := pos;
  5646. Stream.Write(lpos, 4);
  5647. Stream.Position := lpos;
  5648. Pages.SaveToStream(Stream);
  5649. Stream.Free;
  5650. end;
  5651. // report manipulation methods
  5652. procedure TfrReport.DesignReport;
  5653. var
  5654. HF: String;
  5655. begin
  5656. if Pages.Count = 0 then Pages.Add;
  5657. CurReport := Self;
  5658. HF := Application.HelpFile;
  5659. Application.HelpFile := 'FRuser.hlp';
  5660. if frDesigner <> nil then
  5661. frDesigner.ShowModal;
  5662. Application.HelpFile := HF;
  5663. end;
  5664. var
  5665. FirstPassTerminated, FirstTime: Boolean;
  5666. procedure TfrReport.BuildBeforeModal(Sender: TObject);
  5667. begin
  5668. DoBuildReport;
  5669. if FinalPass then
  5670. if Terminated then
  5671. frProgressForm.ModalResult := mrCancel else
  5672. frProgressForm.ModalResult := mrOk
  5673. else
  5674. begin
  5675. FirstPassTerminated := Terminated;
  5676. SavedAllPages := EMFPages.Count;
  5677. DoublePass := False;
  5678. FirstTime := False;
  5679. DoPrepareReport; // do final pass
  5680. DoublePass := True;
  5681. end;
  5682. end;
  5683. function TfrReport.PrepareReport: Boolean;
  5684. var
  5685. ParamOk: Boolean;
  5686. begin
  5687. DocMode := dmPrinting;
  5688. CurDate := Date; CurTime := Time;
  5689. MasterReport := Self;
  5690. CurReport := Self;
  5691. Values.Items.Sorted := True;
  5692. frParser.OnGetValue := GetVariableValue;
  5693. frParser.OnFunction := OnGetParsFunction;
  5694. if Assigned(FOnBeginDoc) then FOnBeginDoc;
  5695. Result := False;
  5696. ParamOk := True;
  5697. if frDataManager <> nil then
  5698. begin
  5699. FillQueryParams;
  5700. ParamOk := frDataManager.ShowParamsDialog;
  5701. end;
  5702. if ParamOk then
  5703. Result := DoPrepareReport;
  5704. FinalPass := False;
  5705. if frDataManager <> nil then
  5706. frDataManager.AfterParamsDialog;
  5707. if Assigned(FOnEndDoc) then FOnEndDoc;
  5708. end;
  5709. function TfrReport.DoPrepareReport: Boolean;
  5710. var
  5711. s: String;
  5712. begin
  5713. Result := True;
  5714. Terminated := False;
  5715. Append := False;
  5716. DisableDrawing := False;
  5717. FinalPass := True;
  5718. FirstTime := True;
  5719. PageNo := 0;
  5720. EMFPages.Clear;
  5721. s := LoadStr(SReportPreparing);
  5722. if DoublePass then
  5723. begin
  5724. DisableDrawing := True;
  5725. FinalPass := False;
  5726. if not Assigned(FOnProgress) and FShowProgress then
  5727. with frProgressForm do
  5728. begin
  5729. if Title = '' then
  5730. Caption := s else
  5731. Caption := s + ' - ' + Title;
  5732. FirstCaption := LoadStr(SFirstPass);
  5733. Label1.Caption := FirstCaption + ' 1';
  5734. OnBeforeModal := BuildBeforeModal;
  5735. Show_Modal(Self);
  5736. end
  5737. else
  5738. BuildBeforeModal(nil);
  5739. Exit;
  5740. end;
  5741. if not Assigned(FOnProgress) and FShowProgress then
  5742. with frProgressForm do
  5743. begin
  5744. if Title = '' then
  5745. Caption := s else
  5746. Caption := s + ' - ' + Title;
  5747. FirstCaption := LoadStr(SPagePreparing);
  5748. Label1.Caption := FirstCaption + ' 1';
  5749. OnBeforeModal := BuildBeforeModal;
  5750. if Visible then
  5751. begin
  5752. if not FirstPassTerminated then DoublePass := True;
  5753. BuildBeforeModal(nil);
  5754. end
  5755. else
  5756. begin
  5757. SavedAllPages := 0;
  5758. if Show_Modal(Self) = mrCancel then
  5759. Result := False;
  5760. end;
  5761. end
  5762. else
  5763. BuildBeforeModal(nil);
  5764. Terminated := False;
  5765. end;
  5766. var
  5767. ExportStream: TFileStream;
  5768. procedure TfrReport.ExportBeforeModal(Sender: TObject);
  5769. var
  5770. i: Integer;
  5771. begin
  5772. Application.ProcessMessages;
  5773. for i := 0 to EMFPages.Count - 1 do
  5774. begin
  5775. FCurrentFilter.OnBeginPage;
  5776. EMFPages.ExportData(i);
  5777. InternalOnProgress(i + 1);
  5778. Application.ProcessMessages;
  5779. FCurrentFilter.OnEndPage;
  5780. end;
  5781. FCurrentFilter.OnEndDoc;
  5782. frProgressForm.ModalResult := mrOk;
  5783. end;
  5784. procedure TfrReport.ExportTo(Filter: TClass; FileName: String);
  5785. var
  5786. s: String;
  5787. begin
  5788. ExportStream := TFileStream.Create(FileName, fmCreate);
  5789. FCurrentFilter := TfrExportFilter(Filter.NewInstance);
  5790. FCurrentFilter.Create(ExportStream);
  5791. FCurrentFilter.OnBeginDoc;
  5792. CurReport := Self;
  5793. MasterReport := Self;
  5794. SavedAllPages := EMFPages.Count;
  5795. with frProgressForm do
  5796. begin
  5797. s := LoadStr(SReportPreparing);
  5798. if Title = '' then
  5799. Caption := s else
  5800. Caption := s + ' - ' + Title;
  5801. FirstCaption := LoadStr(SPagePreparing);
  5802. Label1.Caption := FirstCaption + ' 1';
  5803. OnBeforeModal := ExportBeforeModal;
  5804. Show_Modal(Self);
  5805. end;
  5806. FCurrentFilter.Free;
  5807. FCurrentFilter := nil;
  5808. ExportStream.Free;
  5809. end;
  5810. procedure TfrReport.FillQueryParams;
  5811. var
  5812. i, j: Integer;
  5813. t: TfrView;
  5814. procedure PrepareDS(ds: TfrDataSet);
  5815. begin
  5816. if (ds <> nil) and (ds is TfrDBDataSet) then
  5817. frDataManager.PrepareDataSet(TfrTDataSet((ds as TfrDBDataSet).GetDataSet));
  5818. end;
  5819. begin
  5820. if frDataManager = nil then Exit;
  5821. frDataManager.BeforePreparing;
  5822. if Dataset <> nil then
  5823. PrepareDS(DataSet);
  5824. for i := 0 to Pages.Count - 1 do
  5825. for j := 0 to Pages[i].Objects.Count-1 do
  5826. begin
  5827. t := Pages[i].Objects[j];
  5828. if t is TfrBandView then
  5829. PrepareDS(frFindComponent(CurReport.Owner, t.FormatStr) as TfrDataSet);
  5830. end;
  5831. frDataManager.AfterPreparing;
  5832. end;
  5833. procedure TfrReport.DoBuildReport;
  5834. var
  5835. i: Integer;
  5836. b: Boolean;
  5837. begin
  5838. HookList.Clear;
  5839. CanRebuild := True;
  5840. DocMode := dmPrinting;
  5841. CurReport := Self;
  5842. Values.Items.Sorted := True;
  5843. frParser.OnGetValue := GetVariableValue;
  5844. frParser.OnFunction := OnGetParsFunction;
  5845. ErrorFlag := False;
  5846. b := (Dataset <> nil) and (ReportType = rtMultiple);
  5847. if b then
  5848. begin
  5849. Dataset.Init;
  5850. Dataset.First;
  5851. end;
  5852. for i := 0 to Pages.Count - 1 do
  5853. Pages[i].Skip := False;
  5854. for i := 0 to Pages.Count - 1 do
  5855. Pages[i].InitReport;
  5856. PrepareDataSets;
  5857. for i := 0 to Pages.Count - 1 do
  5858. Pages[i].PrepareObjects;
  5859. repeat
  5860. InternalOnProgress(PageNo + 1);
  5861. for i := 0 to Pages.Count - 1 do
  5862. begin
  5863. FCurPage := Pages[i];
  5864. if FCurPage.Skip then continue;
  5865. FCurPage.Mode := pmNormal;
  5866. if Assigned(FOnManualBuild) then
  5867. FOnManualBuild(FCurPage) else
  5868. FCurPage.FormPage;
  5869. Append := False;
  5870. if ((i = Pages.Count - 1) and CompositeMode and (not b or Dataset.Eof)) or
  5871. ((i <> Pages.Count - 1) and Pages[i + 1].PrintToPrevPage) then
  5872. begin
  5873. Dec(PageNo);
  5874. Append := True;
  5875. end;
  5876. if not Append then
  5877. begin
  5878. PageNo := MasterReport.EMFPages.Count;
  5879. InternalOnProgress(PageNo);
  5880. end;
  5881. if MasterReport.Terminated then break;
  5882. end;
  5883. InternalOnProgress(PageNo);
  5884. if b then Dataset.Next;
  5885. until MasterReport.Terminated or not b or Dataset.Eof;
  5886. for i := 0 to Pages.Count - 1 do
  5887. Pages[i].DoneReport;
  5888. if b then
  5889. Dataset.Exit;
  5890. if (frDataManager <> nil) and FinalPass then
  5891. frDataManager.AfterPreparing;
  5892. Values.Items.Sorted := False;
  5893. end;
  5894. procedure TfrReport.ShowReport;
  5895. begin
  5896. PrepareReport;
  5897. if ErrorFlag then
  5898. begin
  5899. MessageBox(0, PChar(ErrorStr), PChar(LoadStr(SError)),
  5900. mb_Ok + mb_IconError);
  5901. EMFPages.Clear;
  5902. end
  5903. else
  5904. ShowPreparedReport;
  5905. end;
  5906. procedure TfrReport.ShowPreparedReport;
  5907. var
  5908. s: String;
  5909. p: TfrPreviewForm;
  5910. begin
  5911. CurReport := Self;
  5912. MasterReport := Self;
  5913. DocMode := dmPrinting;
  5914. if EMFPages.Count = 0 then Exit;
  5915. s := LoadStr(SPreview);
  5916. if Title <> '' then s := s + ' - ' + Title;
  5917. if not (csDesigning in ComponentState) and Assigned(Preview) then
  5918. Preview.Connect(Self)
  5919. else
  5920. begin
  5921. p := TfrPreviewForm.Create(nil);
  5922. p.Caption := s;
  5923. p.Show_Modal(Self);
  5924. end;
  5925. end;
  5926. procedure TfrReport.PrintBeforeModal(Sender: TObject);
  5927. begin
  5928. DoPrintReport(FPageNumbers, FCopies);
  5929. frProgressForm.ModalResult := mrOk;
  5930. end;
  5931. procedure TfrReport.PrintPreparedReport(PageNumbers: String; Copies: Integer);
  5932. var
  5933. s: String;
  5934. begin
  5935. CurReport := Self;
  5936. MasterReport := Self;
  5937. s := LoadStr(SReportPreparing);
  5938. Terminated := False;
  5939. FPageNumbers := PageNumbers;
  5940. FCopies := Copies;
  5941. if not Assigned(FOnProgress) and FShowProgress then
  5942. with frProgressForm do
  5943. begin
  5944. if Title = '' then
  5945. Caption := s else
  5946. Caption := s + ' - ' + Title;
  5947. FirstCaption := LoadStr(SPagePrinting);
  5948. Label1.Caption := FirstCaption;
  5949. OnBeforeModal := PrintBeforeModal;
  5950. Show_Modal(Self);
  5951. end
  5952. else
  5953. PrintBeforeModal(nil);
  5954. Terminated := False;
  5955. end;
  5956. {$IFDEF Trial}
  5957. {$HINTS OFF}
  5958. procedure TfrReport.DoPrintReport(PageNumbers: String; Copies: Integer);
  5959. var
  5960. i, j: Integer;
  5961. f: Boolean;
  5962. pgList: TStringList;
  5963. procedure ParsePageNumbers;
  5964. var
  5965. i, j, n1, n2: Integer;
  5966. s: String;
  5967. IsRange: Boolean;
  5968. begin
  5969. s := PageNumbers;
  5970. while Pos(' ', s) <> 0 do
  5971. Delete(s, Pos(' ', s), 1);
  5972. if s = '' then Exit;
  5973. s := s + ',';
  5974. i := 1; j := 1; n1 := 1;
  5975. IsRange := False;
  5976. while i <= Length(s) do
  5977. begin
  5978. if s[i] = ',' then
  5979. begin
  5980. n2 := StrToInt(Copy(s, j, i - j));
  5981. j := i + 1;
  5982. if IsRange then
  5983. while n1 <= n2 do
  5984. begin
  5985. pgList.Add(IntToStr(n1));
  5986. Inc(n1);
  5987. end
  5988. else
  5989. pgList.Add(IntToStr(n2));
  5990. IsRange := False;
  5991. end
  5992. else if s[i] = '-' then
  5993. begin
  5994. IsRange := True;
  5995. n1 := StrToInt(Copy(s, j, i - j));
  5996. j := i + 1;
  5997. end;
  5998. Inc(i);
  5999. end;
  6000. end;
  6001. procedure PrintPage(n: Integer);
  6002. var
  6003. s: String[40];
  6004. begin
  6005. with Printer, EMFPages[n]^ do
  6006. begin
  6007. if not Prn.IsEqual(pgSize, pgWidth, pgHeight, pgOr) then
  6008. begin
  6009. EndDoc;
  6010. Prn.SetPrinterInfo(pgSize, pgWidth, pgHeight, pgOr);
  6011. BeginDoc;
  6012. end
  6013. else if not f then NewPage;
  6014. Prn.FillPrnInfo(PrnInfo);
  6015. Visible := True;
  6016. with PrnInfo do
  6017. if pgMargins then
  6018. EMFPages.Draw(n, Printer.Canvas, Rect(-POfx, -POfy, PPgw - POfx, PPgh - POfy))
  6019. else
  6020. EMFPages.Draw(n, Printer.Canvas, Rect(0, 0, PPw, PPh));
  6021. Visible := False;
  6022. EMFPages.Draw(n, Printer.Canvas, Rect(0, 0, 0, 0));
  6023. s[0] := #25;
  6024. s[1] := 'F';
  6025. s[2] := 'a';
  6026. s[3] := 's';
  6027. s[4] := 't';
  6028. s[5] := 'R';
  6029. s[6] := 'e';
  6030. s[7] := 'p';
  6031. s[8] := 'o';
  6032. s[9] := LowerCase(s[5])[1];
  6033. s[10] := s[4];
  6034. s[11] := ' ';
  6035. s[12] := '-';
  6036. s[13] := s[11];
  6037. s[14] := 'u';
  6038. s[15] := 'n';
  6039. s[16] := s[9];
  6040. s[17] := s[6];
  6041. s[18] := 'g';
  6042. s[19] := 'i';
  6043. s[20] := s[3];
  6044. s[21] := s[4];
  6045. s[22] := s[6];
  6046. s[23] := s[9];
  6047. s[24] := s[6];
  6048. s[25] := 'd';
  6049. Canvas.TextOut(10, 10, s);
  6050. end;
  6051. InternalOnProgress(n + 1);
  6052. Application.ProcessMessages;
  6053. f := False;
  6054. Printer.EndDoc;
  6055. pgList.Free;
  6056. end;
  6057. begin
  6058. Prn.Printer := Printer;
  6059. pgList := TStringList.Create;
  6060. ParsePageNumbers;
  6061. if Copies <= 0 then
  6062. Copies := 1;
  6063. with EMFPages[0]^ do
  6064. begin
  6065. Prn.SetPrinterInfo(pgSize, pgWidth, pgHeight, pgOr);
  6066. Prn.FillPrnInfo(PrnInfo);
  6067. end;
  6068. if Title <> '' then
  6069. Printer.Title := 'FastReport: ' + Title else
  6070. Printer.Title := 'FastReport: ' + LoadStr(SUntitled);
  6071. Printer.BeginDoc;
  6072. f := True;
  6073. for i := 0 to EMFPages.Count - 1 do
  6074. if (pgList.Count = 0) or (pgList.IndexOf(IntToStr(i + 1)) <> -1) then
  6075. begin
  6076. PrintPage(i);
  6077. Exit;
  6078. end;
  6079. end;
  6080. {$HINTS ON}
  6081. {$ELSE}
  6082. procedure TfrReport.DoPrintReport(PageNumbers: String; Copies: Integer);
  6083. var
  6084. i, j: Integer;
  6085. f: Boolean;
  6086. pgList: TStringList;
  6087. procedure ParsePageNumbers;
  6088. var
  6089. i, j, n1, n2: Integer;
  6090. s: String;
  6091. IsRange: Boolean;
  6092. begin
  6093. s := PageNumbers;
  6094. while Pos(' ', s) <> 0 do
  6095. Delete(s, Pos(' ', s), 1);
  6096. if s = '' then Exit;
  6097. s := s + ',';
  6098. i := 1; j := 1; n1 := 1;
  6099. IsRange := False;
  6100. while i <= Length(s) do
  6101. begin
  6102. if s[i] = ',' then
  6103. begin
  6104. n2 := StrToInt(Copy(s, j, i - j));
  6105. j := i + 1;
  6106. if IsRange then
  6107. while n1 <= n2 do
  6108. begin
  6109. pgList.Add(IntToStr(n1));
  6110. Inc(n1);
  6111. end
  6112. else
  6113. pgList.Add(IntToStr(n2));
  6114. IsRange := False;
  6115. end
  6116. else if s[i] = '-' then
  6117. begin
  6118. IsRange := True;
  6119. n1 := StrToInt(Copy(s, j, i - j));
  6120. j := i + 1;
  6121. end;
  6122. Inc(i);
  6123. end;
  6124. end;
  6125. procedure PrintPage(n: Integer);
  6126. begin
  6127. with Printer, EMFPages[n]^ do
  6128. begin
  6129. if not Prn.IsEqual(pgSize, pgWidth, pgHeight, pgOr) then
  6130. begin
  6131. EndDoc;
  6132. Prn.SetPrinterInfo(pgSize, pgWidth, pgHeight, pgOr);
  6133. BeginDoc;
  6134. end
  6135. else if not f then NewPage;
  6136. Prn.FillPrnInfo(PrnInfo);
  6137. Visible := True;
  6138. with PrnInfo do
  6139. if pgMargins then
  6140. EMFPages.Draw(n, Printer.Canvas, Rect(-POfx, -POfy, PPgw - POfx, PPgh - POfy))
  6141. else
  6142. EMFPages.Draw(n, Printer.Canvas, Rect(0, 0, PPw, PPh));
  6143. Visible := False;
  6144. EMFPages.Draw(n, Printer.Canvas, Rect(0, 0, 0, 0));
  6145. end;
  6146. InternalOnProgress(n + 1);
  6147. Application.ProcessMessages;
  6148. f := False;
  6149. end;
  6150. begin
  6151. Prn.Printer := Printer;
  6152. pgList := TStringList.Create;
  6153. ParsePageNumbers;
  6154. if Copies <= 0 then
  6155. Copies := 1;
  6156. with EMFPages[0]^ do
  6157. begin
  6158. Prn.SetPrinterInfo(pgSize, pgWidth, pgHeight, pgOr);
  6159. Prn.FillPrnInfo(PrnInfo);
  6160. end;
  6161. if Title <> '' then
  6162. Printer.Title := 'FastReport: ' + Title else
  6163. Printer.Title := 'FastReport: ' + LoadStr(SUntitled);
  6164. Printer.BeginDoc;
  6165. f := True;
  6166. for i := 0 to EMFPages.Count - 1 do
  6167. if (pgList.Count = 0) or (pgList.IndexOf(IntToStr(i + 1)) <> -1) then
  6168. for j := 0 to Copies - 1 do
  6169. begin
  6170. PrintPage(i);
  6171. if Terminated then
  6172. begin
  6173. Printer.Abort;
  6174. pgList.Free;
  6175. Exit;
  6176. end;
  6177. end;
  6178. Printer.EndDoc;
  6179. pgList.Free;
  6180. end;
  6181. {$ENDIF}
  6182. // printer manipulation methods
  6183. procedure TfrReport.SetPrinterTo(PrnName: String);
  6184. begin
  6185. if not PrintToDefault then
  6186. if Prn.Printers.IndexOf(PrnName) <> -1 then
  6187. Prn.PrinterIndex := Prn.Printers.IndexOf(PrnName);
  6188. end;
  6189. function TfrReport.ChangePrinter(OldIndex, NewIndex: Integer): Boolean;
  6190. procedure ChangePages;
  6191. var
  6192. i: Integer;
  6193. begin
  6194. for i := 0 to Pages.Count - 1 do
  6195. with Pages[i] do
  6196. ChangePaper(pgSize, pgWidth, pgHeight, pgOr);
  6197. end;
  6198. begin
  6199. Result := True;
  6200. try
  6201. Prn.PrinterIndex := NewIndex;
  6202. Prn.PaperSize := -1;
  6203. ChangePages;
  6204. except
  6205. on Exception do
  6206. begin
  6207. MessageBox(0, PChar(LoadStr(SPrinterError)),
  6208. PChar(LoadStr(SError)), mb_IconError + mb_Ok);
  6209. Prn.PrinterIndex := OldIndex;
  6210. ChangePages;
  6211. Result := False;
  6212. end;
  6213. end;
  6214. end;
  6215. procedure TfrReport.EditPreparedReport(PageIndex: Integer);
  6216. var
  6217. p: PfrPageInfo;
  6218. Stream: TMemoryStream;
  6219. Designer: TfrReportDesigner;
  6220. DesName: String;
  6221. begin
  6222. if frDesigner = nil then Exit;
  6223. Screen.Cursor := crHourGlass;
  6224. Designer := frDesigner;
  6225. DesName := Designer.Name;
  6226. Designer.Name := DesName + '__';
  6227. Designer.Page := nil;
  6228. frDesigner := TfrReportDesigner(frDesigner.ClassType.NewInstance);
  6229. frDesigner.Create(nil);
  6230. Stream := TMemoryStream.Create;
  6231. SaveToStream(Stream);
  6232. Pages.Clear;
  6233. EMFPages.ObjectsToPage(PageIndex);
  6234. p := EMFPages[PageIndex];
  6235. Pages.FPages.Add(p^.Page);
  6236. CurReport := Self;
  6237. Screen.Cursor := crDefault;
  6238. try
  6239. frDesigner.ShowModal;
  6240. if frDesigner.Modified then
  6241. if MessageBox(0, PChar(LoadStr(SSaveChanges) + '?'),
  6242. PChar(LoadStr(SConfirm)), mb_YesNo + mb_IconQuestion) = mrYes then
  6243. EMFPages.PageToObjects(PageIndex);
  6244. finally
  6245. Pages.FPages.Clear;
  6246. Stream.Position := 0;
  6247. LoadFromStream(Stream);
  6248. Stream.Free;
  6249. frDesigner.Free;
  6250. frDesigner := Designer;
  6251. frDesigner.Name := DesName;
  6252. frDesigner.Page := Pages[0];
  6253. frDesigner.RedrawPage;
  6254. end;
  6255. end;
  6256. // miscellaneous methods
  6257. procedure TfrReport.PrepareDataSets;
  6258. var
  6259. i: Integer;
  6260. begin
  6261. with Values do
  6262. for i := 0 to Items.Count - 1 do
  6263. with Objects[i] do
  6264. if Typ = vtDBField then
  6265. DSet := frGetDataSet(DataSet);
  6266. end;
  6267. procedure TfrReport.SetVars(Value: TStrings);
  6268. begin
  6269. FVars.Assign(Value);
  6270. end;
  6271. procedure TfrReport.GetVarList(CatNo: Integer; List: TStrings);
  6272. var
  6273. i, n: Integer;
  6274. s: String;
  6275. begin
  6276. List.Clear;
  6277. i := 0; n := 0;
  6278. if FVars.Count > 0 then
  6279. repeat
  6280. s := FVars[i];
  6281. if Length(s) > 0 then
  6282. if s[1] <> ' ' then Inc(n);
  6283. Inc(i);
  6284. until n > CatNo;
  6285. while i < FVars.Count do
  6286. begin
  6287. s := FVars[i];
  6288. if (s <> '') and (s[1] = ' ') then
  6289. List.Add(Copy(s, 2, Length(s) - 1)) else
  6290. break;
  6291. Inc(i);
  6292. end;
  6293. end;
  6294. procedure TfrReport.GetCategoryList(List: TStrings);
  6295. var
  6296. i: Integer;
  6297. s: String;
  6298. begin
  6299. List.Clear;
  6300. for i := 0 to FVars.Count - 1 do
  6301. begin
  6302. s := FVars[i];
  6303. if (s <> '') and (s[1] <> ' ') then List.Add(s);
  6304. end;
  6305. end;
  6306. function TfrReport.FindVariable(Variable: String): Integer;
  6307. var
  6308. i: Integer;
  6309. begin
  6310. Result := -1;
  6311. Variable := ' ' + Variable;
  6312. for i := 0 to FVars.Count - 1 do
  6313. if Variable = FVars[i] then
  6314. begin
  6315. Result := i;
  6316. break;
  6317. end;
  6318. end;
  6319. function TfrReport.FindObject(Name: String): TfrView;
  6320. var
  6321. i, j: Integer;
  6322. begin
  6323. Result := nil;
  6324. for i := 0 to Pages.Count - 1 do
  6325. for j := 0 to Pages[i].Objects.Count - 1 do
  6326. if AnsiCompareText(TfrView(Pages[i].Objects[j]).Name, Name) = 0 then
  6327. begin
  6328. Result := Pages[i].Objects[j];
  6329. Exit;
  6330. end;
  6331. end;
  6332. {----------------------------------------------------------------------------}
  6333. constructor TfrCompositeReport.Create(AOwner: TComponent);
  6334. begin
  6335. inherited Create(AOwner);
  6336. Reports := TList.Create;
  6337. end;
  6338. destructor TfrCompositeReport.Destroy;
  6339. begin
  6340. Reports.Free;
  6341. inherited Destroy;
  6342. end;
  6343. procedure TfrCompositeReport.DoBuildReport;
  6344. var
  6345. i: Integer;
  6346. Doc: TfrReport;
  6347. ParamOk: Boolean;
  6348. begin
  6349. CanRebuild := True;
  6350. PageNo := 0;
  6351. for i := 0 to Reports.Count - 1 do
  6352. begin
  6353. Doc := TfrReport(Reports[i]);
  6354. CompositeMode := False;
  6355. if i <> Reports.Count - 1 then
  6356. if (TfrReport(Reports[i + 1]).Pages.Count > 0) and
  6357. TfrReport(Reports[i + 1]).Pages[0].PrintToPrevPage then
  6358. CompositeMode := True;
  6359. if Assigned(Doc.FOnBeginDoc) and FirstTime then
  6360. Doc.FOnBeginDoc;
  6361. ParamOk := True;
  6362. if (frDataManager <> nil) and FirstTime then
  6363. begin
  6364. Doc.FillQueryParams;
  6365. ParamOk := frDataManager.ShowParamsDialog;
  6366. end;
  6367. if ParamOk then
  6368. Doc.DoBuildReport;
  6369. if (frDataManager <> nil) and FinalPass then
  6370. frDataManager.AfterParamsDialog;
  6371. if Assigned(Doc.FOnEndDoc) and FinalPass then
  6372. Doc.FOnEndDoc;
  6373. Append := CompositeMode;
  6374. CompositeMode := False;
  6375. if Terminated then break;
  6376. end;
  6377. end;
  6378. {----------------------------------------------------------------------------}
  6379. procedure TfrObjEditorForm.ShowEditor(t: TfrView);
  6380. begin
  6381. // abstract method
  6382. end;
  6383. {----------------------------------------------------------------------------}
  6384. constructor TfrExportFilter.Create(AStream: TStream);
  6385. begin
  6386. inherited Create;
  6387. Stream := AStream;
  6388. Lines := TList.Create;
  6389. end;
  6390. destructor TfrExportFilter.Destroy;
  6391. begin
  6392. ClearLines;
  6393. Lines.Free;
  6394. inherited Destroy;
  6395. end;
  6396. procedure TfrExportFilter.ClearLines;
  6397. var
  6398. i: Integer;
  6399. p, p1: PfrTextRec;
  6400. begin
  6401. for i := 0 to Lines.Count - 1 do
  6402. begin
  6403. p := PfrTextRec(Lines[i]);
  6404. while p <> nil do
  6405. begin
  6406. p1 := p;
  6407. p := p^.Next;
  6408. FreeMem(p1, SizeOf(TfrTextRec));
  6409. end;
  6410. end;
  6411. Lines.Clear;
  6412. end;
  6413. procedure TfrExportFilter.OnBeginDoc;
  6414. begin
  6415. // abstract method
  6416. end;
  6417. procedure TfrExportFilter.OnEndDoc;
  6418. begin
  6419. // abstract method
  6420. end;
  6421. procedure TfrExportFilter.OnBeginPage;
  6422. begin
  6423. // abstract method
  6424. end;
  6425. procedure TfrExportFilter.OnEndPage;
  6426. begin
  6427. // abstract method
  6428. end;
  6429. procedure TfrExportFilter.OnData(x, y: Integer; View: TfrView);
  6430. begin
  6431. // abstract method
  6432. end;
  6433. procedure TfrExportFilter.OnText(x, y: Integer; const text: String; View: TfrView);
  6434. begin
  6435. // abstract method
  6436. end;
  6437. {----------------------------------------------------------------------------}
  6438. constructor TfrFunctionLibrary.Create;
  6439. begin
  6440. inherited Create;
  6441. List := TStringList.Create;
  6442. List.Sorted := True;
  6443. end;
  6444. destructor TfrFunctionLibrary.Destroy;
  6445. begin
  6446. List.Free;
  6447. inherited Destroy;
  6448. end;
  6449. function TfrFunctionLibrary.OnFunction(const FName: String; p1, p2, p3: Variant;
  6450. var val: String): Boolean;
  6451. var
  6452. i: Integer;
  6453. begin
  6454. Result := False;
  6455. if List.Find(FName, i) then
  6456. begin
  6457. DoFunction(i, p1, p2, p3, val);
  6458. Result := True;
  6459. end;
  6460. end;
  6461. {----------------------------------------------------------------------------}
  6462. constructor TfrStdFunctionLibrary.Create;
  6463. begin
  6464. inherited Create;
  6465. with List do
  6466. begin
  6467. Add('AVG');
  6468. Add('COUNT');
  6469. Add('FORMATDATETIME');
  6470. Add('FORMATFLOAT');
  6471. Add('INPUT');
  6472. Add('LOWERCASE');
  6473. Add('MAX');
  6474. Add('MIN');
  6475. Add('NAMECASE');
  6476. Add('STRTODATE');
  6477. Add('STRTOTIME');
  6478. Add('SUM');
  6479. Add('UPPERCASE');
  6480. end;
  6481. end;
  6482. procedure TfrStdFunctionLibrary.DoFunction(FNo: Integer; p1, p2, p3: Variant;
  6483. var val: String);
  6484. var
  6485. DataSet: TfrTDataSet;
  6486. Field: TfrTField;
  6487. s1, s2, VarName: String;
  6488. min, max, avg, sum, count, d, v: Double;
  6489. dk: (dkNone, dkSum, dkMin, dkMax, dkAvg, dkCount);
  6490. vv: Variant;
  6491. begin
  6492. dk := dkNone;
  6493. val := '0';
  6494. case FNo of
  6495. 0: dk := dkAvg;
  6496. 1: dk := dkCount;
  6497. 2: val := '''' + FormatDateTime(frParser.Calc(p1), frParser.Calc(p2)) + '''';
  6498. 3: val := '''' + FormatFloat(frParser.Calc(p1), frParser.Calc(p2)) + '''';
  6499. 4:
  6500. begin
  6501. s1 := InputBox('', frParser.Calc(p1), frParser.Calc(p2));
  6502. val := '''' + s1 + '''';
  6503. end;
  6504. 5: val := '''' + AnsiLowerCase(frParser.Calc(p1)) + '''';
  6505. 6: dk := dkMax;
  6506. 7: dk := dkMin;
  6507. 8:
  6508. begin
  6509. s1 := AnsiLowerCase(frParser.Calc(p1));
  6510. if Length(s1) > 0 then
  6511. val := '''' + AnsiUpperCase(s1[1]) + Copy(s1, 2, Length(s1) - 1) + ''''
  6512. else
  6513. val := '''' + '''';
  6514. end;
  6515. 9: val := '%d''' + frParser.Calc(p1) + '''';
  6516. 10: val := '%t''' + frParser.Calc(p1) + '''';
  6517. 11: dk := dkSum;
  6518. 12: val := '''' + AnsiUpperCase(frParser.Calc(p1)) + '''';
  6519. end;
  6520. if dk <> dkNone then
  6521. begin
  6522. if dk = dkCount then
  6523. DataSet := frGetDataSet(p1) else
  6524. frGetDataSetAndField(p1, DataSet, Field);
  6525. if (DataSet <> nil) and AggrBand.Visible then
  6526. begin
  6527. min := 1e200; max := -1e200; sum := 0; count := 0; avg := 0;
  6528. DataSet.First;
  6529. while not DataSet.Eof do
  6530. begin
  6531. v := 0;
  6532. if dk <> dkCount then
  6533. if Field.Value <> Null then
  6534. v := Field.AsFloat else
  6535. v := 0;
  6536. if v > max then max := v;
  6537. if v < min then min := v;
  6538. sum := sum + v;
  6539. count := count + 1;
  6540. DataSet.Next;
  6541. end;
  6542. if count > 0 then
  6543. avg := sum / count;
  6544. d := 0;
  6545. case dk of
  6546. dkSum: d := sum;
  6547. dkMin: d := min;
  6548. dkMax: d := max;
  6549. dkAvg: d := avg;
  6550. dkCount: d := count;
  6551. end;
  6552. val := FloatToStr(d);
  6553. end
  6554. else if DataSet = nil then
  6555. begin
  6556. s1 := Trim(p2);
  6557. if s1 = '' then
  6558. s1 := CurBand.View.Name;
  6559. if dk <> dkCount then
  6560. s2 := Trim(p3) else
  6561. s2 := Trim(p2);
  6562. if (AggrBand.Typ in [btPageFooter, btMasterFooter, btDetailFooter,
  6563. btSubDetailFooter, btGroupFooter, btCrossFooter, btReportSummary]) and
  6564. ((s2 = '1') or ((s2 <> '1') and CurBand.Visible)) then
  6565. begin
  6566. VarName := List[FNo] + p1;
  6567. if IsColumns then
  6568. if AggrBand.Typ = btCrossFooter then
  6569. VarName := VarName + '00' else
  6570. VarName := VarName + IntToStr(CurPage.ColPos);
  6571. if not AggrBand.Visible and (AnsiCompareText(CurBand.View.Name, s1) = 0) then
  6572. begin
  6573. s1 := AggrBand.Values.Values[VarName];
  6574. if s1 <> '' then
  6575. if s1[1] = '1' then
  6576. Exit else
  6577. s1 := Copy(s1, 2, 255);
  6578. vv := 0;
  6579. if dk <> dkCount then
  6580. vv := frParser.Calc(p1);
  6581. if vv = Null then
  6582. vv := 0;
  6583. d := vv;
  6584. if s1 = '' then
  6585. if dk = dkMin then s1 := '1e200'
  6586. else if dk = dkMax then s1 := '-1e200'
  6587. else s1 := '0';
  6588. v := StrToFloat(s1);
  6589. case dk of
  6590. dkAvg: v := v + d;
  6591. dkCount: v := v + 1;
  6592. dkMax: if v < d then v := d;
  6593. dkMin: if v > d then v := d;
  6594. dkSum: v := v + d;
  6595. end;
  6596. AggrBand.Values.Values[VarName] := '1' + FloatToStr(v);
  6597. Exit;
  6598. end
  6599. else if AggrBand.Visible then
  6600. begin
  6601. val := Copy(AggrBand.Values.Values[VarName], 2, 255);
  6602. if dk = dkAvg then
  6603. val := FloatToStr(StrToFloat(val) / AggrBand.Count);
  6604. Exit;
  6605. end;
  6606. end;
  6607. end;
  6608. end;
  6609. end;
  6610. {-----------------------------------------------------------------------------}
  6611. const
  6612. PropCount = 16;
  6613. PropNames: Array[0..PropCount - 1] of String =
  6614. ('Left', 'Top', 'Width', 'Height', 'Flags', 'Visible', 'FrameTyp',
  6615. 'FrameWidth', 'FrameColor', 'FillColor', 'Text',
  6616. 'FontName', 'FontSize', 'FontStyle', 'FontColor', 'Adjust');
  6617. ColNames: Array[0..16] of String =
  6618. ('clWhite', 'clBlack', 'clMaroon', 'clGreen', 'clOlive', 'clNavy',
  6619. 'clPurple', 'clTeal', 'clGray', 'clSilver', 'clRed', 'clLime',
  6620. 'clYellow', 'clBlue', 'clFuchsia', 'clAqua', 'clTransparent');
  6621. {$WARNINGS OFF}
  6622. procedure TInterpretator.GetValue(const Name: String; var Value: Variant);
  6623. var
  6624. i: Integer;
  6625. t: TfrView;
  6626. b: TfrBand;
  6627. Prop: String;
  6628. Flag: Boolean;
  6629. begin
  6630. Value := 0;
  6631. t := CurView;
  6632. Prop := Name;
  6633. if frVariables.IndexOf(Name) <> -1 then
  6634. begin
  6635. Value := frVariables[Name];
  6636. Exit;
  6637. end;
  6638. if Name = 'FREESPACE' then
  6639. begin
  6640. Value := IntToStr(CurPage.CurBottomY - CurPage.CurY);
  6641. Exit;
  6642. end;
  6643. if Pos('.', Name) <> 0 then
  6644. begin
  6645. t := CurPage.FindRTObject(Copy(Name, 1, Pos('.', Name) - 1));
  6646. Prop := Copy(Name, Pos('.', Name) + 1, 255);
  6647. end;
  6648. if t = nil then
  6649. begin
  6650. frParser.OnGetValue(Name, Value);
  6651. Exit;
  6652. end;
  6653. Flag := False;
  6654. for i := 0 to PropCount - 1 do
  6655. if AnsiCompareText(PropNames[i], Prop) = 0 then
  6656. begin
  6657. Flag := True;
  6658. break;
  6659. end;
  6660. if not Flag then
  6661. for i := 0 to 16 do
  6662. if AnsiCompareText(ColNames[i], Prop) = 0 then
  6663. begin
  6664. if i <> 16 then
  6665. Value := frColors[i] else
  6666. Value := clNone;
  6667. Exit;
  6668. end;
  6669. if not Flag or ((i >= 11) and not (t is TfrMemoView)) then
  6670. begin
  6671. frParser.OnGetValue(Name, Value);
  6672. Exit;
  6673. end;
  6674. if t is TfrBandView then
  6675. begin
  6676. b := t.Parent;
  6677. case i of
  6678. 0: Value := b.x;
  6679. 1: Value := b.y;
  6680. 2: Value := b.dx;
  6681. 3: Value := b.dy;
  6682. 5: Value := b.Visible;
  6683. end;
  6684. end
  6685. else
  6686. case i of
  6687. 0: Value := t.x;
  6688. 1: Value := t.y;
  6689. 2: Value := t.dx;
  6690. 3: Value := t.dy;
  6691. 4: Value := t.Flags;
  6692. 5: Value := t.Visible;
  6693. 6: Value := t.FrameTyp;
  6694. 7: Value := t.FrameWidth;
  6695. 8: Value := t.FrameColor;
  6696. 9: Value := t.FillColor;
  6697. 10: Value := t.Memo.Text;
  6698. 11: Value := TfrMemoView(t).Font.Name;
  6699. 12: Value := TfrMemoView(t).Font.Size;
  6700. 13: Value := frGetFontStyle(TfrMemoView(t).Font.Style);
  6701. 14: Value := TfrMemoView(t).Font.Color;
  6702. 15: Value := TfrMemoView(t).Adjust;
  6703. end;
  6704. end;
  6705. {$WARNINGS ON}
  6706. procedure TInterpretator.SetValue(const Name: String; Value: Variant);
  6707. var
  6708. i: Integer;
  6709. t: TfrView;
  6710. b: TfrBand;
  6711. Prop: String;
  6712. Flag: Boolean;
  6713. begin
  6714. t := CurView;
  6715. Prop := Name;
  6716. if Pos('.', Name) <> 0 then
  6717. begin
  6718. t := CurPage.FindRTObject(Copy(Name, 1, Pos('.', Name) - 1));
  6719. Prop := Copy(Name, Pos('.', Name) + 1, 255);
  6720. end;
  6721. // if t = nil then Exit;
  6722. Flag := False;
  6723. for i := 0 to PropCount - 1 do
  6724. if AnsiCompareText(PropNames[i], Prop) = 0 then
  6725. begin
  6726. Flag := True;
  6727. break;
  6728. end;
  6729. if not Flag then
  6730. begin
  6731. frVariables[Name] := Value;
  6732. Exit;
  6733. end;
  6734. if (i >= 11) and not (t is TfrMemoView) then Exit;
  6735. if t is TfrBandView then
  6736. begin
  6737. b := t.Parent;
  6738. case i of
  6739. 0: b.x := Value;
  6740. 1: b.y := Value;
  6741. 2: b.dx := Value;
  6742. 3: b.dy := Value;
  6743. 5: b.Visible := Value;
  6744. end;
  6745. end
  6746. else
  6747. case i of
  6748. 0: t.x := Value;
  6749. 1: t.y := Value;
  6750. 2: t.dx := Value;
  6751. 3: t.dy := Value;
  6752. 4: t.Flags := Value;
  6753. 5: t.Visible := Value;
  6754. 6: t.FrameTyp := Value;
  6755. 7: t.FrameWidth := Value;
  6756. 8: t.FrameColor := Value;
  6757. 9: t.FillColor := Value;
  6758. 10: t.Memo.Text := Value;
  6759. 11: TfrMemoView(t).Font.Name := Value;
  6760. 12: TfrMemoView(t).Font.Size := Value;
  6761. 13: TfrMemoView(t).Font.Style := frSetFontStyle(Value);
  6762. 14: TfrMemoView(t).Font.Color := Value;
  6763. 15: TfrMemoView(t).Adjust := Value;
  6764. end;
  6765. end;
  6766. procedure TInterpretator.DoFunction(const Name: String; p1, p2, p3: Variant;
  6767. var val: String);
  6768. begin
  6769. if Name = 'NEWPAGE' then
  6770. begin
  6771. CurBand.ForceNewPage := True;
  6772. Val := '0';
  6773. end
  6774. else if Name = 'NEWCOLUMN' then
  6775. begin
  6776. CurBand.ForceNewColumn := True;
  6777. Val := '0';
  6778. end
  6779. else
  6780. frParser.OnFunction(Name, p1, p2, p3, val);
  6781. end;
  6782. {----------------------------------------------------------------------------}
  6783. procedure TfrCompressor.Compress(StreamIn, StreamOut: TStream);
  6784. begin
  6785. // abstract method
  6786. end;
  6787. procedure TfrCompressor.DeCompress(StreamIn, StreamOut: TStream);
  6788. begin
  6789. // abstract method
  6790. end;
  6791. {----------------------------------------------------------------------------}
  6792. procedure DoInit;
  6793. const
  6794. Clr: Array[0..1] of TColor = (clWhite, clSilver);
  6795. var
  6796. i, j: Integer;
  6797. begin
  6798. SMemo := TStringList.Create;
  6799. SBmp := TBitmap.Create;
  6800. TempBmp := TBitmap.Create;
  6801. SBmp.Width := 8; SBmp.Height := 8;
  6802. TempBmp.Width := 8; TempBmp.Height := 8;
  6803. for j := 0 to 7 do
  6804. for i := 0 to 7 do
  6805. SBmp.Canvas.Pixels[i, j] := Clr[(j + i) mod 2];
  6806. frRegisterFunctionLibrary(TfrStdFunctionLibrary);
  6807. frProgressForm := TfrProgressForm.Create(nil);
  6808. frCharset := StrToInt(LoadStr(SCharset));
  6809. for i := 0 to 21 do
  6810. frBandNames[i] := LoadStr(SBand1 + i);
  6811. for i := 0 to frSpecCount - 1 do
  6812. frSpecArr[i] := LoadStr(SVar1 + i);
  6813. for i := 0 to 3 do
  6814. BoolStr[i] := LoadStr(SFormat51 + i);
  6815. for i := 0 to 3 do
  6816. begin
  6817. frDateFormats[i] := LoadStr(SDateFormat1 + i);
  6818. frTimeFormats[i] := LoadStr(STimeFormat1 + i);
  6819. end;
  6820. frParser := TfrParser.Create;
  6821. frInterpretator := TInterpretator.Create;
  6822. frVariables := TfrVariables.Create;
  6823. frCompressor := TfrCompressor.Create;
  6824. HookList := TList.Create;
  6825. end;
  6826. procedure DoExit;
  6827. var
  6828. i: Integer;
  6829. begin
  6830. SBmp.Free;
  6831. TempBmp.Free;
  6832. SMemo.Free;
  6833. frProgressForm.Free;
  6834. for i := 0 to frFunctionsCount - 1 do
  6835. frFunctions[i].FunctionLibrary.Free;
  6836. frParser.Free;
  6837. frInterpretator.Free;
  6838. frVariables.Free;
  6839. frCompressor.Free;
  6840. HookList.Free;
  6841. end;
  6842. initialization
  6843. DoInit;
  6844. finalization
  6845. DoExit;
  6846. end.