ec2ce65753
git-svn-id: https://svn.code.sf.net/p/kolmck/code@76 91bb2d04-0c0c-4d2d-88a5-bbb6f4c1fa07
1277 lines
40 KiB
ObjectPascal
1277 lines
40 KiB
ObjectPascal
{ KOLReport v2.0 (C) 2002 by Vladimir Kladov.
|
|
|
|
See Demo project attached for documentation. All other documentation planned
|
|
to be added later.
|
|
|
|
In version 2.0:
|
|
[+] metafiles used, spooling size became less, printing quality increased.
|
|
[+] with new version of KOLPrinters by Boguslaw Brandys, printer setup dialog provided.
|
|
}
|
|
unit KOLReport;
|
|
|
|
interface
|
|
|
|
//{$DEFINE use_MHPRINTER}
|
|
// (uncomment line above to use TKOLMHPrinter prior to TKOLPrinter)
|
|
|
|
uses Windows, Messages, KOL,
|
|
{$IFDEF use_MHPRINTER} KOLMHPrinters
|
|
{$ELSE} KOLPrinters, KOLPageSetupDialog
|
|
{$ENDIF};
|
|
|
|
type
|
|
{$IFDEF use_MHPRINTER} PPrinter = PMHPrinter; {$ENDIF}
|
|
|
|
TPaperSize = ( psA4, psA5, psA6, psA3, psLetter, psCustom );
|
|
{* Available paper sizes. }
|
|
TBandLayout = ( blLeft, blCenter, blRight, blExpandRight );
|
|
{* Available band layouts. }
|
|
TMargins = TRect;
|
|
|
|
TMF = HDC; // used as a handle to memory-based EnhMetafile.
|
|
|
|
PReport = ^TReport;
|
|
|
|
PPreviewObj = ^TPreviewObj;
|
|
TPreviewObj = object( TObj )
|
|
{* Preview form container object. }
|
|
private
|
|
procedure SetCurPage(const Value: Integer);
|
|
procedure SetFitMode(const Value: Integer);
|
|
public
|
|
Form: PControl;
|
|
{* Form. }
|
|
TB: PControl;
|
|
{* Toolbar. }
|
|
SB: PControl;
|
|
{* Scrollbar. }
|
|
PB: PControl;
|
|
{* PaintBox. }
|
|
LB: PControl;
|
|
PSD: PPageSetupDlg; {Brandys}
|
|
Options: TPageSetupOptions;
|
|
{* Label to show current page number and total pages count. }
|
|
FFitMode: Integer;
|
|
{* Fit mode: 0 - fit height, 1 - fit width, 2 - 1:1 }
|
|
ViewMenu: PMenu;
|
|
{* Drop down menu for toolbar button TBView. }
|
|
FBuf: PBitmap;
|
|
{* Buffer where current page stored (scaled). }
|
|
protected
|
|
FReport: PReport;
|
|
{* Reference to parent Report object. }
|
|
FCurPage: Integer;
|
|
{* Current page index. }
|
|
FBufPage: Integer;
|
|
{* Buffered page index. }
|
|
procedure TBClick( Sender: PObj );
|
|
procedure TBDropDownViewMenu( Sender: PObj );
|
|
procedure TBViewMenuClick( Sender: PMenu; Item: Integer );
|
|
procedure AdjustButtons( Sender: PObj );
|
|
procedure PaintPage( Sender: PControl; DC: HDC );
|
|
procedure AdjustFitMode;
|
|
procedure PrinterSetup;
|
|
procedure ResizePreviewForm( Sender: PObj );
|
|
public
|
|
destructor Destroy; virtual;
|
|
{* }
|
|
property CurPage: Integer read FCurPage write SetCurPage;
|
|
{* Current page index (starting from 0). }
|
|
function PageCount: Integer;
|
|
{* Total pages count. Could be 0, if a report is empty (nothing to show). }
|
|
procedure PrintAllPages;
|
|
{* Call this method to print all pages. }
|
|
property FitMode: Integer read FFitMode write SetFitMode;
|
|
{* Fit mode: 0 - fit height, 1 - fit width, 2 - 1:1. }
|
|
end;
|
|
|
|
TReport = object( TObj )
|
|
{* Report object. It is used to create report and to print or preview it}
|
|
private
|
|
FDocName: String;
|
|
FReplaceFontHeight0: Integer;
|
|
FMargins: TMargins;
|
|
function GetPages(Idx: Integer): TMF;
|
|
function GetImages(Idx: Integer): HENHMETAFILE;
|
|
procedure SetMargins(const Value: TMargins);
|
|
function GetMarginsPixels( const Index: Integer ): TMargins;
|
|
protected
|
|
FPageTop: Boolean;
|
|
FY: Integer;
|
|
FOnNewPage: TOnEvent;
|
|
FPrinter: PPrinter;
|
|
FX: Integer;
|
|
FPrinting: Boolean;
|
|
FDCPages: PList;
|
|
FHDPages: PList;
|
|
FStage: Integer;
|
|
FOnPrint: TOnEvent;
|
|
FPreviewForm: PPreviewObj;
|
|
FBottom: Integer;
|
|
FPagePixelsSize: TSize;
|
|
FPaperSize: TPaperSize;
|
|
FCustomPaperSize: TSize;
|
|
FPageWidth: Integer;
|
|
FPageHeight: Integer;
|
|
FDoubleBufferedPreview: Boolean;
|
|
FCurBandHeight: Integer;
|
|
FOnEndBand: TOnEvent;
|
|
fNewPageHandling: Boolean;
|
|
fNewBandHandling: Boolean;
|
|
procedure SetPageTop(const Value: Boolean);
|
|
procedure SetPrinter(const Value: PPrinter);
|
|
function GetPageCount: Integer;
|
|
function GetPreviewForm: PPreviewObj;
|
|
procedure SetPreviewForm(const Value: PPreviewObj);
|
|
function GetCurrentPage: TMF;
|
|
function GetPrinter: PPrinter;
|
|
function GetPagePixelsSize: TSize;
|
|
function GetOrientation: TPrinterOrientation;
|
|
procedure SetPaperSize(const Value: TPaperSize);
|
|
procedure SetCustomPaperSize(const Value: TSize);
|
|
function GetPageHeight: Integer;
|
|
function GetPageWidth: Integer;
|
|
procedure GetPageWidthHeight;
|
|
procedure SetX(const Value: Integer);
|
|
procedure SetY(const Value: Integer);
|
|
protected
|
|
function AddPage: TMF;
|
|
function PaintBand( MF: TMF; Band: PControl; Xpos, Ypos: Integer ): Integer;
|
|
function ScaleX( W: Integer ): Integer;
|
|
function ScaleY( H: Integer ): Integer;
|
|
procedure DoPrintPreview( Proc: TObjectMethod );
|
|
procedure DoPrint;
|
|
procedure DoPreview;
|
|
procedure DoPreviewModal;
|
|
public
|
|
Destructor Destroy; virtual;
|
|
procedure Clear;
|
|
{* Call this method to make report empty. If the preview form is active
|
|
for the report, it is closed too. }
|
|
procedure ClearPages;
|
|
{* Clears all pages. }
|
|
property PreviewForm: PPreviewObj read GetPreviewForm write SetPreviewForm;
|
|
{* Access to preview form object. }
|
|
property DoubleBufferedPreview: Boolean read FDoubleBufferedPreview write FDoubleBufferedPreview;
|
|
{* Set this value to TRUE, if you wish from PreviewForm to be shown
|
|
DoubleBuffered. }
|
|
property PagePixelsSize: TSize read GetPagePixelsSize;
|
|
{* Size of a page in screen pixels. }
|
|
property Orientation: TPrinterOrientation read GetOrientation;
|
|
{* Orientation of a Printer. }
|
|
property PaperSize: TPaperSize read FPaperSize write SetPaperSize;
|
|
{* Paper size type (psA4, psA3, ... psCustom). }
|
|
property CustomPaperSize: TSize read FCustomPaperSize write SetCustomPaperSize;
|
|
{* Custom paper size in millimeters. }
|
|
property PageWidth: Integer read GetPageWidth;
|
|
{* Paper width in Printer canvas pixels. }
|
|
property PageHeight: Integer read GetPageHeight;
|
|
{* Paper height in Printer canvas pixels. }
|
|
property CurrentPage: TMF read GetCurrentPage;
|
|
{* Current page metafile DC. Valid only while drawing the page. }
|
|
property Printer: PPrinter read GetPrinter write SetPrinter;
|
|
{* Printer object. }
|
|
property PageTop: Boolean read FPageTop write SetPageTop;
|
|
{* True, if current position is on top of current page. (It is set to
|
|
True just after calling OnNewPage event, i.e. *after* printing top
|
|
page colontitles). }
|
|
property X: Integer read FX write SetX;
|
|
{* Current X position. }
|
|
property Y: Integer read FY write SetY;
|
|
{* Current Y position. }
|
|
public
|
|
procedure AddBand( Band: PControl );
|
|
{* Call this method to add a band. Band could be any control, not only
|
|
created with NewBand or NewReportLabel etc. Before adding a band,
|
|
change its contant as you wish (change Caption, adjust Frames, Color,
|
|
Font, etc.) }
|
|
procedure AddBandEx( Band: PControl; BandLayout: TBandLayout );
|
|
{* Call this method to add a band with special aligning option. }
|
|
procedure AddFooter( Band: PControl );
|
|
{* Adds a footer band to a current page. It is possible to add several
|
|
footers, in such case the first is added to the bottom, and all the
|
|
follows above it. }
|
|
procedure AddFooterEx( Band: PControl; BandLayout: TBandLayout );
|
|
{* Adds a footer with special aligning option. }
|
|
procedure AddRight( Band: PControl );
|
|
{* Adds a band or a cell just right, without shifting current Y position
|
|
onto a height of a Band, like in AddBand or AddBandEx. Calling
|
|
AddRight ands AddRightEx several times it is possible to construct
|
|
desired band from prepared cells dynamically. If there are no place
|
|
for a new band between X position and right margin of the page, new
|
|
band is added from the starting of the next horizontal band
|
|
automatically. }
|
|
procedure AddRightEx( Band: PControl; BandLayout: TBandLayout );
|
|
{* Adds a band or a cell just right, and with additional layout options. }
|
|
procedure NewPage;
|
|
{* Forces new page. If called twice, empty page will be printed. }
|
|
property Bottom: Integer read FBottom;
|
|
{* Bottom available position (in screen pixels). Valid while drawing
|
|
onto current page. }
|
|
property PageCount: Integer read GetPageCount;
|
|
{* Total number of pages. }
|
|
property Pages[ Idx: Integer ]: TMF read GetPages;
|
|
{* Access to pages metafiles DC. Valid while drawing pages. }
|
|
property Images[ Idx: Integer ]: HENHMETAFILE read GetImages;
|
|
{* Access to page metafiles handles. If a handle for a certain page
|
|
is accessed, its metafile DC become unavailable. }
|
|
procedure Print;
|
|
{* Call this method to print all the pages. }
|
|
procedure PrintPages( FromPage, ToPage: Integer );
|
|
{* Call this method to print given pages range. }
|
|
procedure Preview;
|
|
{* Call this method to show preview non-modal. Be sure, that the Report
|
|
object is existing while preview is active. }
|
|
procedure PreviewModal;
|
|
{* Call this method to show preview form modal. }
|
|
procedure Abort;
|
|
{* Call this method to stop current printing. }
|
|
property Printing: Boolean read FPrinting;
|
|
{* True, if pages are currently printing. }
|
|
property Stage: Integer read FStage;
|
|
{* If OnPrint event is called, this value 1 or 2 shows a stage of
|
|
printing. In the first call of OnPrint event, it has value 1, in the
|
|
second its value is 2. }
|
|
property OnPrint: TOnEvent read FOnPrint write FOnPrint;
|
|
{* If this event is assigned, perform adding all bands in this event
|
|
handler. Please remember, that OnPrint is called twice. Be sure, that
|
|
all your initializations made correctly for both stages. Mainly, this
|
|
method is used to provide printing some data which depends on total
|
|
pages count (e.g. to print Page 1 From 10. You should store total
|
|
pages count after stage 1, and use this information on stage 2).
|
|
Also, this event allows to repeat printing after showing Printer setup
|
|
dialog in case when some settings are changed (page size, layout,
|
|
margins, etc.) }
|
|
property OnNewPage: TOnEvent read FOnNewPage write FOnNewPage;
|
|
{* This event is called when new page is started (by any reason). You can
|
|
add here page header or footers, if you wish. }
|
|
property OnEndBand: TOnEvent read FOnEndBand write FOnEndBand;
|
|
{* This event can be useful when bands are created dynamically from cells
|
|
calling AddRight or AddRightEx. }
|
|
function HeightAvailable: Integer;
|
|
{* Pixels available vertically on current page (in screen pixels). If
|
|
this value is not sufficient to add a band, new page is started. It
|
|
is possible to check this value manually to ensure that a certain
|
|
number of bands could be fit, and to force new page if you wish from
|
|
some data to be located always together, e.g. subdetail title +
|
|
column header + at least 1 band of subdetail data. }
|
|
property DocumentName: String read FDocName write FDocName;
|
|
{* Assign a name of your document here. This value is shown in spooler
|
|
queue and helps to identify your report among other printing documents. }
|
|
property ReplaceFontHeight0: Integer read FReplaceFontHeight0 write FReplaceFontHeight0;
|
|
{* Change this value, if default value 18 pixels is not satisfying you.
|
|
While adding a band, all its fonts with FontHeight=0 are replaced by this
|
|
value to provide correct scaling onto Printer device. }
|
|
property Margins: TMargins read FMargins write SetMargins;
|
|
{* Margins in 0.01 millimeters. }
|
|
property MarginsPrinterPixels: TMargins index 1 read GetMarginsPixels;
|
|
{* Margins in Printer's pixels. }
|
|
property MarginsScreenPixels: TMargins index 2 read GetMarginsPixels;
|
|
{* Margins in screen pixels. }
|
|
end;
|
|
|
|
TFrame = ( frLeft, frTop, frRight, frBottom );
|
|
{* Frames for special band control. }
|
|
TFrames = set of TFrame;
|
|
{* }
|
|
|
|
TPaddings = packed record
|
|
{* Paddings. }
|
|
LeftPadding, TopPadding, RightPadding, BottomPadding: Integer;
|
|
end;
|
|
|
|
const
|
|
AllFrames: TFrames = [ frLeft, frTop, frRight, frBottom ];
|
|
{* Use this constant to tell that all the frames are turned on. }
|
|
|
|
function NewReport: PReport;
|
|
{* Call this function to create report object. }
|
|
procedure NewPreviewForm( var PreviewObj: PPreviewObj; AParent: PControl );
|
|
{* This function is called automatically when Preview or PreviewModal method
|
|
is called for TReport object. }
|
|
|
|
function NewBand( AParent: PControl; Frames: TFrames ): PControl;
|
|
{* Call this function to create special band control. It is very similar to
|
|
a panel, and can contain other controls as children. }
|
|
function NewReportLabel( AParent: PControl; const Caption: String; Frames: TFrames ): PControl;
|
|
{* Call this function to create band label. It can be used along or as a
|
|
child of a band. }
|
|
function NewWordWrapReportLabel( AParent: PControl; const Caption: String; Frames: TFrames ): PControl;
|
|
{* Like NewReportLabel, but with WordWrap. }
|
|
|
|
procedure SetPaddings( BandCtl: PControl; LeftPadding, TopPadding, RightPadding, BottomPadding: Integer );
|
|
{* Use this function to change band paddings. }
|
|
|
|
type
|
|
TKOLReport = PReport;
|
|
TKOLBand = PControl;
|
|
TKOLReportLabel = PControl;
|
|
|
|
implementation
|
|
|
|
const TBFrst = 0;
|
|
TBPrev = 1;
|
|
TBNext = 2;
|
|
TBLast = 3;
|
|
TBPrnt = 4;
|
|
TBSetu = 5;
|
|
TBView = 6;
|
|
TBExit = 7;
|
|
|
|
function GetProviderPrinter: PPrinter;
|
|
begin
|
|
Result := Printer;
|
|
end;
|
|
|
|
function NewReport: PReport;
|
|
begin
|
|
new( Result, Create );
|
|
Result.FDocName := 'Report 1';
|
|
Result.FDCPages := NewList;
|
|
Result.FHDPages := NewList;
|
|
Result.FCustomPaperSize.cx := 210;
|
|
Result.FCustomPaperSize.cy := 270;
|
|
Result.FReplaceFontHeight0 := -12;
|
|
Result.FMargins := MakeRect( 500, 500, 500, 500 );
|
|
end;
|
|
|
|
procedure NewPreviewForm( var PreviewObj: PPreviewObj; AParent: PControl );
|
|
var Pn: PControl;
|
|
begin
|
|
new( PreviewObj, Create );
|
|
PreviewObj.Form := NewForm( AParent, 'Preview' ).SetSize( 600, 600 )
|
|
.SetPosition( (GetSystemMetrics( SM_CXSCREEN ) - 600) div 2,
|
|
(GetSystemMetrics( SM_CYSCREEN ) - 600) div 2 );
|
|
{Brandys}
|
|
PreviewObj.Options := [psdMargins,psdSamplePage,psdPaperControl,psdPrinterControl,psdWarning,psdHundredthsOfMillimeters,psdUseMargins,psdUseMinMargins];
|
|
PreviewObj.PSD := NewPageSetupDialog(PreviewObj.Form,PreviewObj.Options);
|
|
PreviewObj.PSD.SetMinMargins(500,500,500,500);
|
|
PreviewObj.Form.Border := 0;
|
|
Pn := NewPanel( PreviewObj.Form, esNone ).SetSize( 0, 25 ).SetAlign( caTop );
|
|
PreviewObj.TB := NewToolbar( Pn, caNone, [ tboNoDivider ],
|
|
THandle(-1), [ '<<', '<', '>', '>>', ' Print', 'Setup', '^View', 'Close' ],
|
|
[ -1, -1, -1, -1, 14, -2 ] ).SetAlign( caLeft ).SetSize( 440, 0 );
|
|
PreviewObj.TB.OnClick := PreviewObj.TBClick;
|
|
PreviewObj.TB.OnTBDropDown := PreviewObj.TBDropDownViewMenu;
|
|
NewMenu( PreviewObj.Form, 0, [ '' ], nil );
|
|
PreviewObj.ViewMenu := NewMenu( PreviewObj.Form, 0,
|
|
[ '-!Fit &Height', '-!Fit &Width', '-!&1:1' ],
|
|
PreviewObj.TBViewMenuClick );
|
|
PreviewObj.LB := NewLabel( Pn, '' ).SetAlign( caClient );
|
|
PreviewObj.LB.TextAlign := taRight;
|
|
PreviewObj.LB.VerticalAlign := vaCenter;
|
|
PreviewObj.Form.OnShow := PreviewObj.AdjustButtons;
|
|
PreviewObj.SB := NewScrollBoxEx( PreviewObj.Form, esLowered ).SetAlign( caClient );
|
|
PreviewObj.PB := NewPaintBox( PreviewObj.SB );
|
|
PreviewObj.PB.OnPaint := PreviewObj.PaintPage;
|
|
|
|
//PreviewObj.TB.TBButtonVisible[ TBSetu ] := FALSE;
|
|
PreviewObj.Form.OnResize := PreviewObj.ResizePreviewForm;
|
|
end;
|
|
|
|
type
|
|
PFramesData = ^TFramesData;
|
|
TFramesData = packed Record
|
|
Frames: TFrames;
|
|
Paddings: TPaddings;
|
|
end;
|
|
|
|
procedure PaintFrames( Self_, Sender: PControl; DC: HDC );
|
|
var Br: HBrush;
|
|
R: TRect;
|
|
procedure FillFrame( X1, Y1, X2, Y2: Integer );
|
|
begin
|
|
if X2 <= X1 then Exit;
|
|
if Y2 <= Y1 then Exit;
|
|
FillRect( DC, MakeRect( X1, Y1, X2, Y2 ), Br );
|
|
end;
|
|
var Data: PFramesData;
|
|
W, H, B: Integer;
|
|
Fmt: DWORD;
|
|
OldFont: HFont;
|
|
OldBk: Integer;
|
|
begin
|
|
Data := Self_.CustomData;
|
|
Br := CreateSolidBrush( Color2RGB( Self_.Font.Color ) );
|
|
W := Self_.ClientWidth;
|
|
H := Self_.ClientHeight;
|
|
B := Self_.Border;
|
|
R := Self_.ClientRect;
|
|
if frLeft in Data.Frames then
|
|
begin
|
|
FillFrame( 0, 0, B, H );
|
|
Inc( R.Left, B );
|
|
end;
|
|
if frTop in Data.Frames then
|
|
begin
|
|
FillFrame( 0, 0, W, B );
|
|
Inc( R.Top, B );
|
|
end;
|
|
if frRight in Data.Frames then
|
|
begin
|
|
FillFrame( W - B, 0, W, H );
|
|
Dec( R.Right, B );
|
|
end;
|
|
if frBottom in Data.Frames then
|
|
begin
|
|
FillFrame( 0, H - B, W, H );
|
|
Dec( R.Bottom, B );
|
|
end;
|
|
DeleteObject( Br );
|
|
|
|
Br := CreateSolidBrush( Color2RGB( Self_.Color ) );
|
|
FillRect( DC, R, Br );
|
|
Inc( R.Left, Data.Paddings.LeftPadding );
|
|
Inc( R.Top, Data.Paddings.TopPadding );
|
|
Dec( R.Right, Data.Paddings.RightPadding );
|
|
Dec( R.Bottom, Data.Paddings.BottomPadding );
|
|
DeleteObject( Br );
|
|
|
|
case Self_.TextAlign of
|
|
taCenter: Fmt := DT_CENTER;
|
|
taRight: Fmt := DT_RIGHT;
|
|
else Fmt := DT_LEFT;
|
|
end;
|
|
case Self_.VerticalAlign of
|
|
vaTop: Fmt := Fmt or DT_TOP;
|
|
vaCenter: Fmt := Fmt or DT_VCENTER;
|
|
vaBottom: Fmt := Fmt or DT_BOTTOM;
|
|
end;
|
|
if Self_.WordWrap then
|
|
Fmt := Fmt or DT_WORDBREAK
|
|
else
|
|
Fmt := Fmt or DT_SINGLELINE;
|
|
OldFont := SelectObject( DC, Self_.Font.Handle );
|
|
|
|
OldBk := SetBkMode( DC, TRANSPARENT );
|
|
DrawText( DC, PChar( Self_.Caption ), Length( Self_.Caption ), R, Fmt );
|
|
SetBkMode( DC, OldBk );
|
|
SelectObject( DC, OldFont );
|
|
|
|
end;
|
|
|
|
function NewBand( AParent: PControl; Frames: TFrames ): PControl;
|
|
var Data: PFramesData;
|
|
begin
|
|
Result := NewPanel( AParent, esNone );
|
|
Result.Color := clWhite;
|
|
Result.Border := 1;
|
|
Data := AllocMem( Sizeof( TFramesData ) );
|
|
Result.CustomData := Data;
|
|
Data.Frames := Frames;
|
|
Data.Paddings.LeftPadding := 4;
|
|
Data.Paddings.RightPadding := 4;
|
|
Result.OnPaint := TOnPaint( MakeMethod( Result, @ PaintFrames ) );
|
|
Result.Width := 400;
|
|
Result.Height := 40;
|
|
Result.aAutoSzX := 12;
|
|
end;
|
|
|
|
procedure InitBandLabel( L: PControl; Frames: TFrames );
|
|
var Data: PFramesData;
|
|
begin
|
|
L.Color := clWhite;
|
|
L.Border := 1;
|
|
Data := AllocMem( Sizeof( TFramesData ) );
|
|
L.CustomData := Data;
|
|
Data.Frames := Frames;
|
|
Data.Paddings.LeftPadding := 4;
|
|
Data.Paddings.RightPadding := 4;
|
|
L.OnPaint := TOnPaint( MakeMethod( L, @ PaintFrames ) );
|
|
L.aAutoSzX := 12;
|
|
end;
|
|
|
|
function NewReportLabel( AParent: PControl; const Caption: String; Frames: TFrames ): PControl;
|
|
begin
|
|
Result := NewLabel( AParent, Caption ).AutoSize( TRUE );
|
|
InitBandLabel( Result, Frames );
|
|
end;
|
|
|
|
function NewWordWrapReportLabel( AParent: PControl; const Caption: String; Frames: TFrames ): PControl;
|
|
begin
|
|
Result := NewWordWrapLabel( AParent, Caption ).AutoSize( TRUE );
|
|
InitBandLabel( Result, Frames );
|
|
end;
|
|
|
|
procedure SetPaddings( BandCtl: PControl; LeftPadding, TopPadding, RightPadding, BottomPadding: Integer );
|
|
var Data: PFramesData;
|
|
WasHPadding: Integer;
|
|
begin
|
|
Data := BandCtl.CustomData;
|
|
WasHPadding := Data.Paddings.LeftPadding + Data.Paddings.RightPadding;
|
|
Data.Paddings.LeftPadding := LeftPadding;
|
|
Data.Paddings.TopPadding := TopPadding;
|
|
Data.Paddings.RightPadding := RightPadding;
|
|
Data.Paddings.BottomPadding := BottomPadding;
|
|
BandCtl.aAutoSzX := BandCtl.aAutoSzX - WasHPadding + LeftPadding + RightPadding;
|
|
if BandCtl.IsAutoSize then
|
|
BandCtl.AutoSize( TRUE );
|
|
end;
|
|
|
|
{ TReport }
|
|
|
|
procedure TReport.Abort;
|
|
begin
|
|
Clear;
|
|
if Assigned( FPrinter ) then
|
|
begin
|
|
if Printer.Printing then
|
|
Printer.Abort;
|
|
end;
|
|
end;
|
|
|
|
procedure TReport.AddBand(Band: PControl);
|
|
begin
|
|
AddBandEx( Band, blLeft );
|
|
end;
|
|
|
|
procedure TReport.AddBandEx(Band: PControl; BandLayout: TBandLayout);
|
|
var MF: TMF;
|
|
OldW: Integer;
|
|
begin
|
|
if FCurBandHeight > 0 then
|
|
begin
|
|
if not fNewBandHandling then
|
|
if Assigned( OnEndBand ) then
|
|
begin
|
|
fNewBandHandling := TRUE;
|
|
OnEndBand( @ Self );
|
|
fNewBandHandling := FALSE;
|
|
end;
|
|
FX := MarginsScreenPixels.Left;
|
|
FY := FY + FCurBandHeight;
|
|
end;
|
|
if Band.Height > HeightAvailable then
|
|
NewPage;
|
|
MF := CurrentPage;
|
|
case BandLayout of
|
|
blLeft: FY := FY + PaintBand( MF, Band, X, Y );
|
|
blRight: FY := FY + PaintBand( MF, Band, PagePixelsSize.cx - Band.Width, Y );
|
|
blCenter: FY := FY + PaintBand( MF, Band, (PagePixelsSize.cx - Band.Width) div 2, Y );
|
|
blExpandRight: begin
|
|
OldW := Band.Width;
|
|
try
|
|
Band.Width := PagePixelsSize.cx - MarginsScreenPixels.Right - X;
|
|
FY := FY + PaintBand( MF, Band, X, Y );
|
|
finally
|
|
Band.Width := OldW;
|
|
end;
|
|
end;
|
|
end;
|
|
FPageTop := FALSE;
|
|
FCurBandHeight := 0;
|
|
end;
|
|
|
|
procedure TReport.AddFooter(Band: PControl);
|
|
begin
|
|
AddFooterEx( Band, blLeft );
|
|
end;
|
|
|
|
procedure TReport.AddFooterEx(Band: PControl; BandLayout: TBandLayout);
|
|
var MF: TMF;
|
|
OldW: Integer;
|
|
begin
|
|
if Band.Height > HeightAvailable then
|
|
NewPage;
|
|
MF := CurrentPage;
|
|
case BandLayout of
|
|
blLeft: FBottom := FBottom - PaintBand( MF, Band, 0, FBottom - Band.Height );
|
|
blRight: FBottom := FBottom - PaintBand( MF, Band,
|
|
PagePixelsSize.cx - Band.Width, FBottom - Band.Height );
|
|
blCenter: FBottom := FBottom - PaintBand( MF, Band,
|
|
(PagePixelsSize.cx - Band.Width) div 2, FBottom - Band.Height );
|
|
blExpandRight: begin
|
|
OldW := Band.Width;
|
|
try
|
|
Band.Width := PagePixelsSize.cx -
|
|
MarginsScreenPixels.Left - MarginsScreenPixels.Right;
|
|
FBottom := FBottom - PaintBand( MF, Band, 0, FBottom - Band.Height );
|
|
finally
|
|
Band.Width := OldW;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TReport.AddPage: TMF;
|
|
var MF: TMF;
|
|
R: TRect;
|
|
DC0: HDC;
|
|
begin
|
|
DC0 := GetDC( 0 );
|
|
R := MakeRect( 0, 0,
|
|
MulDiv(PagePixelsSize.cx, GetDeviceCaps(DC0, HORZSIZE)*100, GetDeviceCaps(DC0, HORZRES)),
|
|
MulDiv(PagePixelsSize.cy, GetDeviceCaps(DC0, VERTSIZE)*100, GetDeviceCaps(DC0, VERTRES)) );
|
|
|
|
MF := CreateEnhMetaFile( DC0, nil, @ R, '' );
|
|
ReleaseDC( 0, DC0 );
|
|
|
|
FDCPages.Add( Pointer( MF ) );
|
|
Result := MF;
|
|
FPageTop := TRUE;
|
|
FBottom := PagePixelsSize.cy - MarginsScreenPixels.Bottom;
|
|
if not fNewPageHandling then
|
|
if Assigned( OnNewPage ) then
|
|
begin
|
|
fNewPageHandling := TRUE;
|
|
OnNewPage( @ Self );
|
|
fNewPageHandling := FALSE;
|
|
end;
|
|
end;
|
|
|
|
procedure TReport.AddRight(Band: PControl);
|
|
begin
|
|
AddRightEx( Band, blLeft );
|
|
end;
|
|
|
|
procedure TReport.AddRightEx(Band: PControl; BandLayout: TBandLayout);
|
|
var MF: TMF;
|
|
OldW: Integer;
|
|
begin
|
|
if Band.Height > HeightAvailable then
|
|
NewPage;
|
|
MF := CurrentPage;
|
|
if Band.Width > PagePixelsSize.cx - MarginsScreenPixels.Right - X then
|
|
begin
|
|
if not fNewBandHandling then
|
|
if Assigned( OnEndBand ) then
|
|
begin
|
|
fNewBandHandling := TRUE;
|
|
OnEndBand( @ Self );
|
|
fNewBandHandling := FALSE;
|
|
end;
|
|
FX := MarginsScreenPixels.Left;
|
|
FY := FY + FCurBandHeight;
|
|
FCurBandHeight := 0;
|
|
end;
|
|
case BandLayout of
|
|
blLeft: PaintBand( MF, Band, X, Y );
|
|
blRight: PaintBand( MF, Band, X + PagePixelsSize.cx - Band.Width, Y );
|
|
blCenter: PaintBand( MF, Band, X + (PagePixelsSize.cx - X - Band.Width) div 2, Y );
|
|
blExpandRight: begin
|
|
OldW := Band.Width;
|
|
try
|
|
Band.Width := PagePixelsSize.cx - MarginsScreenPixels.Right - X;
|
|
PaintBand( MF, Band, X, Y );
|
|
finally
|
|
Band.Width := OldW;
|
|
end;
|
|
end;
|
|
end;
|
|
FX := X + Band.Width;
|
|
if FCurBandHeight < Band.Height then
|
|
FCurBandHeight := Band.Height;
|
|
FPageTop := FALSE;
|
|
end;
|
|
|
|
procedure TReport.Clear;
|
|
begin
|
|
if FPreviewForm <> nil then
|
|
FPreviewForm.Form.Free;
|
|
ClearPages;
|
|
end;
|
|
|
|
destructor TReport.Destroy;
|
|
begin
|
|
Clear;
|
|
FDCPages.Free;
|
|
FHDPages.Free;
|
|
FDocName := '';
|
|
inherited;
|
|
end;
|
|
|
|
procedure TReport.DoPreview;
|
|
begin
|
|
if PageCount = 0 then Exit;
|
|
PreviewForm.Form.DoubleBuffered := DoubleBufferedPreview;
|
|
PreviewForm.FReport := @ Self;
|
|
PreviewForm.Form.Caption := FDocName;
|
|
PreviewForm.Form.Show;
|
|
end;
|
|
|
|
procedure TReport.DoPreviewModal;
|
|
begin
|
|
if PageCount = 0 then Exit;
|
|
PreviewForm.Form.DoubleBuffered := DoubleBufferedPreview;
|
|
PreviewForm.FReport := @ Self;
|
|
PreviewForm.Form.Caption := FDocName;
|
|
PreviewForm.Form.ShowModal;
|
|
FPreviewForm.Form.Free;
|
|
FPreviewForm := nil;
|
|
end;
|
|
|
|
procedure TReport.DoPrint;
|
|
begin
|
|
PrintPages( 0, PageCount-1 );
|
|
end;
|
|
|
|
procedure TReport.DoPrintPreview(Proc: TObjectMethod);
|
|
begin
|
|
if Printing then Abort;
|
|
if Assigned( FOnPrint ) then
|
|
begin
|
|
Clear;
|
|
FStage := 1;
|
|
FOnPrint( @ Self );
|
|
if PageCount = 0 then Exit;
|
|
Clear;
|
|
FStage := 2;
|
|
FOnPrint( @ Self );
|
|
end;
|
|
Proc;
|
|
end;
|
|
|
|
function TReport.GetCurrentPage: TMF;
|
|
begin
|
|
if PageCount = 0 then
|
|
Result := AddPage
|
|
else
|
|
Result := Pages[ PageCount-1 ];
|
|
end;
|
|
|
|
function TReport.GetOrientation: TPrinterOrientation;
|
|
begin
|
|
Result := Printer.Orientation;
|
|
end;
|
|
|
|
function TReport.GetPageHeight: Integer;
|
|
begin
|
|
GetPageWidthHeight;
|
|
Result := FPageHeight;
|
|
end;
|
|
|
|
function TReport.GetPagePixelsSize: TSize;
|
|
var I: Integer;
|
|
P: TPoint;
|
|
DC0: HDC;
|
|
begin
|
|
if (FPagePixelsSize.cx = 0) or (FPagePixelsSize.cy = 0) then
|
|
begin
|
|
case PaperSize of
|
|
psA3: P := MakePoint( 297, 420 );
|
|
psA4: P := MakePoint( 210, 297 );
|
|
psA5: P := MakePoint( 148, 210 );
|
|
psA6: P := MakePoint( 105, 148 );
|
|
psLetter: P := MakePoint( 216, 280 );
|
|
else P := MakePoint( FCustomPaperSize.cx, FCustomPaperSize.cy );
|
|
end;
|
|
DC0 := GetDC( 0 );
|
|
FPagePixelsSize.cx := Round( (P.x * 0.039370) * GetDeviceCaps( DC0, LOGPIXELSX ) );
|
|
FPagePixelsSize.cy := Round( (P.y * 0.039370) * GetDeviceCaps( DC0, LOGPIXELSY ) );
|
|
ReleaseDC( 0, DC0 );
|
|
end;
|
|
Result := FPagePixelsSize;
|
|
if Orientation = poLandscape then
|
|
begin
|
|
I := Result.cx;
|
|
Result.cx := Result.cy;
|
|
Result.cy := I;
|
|
end;
|
|
end;
|
|
|
|
function TReport.GetPageCount: Integer;
|
|
begin
|
|
Result := FDCPages.Count;
|
|
end;
|
|
|
|
function TReport.GetPageWidth: Integer;
|
|
begin
|
|
GetPageWidthHeight;
|
|
Result := FPageWidth;
|
|
end;
|
|
|
|
procedure TReport.GetPageWidthHeight;
|
|
begin
|
|
if (FPageWidth <> 0) and (FPageHeight <> 0) then Exit;
|
|
if Printer.Printing then
|
|
begin
|
|
FPageWidth := Printer.PageWidth;
|
|
FPageHeight := Printer.PageHeight;
|
|
end
|
|
else
|
|
begin
|
|
Printer.BeginDoc;
|
|
TRY
|
|
FPageWidth := Printer.PageWidth;
|
|
FPageHeight := Printer.PageHeight;
|
|
FINALLY
|
|
Printer.Abort;
|
|
END;
|
|
end;
|
|
end;
|
|
|
|
function TReport.GetPreviewForm: PPreviewObj;
|
|
begin
|
|
if FPreviewForm = nil then
|
|
begin
|
|
NewPreviewForm( FPreviewForm, Applet );
|
|
FPreviewForm.FReport := @ Self;
|
|
end;
|
|
Result := FPreviewForm;
|
|
end;
|
|
|
|
function TReport.GetPrinter: PPrinter;
|
|
begin
|
|
if FPrinter = nil then
|
|
FPrinter := GetProviderPrinter;
|
|
Result := FPrinter;
|
|
end;
|
|
|
|
function TReport.HeightAvailable: Integer;
|
|
begin
|
|
Result := FBottom - FY;
|
|
end;
|
|
|
|
procedure TReport.NewPage;
|
|
begin
|
|
FY := MarginsScreenPixels.Top;
|
|
FX := MarginsScreenPixels.Left;
|
|
AddPage;
|
|
end;
|
|
|
|
function TReport.PaintBand(MF: TMF; Band: PControl; Xpos, Ypos: Integer): Integer;
|
|
|
|
procedure PaintBandWithChildren( Band: PControl; DC: HDC );
|
|
var I: Integer;
|
|
C: PControl;
|
|
P0, P: TPoint;
|
|
R0, R1, R2: TRect;
|
|
Save: Integer;
|
|
FontHeight0Replaced: Boolean;
|
|
begin
|
|
FontHeight0Replaced := FALSE;
|
|
if (ReplaceFontHeight0 <> 0) and (Band.Font.FontHeight = 0) then
|
|
begin
|
|
FontHeight0Replaced := TRUE;
|
|
Band.Font.FontHeight := ReplaceFontHeight0;
|
|
end;
|
|
Band.Perform( WM_PRINT, DC, PRF_NONCLIENT );
|
|
GetClientRect( Band.Handle, R0 );
|
|
P0 := MakePoint( 0, 0 );
|
|
ClientToScreen( Band.Handle, P0 );
|
|
GetWindowOrgEx( DC, P );
|
|
GetWindowRect( Band.Handle, R1 );
|
|
OffsetRect( R0, P0.x - R1.Left, P0.y - R1.Top );
|
|
SetWindowOrgEx( DC, P.x - (P0.x - R1.Left), P.y - (P0.y - R1.Top), @ P );
|
|
IntersectClipRect( DC, R0.Left, R0.Top, R0.Right, R0.Bottom );
|
|
Band.Perform( WM_ERASEBKGND, DC, 0 );
|
|
Band.Perform( WM_PAINT, DC, 0 );
|
|
GetWindowRect( Band.Handle, R1 );
|
|
for I := 0 to Band.ChildCount-1 do
|
|
begin
|
|
Save := SaveDC( DC );
|
|
C := Band.Children[ I ];
|
|
GetWindowRect( C.Handle, R2 );
|
|
SetWindowOrgEx( DC, P.x - (R2.Left - R1.Left), P.y - (R2.Top - R1.Top), nil );
|
|
IntersectClipRect( DC, 0, 0, R2.Right - R2.Left, R2.Bottom - R2.Top );
|
|
PaintBandWithChildren( C, DC );
|
|
RestoreDC( DC, Save );
|
|
end;
|
|
if FontHeight0Replaced then
|
|
Band.Font.FontHeight := 0;
|
|
end;
|
|
|
|
var OldParent: PControl;
|
|
WasVisible: Boolean;
|
|
WasBR: TRect;
|
|
P: TPoint;
|
|
Save: Integer;
|
|
|
|
begin
|
|
OldParent := Band.Parent;
|
|
OldParent.CreateWindow;
|
|
WasVisible := Band.Visible;
|
|
WasBR := Band.BoundsRect;
|
|
try
|
|
Band.Visible := FALSE;
|
|
Band.Parent := Applet;
|
|
Band.Top := Applet.Height;
|
|
SetParent( Band.GetWindowHandle, Applet.Handle );
|
|
Band.Visible := TRUE;
|
|
|
|
Save := SaveDC( MF );
|
|
GetWindowOrgEx( MF, P );
|
|
SetWindowOrgEx( MF, P.x - Xpos, P.y - Ypos, nil );
|
|
|
|
PaintBandWithChildren( Band, MF );
|
|
|
|
SetWindowOrgEx( MF, P.x, P.y, nil );
|
|
RestoreDC( MF, Save );
|
|
|
|
finally
|
|
Band.Visible := FALSE;
|
|
Band.Parent := OldParent;
|
|
SetParent( Band.Handle, OldParent.Handle );
|
|
Band.BoundsRect := WasBR;
|
|
Band.Visible := WasVisible;
|
|
end;
|
|
Result := Band.Height;
|
|
end;
|
|
|
|
procedure TReport.Preview;
|
|
begin
|
|
DoPrintPreview( DoPreview );
|
|
end;
|
|
|
|
procedure TReport.PreviewModal;
|
|
begin
|
|
DoPrintPreview( DoPreviewModal );
|
|
end;
|
|
|
|
procedure TReport.Print;
|
|
begin
|
|
DoPrintPreview( DoPrint );
|
|
end;
|
|
|
|
function TReport.ScaleX(W: Integer): Integer;
|
|
begin
|
|
Result := Round( W * Printer.PageWidth / PagePixelsSize.cx );
|
|
end;
|
|
|
|
function TReport.ScaleY(H: Integer): Integer;
|
|
begin
|
|
Result := Round( H * Printer.PageHeight / PagePixelsSize.cy );
|
|
end;
|
|
|
|
procedure TReport.SetCustomPaperSize(const Value: TSize);
|
|
const PapSizes: array[ TPaperSize, 1..2] of Integer = ( ( 210, 297 ),
|
|
( 148, 210 ), ( 105, 148 ), ( 297, 420 ), (216, 280), ( 0, 0 ) );
|
|
var PSidx: TPaperSize;
|
|
begin
|
|
FCustomPaperSize := Value;
|
|
for PSidx := Low( TPaperSize ) to Pred( High( TPaperSize ) ) do
|
|
begin
|
|
if (PapSizes[ PSidx ][ 1 ] = Value.cx) and
|
|
(PapSizes[ PSidx ][ 2 ] = Value.cy) then
|
|
begin
|
|
PaperSize := PSidx;
|
|
exit;
|
|
end;
|
|
end;
|
|
PaperSize := psCustom;
|
|
end;
|
|
|
|
procedure TReport.SetPageTop(const Value: Boolean);
|
|
begin
|
|
FPageTop := Value;
|
|
end;
|
|
|
|
procedure TReport.SetPaperSize(const Value: TPaperSize);
|
|
begin
|
|
if FPaperSize = Value then Exit;
|
|
if FPrinting then Abort;
|
|
FPaperSize := Value;
|
|
end;
|
|
|
|
procedure TReport.SetPreviewForm(const Value: PPreviewObj);
|
|
begin
|
|
if FPreviewForm = Value then Exit;
|
|
if FPreviewForm <> nil then
|
|
FPreviewForm.Form.Free;
|
|
FPreviewForm := Value;
|
|
end;
|
|
|
|
procedure TReport.SetPrinter(const Value: PPrinter);
|
|
begin
|
|
if FPrinter = Value then Exit;
|
|
if FPrinting then Abort;
|
|
FPrinter := Value;
|
|
FPageWidth := 0;
|
|
FPageHeight := 0;
|
|
end;
|
|
|
|
procedure TReport.SetX(const Value: Integer);
|
|
begin
|
|
if FX = Value then Exit;
|
|
FX := Value;
|
|
end;
|
|
|
|
procedure TReport.SetY(const Value: Integer);
|
|
begin
|
|
if FY = Value then Exit;
|
|
FY := Value;
|
|
FCurBandHeight := 0;
|
|
end;
|
|
|
|
function TReport.GetPages(Idx: Integer): TMF;
|
|
begin
|
|
Result := TMF( FDCPages.Items[ Idx ] );
|
|
end;
|
|
|
|
function TReport.GetImages(Idx: Integer): HENHMETAFILE;
|
|
begin
|
|
while FHDPages.Count <= Idx do
|
|
FHDPages.Add( nil );
|
|
if FHDPages.Items[ Idx ] = nil then
|
|
begin
|
|
FHDPages.Items[ Idx ] := Pointer( CloseEnhMetafile( Pages[ Idx ] ) );
|
|
FDCPages.Items[ Idx ] := nil;
|
|
end;
|
|
Result := HENHMETAFILE( FHDPages.Items[ Idx ] );
|
|
end;
|
|
|
|
procedure TReport.PrintPages(FromPage, ToPage: Integer);
|
|
var I: Integer;
|
|
MF: HENHMETAFILE;
|
|
PrintingStarted: Boolean;
|
|
N: Integer;
|
|
begin
|
|
PrintingStarted := FALSE;
|
|
TRY
|
|
for I := FromPage to ToPage do
|
|
begin
|
|
MF := Images[ I ];
|
|
if I = 0 then
|
|
begin
|
|
Printer.Title := FDocName;
|
|
Printer.BeginDoc;
|
|
PrintingStarted := TRUE;
|
|
end;
|
|
N := 1;
|
|
while PageWidth > PagePixelsSize.cx * N do
|
|
Inc( N );
|
|
PlayEnhMetaFile( Printer.Canvas.Handle, MF,
|
|
MakeRect( 0, 0, PageWidth-1, PageHeight-1 ) );
|
|
|
|
if I < ToPage then
|
|
Printer.NewPage;
|
|
end;
|
|
FINALLY
|
|
if PrintingStarted then
|
|
Printer.EndDoc;
|
|
END;
|
|
end;
|
|
|
|
procedure TReport.ClearPages;
|
|
var I: Integer;
|
|
begin
|
|
for I := PageCount-1 downto 0 do
|
|
DeleteEnhMetaFile( Images[ I ] );
|
|
FDCPages.Clear;
|
|
FHDPages.Clear;
|
|
FY := MarginsScreenPixels.Top;
|
|
FX := MarginsScreenPixels.Left;
|
|
FPagePixelsSize.cx := 0; // force recalculation of Page size
|
|
end;
|
|
|
|
procedure TReport.SetMargins(const Value: TMargins);
|
|
begin
|
|
if (fMargins.Left = Value.Left) and
|
|
(fMargins.Top = Value.Top) and
|
|
(fMargins.Right = Value.Right) and
|
|
(fMargins.Bottom = Value.Bottom) then Exit;
|
|
if FPrinting then Abort;
|
|
FMargins := Value;
|
|
end;
|
|
|
|
function TReport.GetMarginsPixels( const Index: Integer ): TMargins;
|
|
var DC: HDC;
|
|
begin
|
|
if Index = 1 then DC := Printer.Canvas.Handle
|
|
else DC := GetDC( 0 );
|
|
Result.Left := Round( Margins.Left / 1000 / 2.55 * GetDeviceCaps( DC, LOGPIXELSX ) );
|
|
Result.Right := Round( Margins.Right / 1000 / 2.55 * GetDeviceCaps( DC, LOGPIXELSX ) );
|
|
Result.Top := Round( Margins.Top / 1000 / 2.55 * GetDeviceCaps( DC, LOGPIXELSY ) );
|
|
Result.Bottom := Round( Margins.Bottom / 1000 / 2.55 * GetDeviceCaps( DC, LOGPIXELSY ) );
|
|
if Index <> 1 then
|
|
ReleaseDC( 0, DC );
|
|
end;
|
|
|
|
{ TPreviewObj }
|
|
|
|
procedure TPreviewObj.AdjustButtons( Sender: PObj );
|
|
begin
|
|
TB.TBButtonEnabled[ TBFrst ] := FCurPage > 0;
|
|
TB.TBButtonEnabled[ TBPrev ] := FCurPage > 0;
|
|
TB.TBButtonEnabled[ TBNext ] := FCurPage < PageCount - 1;
|
|
TB.TBButtonEnabled[ TBLast ] := FCurPage < PageCount - 1;
|
|
TB.TBButtonEnabled[ TBPrnt ] := PageCount > 0;
|
|
{$IFDEF use_MHPRINTER}
|
|
TB.TBButtonEnabled[ TBExit ] := TRUE;
|
|
{$ENDIF}
|
|
if PageCount = 0 then
|
|
LB.Caption := ''
|
|
else
|
|
LB.Caption := 'Page ' + Int2Str( FCurPage + 1 ) + ' from ' + Int2Str( PageCount );
|
|
end;
|
|
|
|
procedure TPreviewObj.AdjustFitMode;
|
|
var K: Double;
|
|
begin
|
|
if PageCount = 0 then Exit;
|
|
case FFitMode of
|
|
0: begin // fit Height
|
|
PB.Height := SB.ClientHeight;
|
|
K := FReport.PagePixelsSize.cx / FReport.PagePixelsSize.cy;
|
|
PB.Width := Round( K * SB.ClientHeight );
|
|
SetScrollPos( SB.Handle, SB_VERT, 0, TRUE );
|
|
end;
|
|
1: begin // fit Width
|
|
PB.Width := SB.ClientWidth;
|
|
K := FReport.PagePixelsSize.cy / FReport.PagePixelsSize.cx;
|
|
PB.Height := Round( K * SB.ClientWidth );
|
|
end;
|
|
2: begin // 1:1
|
|
PB.Width := FReport.PagePixelsSize.cx;
|
|
PB.Height := FReport.PagePixelsSize.cy;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
destructor TPreviewObj.Destroy;
|
|
begin
|
|
FBuf.Free;
|
|
PSD.Free;{Brandys}
|
|
inherited;
|
|
end;
|
|
|
|
function TPreviewObj.PageCount: Integer;
|
|
begin
|
|
Result := FReport.FDCPages.Count;
|
|
end;
|
|
|
|
procedure TPreviewObj.PaintPage(Sender: PControl; DC: HDC);
|
|
var MF: HENHMETAFILE;
|
|
Tmp: PBitmap;
|
|
R: TRect;
|
|
begin
|
|
if FCurPage >= PageCount then Exit;
|
|
MF := FReport.Images[ FCurPage ];
|
|
AdjustFitMode;
|
|
{if (PB.Width = FReport.PagePixelsSize.cx) and
|
|
(PB.Height = FReport.PagePixelsSize.cy) then
|
|
PlayEnhMetaFile( DC, MF, MakeRect( 0, 0, PB.Width, PB.Height ) )
|
|
else}
|
|
begin
|
|
if (FBufPage <> FCurPage) or (FBuf = nil) or
|
|
(FBuf.Width <> PB.ClientWidth) or (FBuf.Height <> PB.ClientHeight) then
|
|
begin
|
|
FBuf.Free;
|
|
FBufPage := FCurPage;
|
|
FBuf := NewDIBBitmap( PB.ClientWidth, PB.ClientHeight, pf24bit );
|
|
FBuf.Canvas.Brush.Color := clWhite;
|
|
FBuf.Canvas.FillRect( MakeRect( 0, 0, FBuf.Width, FBuf.Height ) );
|
|
SetStretchBltMode( FBuf.Canvas.Handle, HALFTONE );
|
|
SetBrushOrgEx( FBuf.Canvas.Handle, 0, 0, nil );
|
|
{R := MakeRect( FReport.MarginsScreenPixels.Left,
|
|
FReport.MarginsScreenPixels.Top,
|
|
FBuf.Width-1 - FReport.MarginsScreenPixels.Right,
|
|
FBuf.Height-1 - FReport.MarginsScreenPixels.Bottom );}
|
|
R := MakeRect( 0, 0, FBuf.Width-1, FBuf.Height-1 );
|
|
if FBuf.Width >= FReport.PagePixelsSize.cx then
|
|
PlayEnhMetaFile( FBuf.Canvas.Handle, MF, R )
|
|
else
|
|
begin
|
|
Tmp := NewDIBBitmap( FReport.PagePixelsSize.cx, FReport.PagePixelsSize.cy, pf24bit );
|
|
Tmp.Canvas.Brush.Color := clWhite;
|
|
Tmp.Canvas.FillRect( MakeRect( 0, 0, Tmp.Width, Tmp.Height ) );
|
|
PlayEnhMetaFile( Tmp.Canvas.Handle, MF, MakeRect( 0, 0, Tmp.Width-1, Tmp.Height-1 ) );
|
|
Inc( R.Right ); Inc( R.Bottom );
|
|
Tmp.StretchDraw( FBuf.Canvas.Handle, R );
|
|
Tmp.Free;
|
|
end;
|
|
end;
|
|
FBuf.Draw( DC, 0, 0 );
|
|
end;
|
|
end;
|
|
|
|
{$IFDEF use_MHPRINTER}
|
|
procedure TPreviewObj.PrinterSetup;
|
|
begin
|
|
ShowMessage( 'Not implementer.' );
|
|
end;
|
|
{$ELSE}
|
|
procedure TPreviewObj.PrinterSetup;
|
|
var
|
|
Orientation: TPrinterOrientation;
|
|
PgSz: TSize;
|
|
M: TRect;
|
|
begin
|
|
Orientation := Printer.Orientation;
|
|
PgSz.cx := Printer.PageWidth;
|
|
PgSz.cy := Printer.PageHeight;
|
|
if not Assigned( FReport.OnPrint ) then
|
|
Options := Options - [ psdOrientation ];
|
|
if PSD = nil then
|
|
PSD := NewPageSetupDialog( Form, Options );
|
|
PSD.SetMargins( FReport.FMargins.Left, FReport.FMargins.Top,
|
|
FReport.FMargins.Right, FReport.FMargins.Bottom );
|
|
if PSD.Execute then
|
|
begin
|
|
Printer.Assign(PSD.Info);//assign selected options to printer DC
|
|
M := PSD.GetMargins;
|
|
if Assigned( FReport.OnPrint ) then
|
|
if (Printer.Orientation <> Orientation) or
|
|
(Printer.PageWidth <> PgSz.cx) or
|
|
(Printer.PageHeight <> PgSz.cy) or
|
|
not CompareMem( @ M, @ FReport.FMargins, Sizeof( M ) ) then
|
|
begin
|
|
FReport.FMargins := M;
|
|
FCurPage := 0;
|
|
FReport.ClearPages;
|
|
PgSz.cx := GetDeviceCaps( Printer.Canvas.Handle, HORZSIZE );
|
|
PgSz.cy := GetDeviceCaps( Printer.Canvas.Handle, VERTSIZE );
|
|
FReport.CustomPaperSize := PgSz;
|
|
FReport.OnPrint( FReport );
|
|
end;
|
|
Printer.AssignMargins(M,mgMillimeters);
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
procedure TPreviewObj.PrintAllPages;
|
|
begin
|
|
FReport.DoPrint;
|
|
end;
|
|
|
|
procedure TPreviewObj.ResizePreviewForm(Sender: PObj);
|
|
begin
|
|
AdjustFitMode;
|
|
end;
|
|
|
|
procedure TPreviewObj.SetCurPage(const Value: Integer);
|
|
begin
|
|
FCurPage := Value;
|
|
AdjustButtons( @ Self );
|
|
end;
|
|
|
|
procedure TPreviewObj.SetFitMode(const Value: Integer);
|
|
begin
|
|
if FFitMode = Value then Exit;
|
|
FFitMode := Value;
|
|
AdjustFitMode;
|
|
PB.Invalidate;
|
|
end;
|
|
|
|
procedure TPreviewObj.TBClick(Sender: PObj);
|
|
begin
|
|
case PControl(Sender).CurIndex of
|
|
TBFrst: { << } FCurPage := 0;
|
|
TBPrev: { < } if FCurPage > 0 then Dec( FCurPage );
|
|
TBNext: { > } if FCurPage < PageCount - 1 then Inc( FCurPage );
|
|
TBLast: { >> } FCurPage := PageCount - 1;
|
|
TBPrnt: {Print} PrintAllPages;
|
|
TBSetu: {Setup} PrinterSetup;
|
|
TBView: {View} TBDropDownViewMenu( TB );
|
|
TBExit: {Close} begin Form.Close; Exit; end;
|
|
end;
|
|
AdjustButtons( @ Self );
|
|
end;
|
|
|
|
procedure TPreviewObj.TBDropDownViewMenu(Sender: PObj);
|
|
var R: TRect;
|
|
begin
|
|
R := TB.TBButtonRect[ TBView ];
|
|
R.Top := R.Bottom;
|
|
R.TopLeft := TB.Client2Screen( R.TopLeft );
|
|
ViewMenu.RadioCheck( FitMode );
|
|
ViewMenu.Popup( R.Left, R.Top );
|
|
end;
|
|
|
|
procedure TPreviewObj.TBViewMenuClick(Sender: PMenu; Item: Integer);
|
|
begin
|
|
FitMode := Item;
|
|
end;
|
|
|
|
end.
|