Contributor: ANGUS JOHNSON


Delphi1 & Delphi2.

This unit is to replace QuickReport's Preview Form.

Advantages:
  1. cursor keys can be used to move around the preview page.
  2. [page_up] and [page_down] keys used to move between pages
  3. [home] or [ctrl][page_up] to move to first page
  4. [end] or [ctrl][page_down] to move to last page

  5. automatically fills entire screen (except task bar)


Usage:

  1. Make sure QuickRep is in the uses clause on your MainForm.
  2. Add this Preview unit to your project.
  3. Add the following procedure to your MainForm -
	procedure TMainForm.MyPreview;
	begin
	   FmPreview.ShowModal;
	end;
  4. add -
	QRPrinter.OnPreview := MyPreview;
     to your code (or place it in FormCreate method) before calling -
	YourReport.Quickreport1.preview;


Angus Johnson
ajohnson@rpi.net.au


unit Preview;

interface

uses
  SysUtils, Classes, Controls, Forms, Quickrep, ExtCtrls, Messages,
  StdCtrls, Buttons, WinTypes, WinProcs, Dialogs, Printers,
  IniFiles;

type
  TFmPreview = class(TForm)
	 Panel1: TPanel;
	 QRPreview1: TQRPreview;
	 Label1: TLabel;
	 PrintDialog1: TPrintDialog;
	 bbPrev: TBitBtn;
	 bbNext: TBitBtn;
	 bbZoomOut: TBitBtn;
	 bbZoomW: TBitBtn;
	 bbZoomIn: TBitBtn;
	 bbPrint: TBitBtn;
    bbClose: TBitBtn;
	 procedure FormShow(Sender: TObject);
	 procedure bbZoomOutClick(Sender: TObject);
	 procedure bbZoomWClick(Sender: TObject);
	 procedure bbPrevClick(Sender: TObject);
	 procedure bbNextClick(Sender: TObject);
	 procedure bbPrintClick(Sender: TObject);
	 procedure bbZoomInClick(Sender: TObject);
	 procedure bbCloseClick(Sender: TObject);
	 procedure FormActivate(Sender: TObject);
	 procedure FormClose(Sender: TObject; var Action: TCloseAction);
	 procedure FormKeyDown(Sender: TObject; var Key: Word;
	   Shift: TShiftState);
  private
	 procedure CMDialogKey(var message: TCMDialogKey); message CM_DIALOGKEY;
  public
  end;

var
  FmPreview: TFmPreview;

implementation

uses
  Main;

{$R *.DFM}


procedure TFmPreview.FormShow(Sender: TObject);
begin
	QRPreview1.Zoom := 100; {defaults to ZoomIn}
	Label1.caption := 'Page 1 of ' +inttostr(QRPrinter.PageCount);
	if QRPrinter.PageCount = 1 then bbNext.enabled := false
	else bbNext.enabled := true;
	bbClose.setfocus;
	bbZoomIn.enabled := false;
	bbZoomW.enabled := true;
	bbZoomOut.enabled := true;
end;

procedure TFmPreview.bbZoomOutClick(Sender: TObject);
begin
	QRPreview1.ZoomToFit;
	bbZoomOut.enabled := false;
	bbZoomW.enabled := true;
	bbZoomIn.enabled := true;
	bbClose.setfocus;
end;

procedure TFmPreview.bbZoomWClick(Sender: TObject);
begin
	QRPreview1.ZoomToWidth;
	bbZoomW.enabled := false;
	bbZoomOut.enabled := true;
	bbZoomIn.enabled := true;
	bbClose.setfocus;
end;

procedure TFmPreview.bbPrevClick(Sender: TObject);
begin {Previous page}
  if QRPreview1.PageNumber > 1 then
         QRPreview1.PageNumber := QRPreview1.PageNumber-1;
  Label1.caption := 'Page ' + inttostr(QRPreview1.PageNumber)+
                        ' of ' +inttostr(QRPrinter.PageCount);
  bbNext.enabled := true;
  if QRPreview1.PageNumber = 1 then begin
	 bbPrev.enabled := false;
	 bbNext.setfocus;
  end;
end;

procedure TFmPreview.bbNextClick(Sender: TObject);
begin {Next page}
  if QRPreview1.PageNumber < QRPrinter.PageCount then
					QRPreview1.PageNumber := QRPreview1.PageNumber+1;
  Label1.caption := 'Page ' + inttostr(QRPreview1.PageNumber)+
					' of ' +inttostr(QRPrinter.PageCount);
  bbPrev.enabled := true;
  if QRPreview1.PageNumber = QRPrinter.PageCount then begin
	 bbNext.enabled := false;
	 bbPrev.setfocus;
  end;
end;

procedure TFmPreview.bbPrintClick(Sender: TObject);
begin
  {A PrintDialog component can be added to the form with an -
  if not PrintDialog1.execute then exit -
  statement placed here.}
  screen.cursor := crHourglass;
  try
	 QRPrinter.Print;
	 while tag > 1 do begin
	   QRPrinter.Print;
	   tag := tag-1;
	 end;
	 tag := 1;
  finally
	 screen.cursor := crDefault;
  end;
  close;
end;

procedure TFmPreview.bbZoomInClick(Sender: TObject);
begin
	QRPreview1.Zoom := 100;
	bbZoomIn.enabled := false;
	bbZoomW.enabled := true;
	bbZoomOut.enabled := true;
	bbClose.setfocus;
end;

procedure TFmPreview.bbCloseClick(Sender: TObject);
begin
	close;
end;

procedure TFmPreview.FormActivate(Sender: TObject);
var
  TrayHwnd: HWnd;
  Rect: TRect;
  CxFullScreen, CyFullScreen, CyCaption: integer;
begin
  {size the form to fill the screen...}
  TrayHwnd := FindWindow('Shell_TrayWnd','');
  if TrayHwnd = 0 then {not Win95 screen}
	 WindowState := wsMaximized
  else begin
	 GetWindowRect(TrayHwnd,Rect);
	 CxFullScreen    := GetSystemMetrics(SM_CXFULLSCREEN);
	 CyFullScreen    := GetSystemMetrics(SM_CYFULLSCREEN);
	 CyCaption       := GetSystemMetrics(SM_CYCAPTION);

	 {NOTE: Position must equal either poDefault or poDesigned,
	  and WindowState = wsNormal}
	 Top      := 0;
	 Left     := 0;
	 Width    := CxFullScreen;
	 Height   := CyFullScreen + CyCaption;

	 if (Rect.Top < 0) and (Rect.Left < 0) then begin
	   {Taskbar on either top or left}
	   if Rect.Right > Rect.Bottom then {Taskbar on top}
		 Top  := Rect.Bottom
	   else {Taskbar on left}
		 Left := Rect.Right;
	 end;
  end;
  bbClose.left := width - 76;
  bbPrint.left := width - 144;
end;

procedure TFmPreview.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  QRPreview1.PageNumber := 1; {this is necessary if reopening form!!!?}
  bbPrev.enabled := false;
  QRPreview1.HorzScrollbar.Position := 0;
  QRPreview1.VertScrollbar.Position := 0;
end;

procedure TFmPreview.CMDialogKey(var message: TCMDialogKey);
begin {INTERCEPTS ARROW KEYS INORDER TO MOVE AROUND PAGE}
  with message do
	 case CharCode of
	   VK_LEFT: begin
		 with QRPreview1.HorzScrollbar do Position := Position -50;
		 exit;
		 end;
		VK_RIGHT: begin
		 with QRPreview1.HorzScrollbar do Position := Position +50;
		 exit;
		 end;
		VK_UP: begin
		 with QRPreview1.VertScrollbar do Position := Position -50;
		 exit;
		 end;
		VK_DOWN: begin
		 with QRPreview1.VertScrollbar do Position := Position +50;
		 exit;
		 end;
	 end;
  inherited;
end;

procedure TFmPreview.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin {INTERCEPTS [PG_UP],[PG_DN], [CTRL][PG_UP],[CTRL][PG_DN], [HOME],[END]}
  if (((Key = VK_NEXT) and (Shift = [ssCtrl])) or (Key = VK_END))
											and bbNext.enabled then begin
	 QRPreview1.PageNumber := QRPrinter.PageCount; {GOTO LAST PAGE}
	 Label1.caption := 'Page ' + inttostr(QRPrinter.PageCount)+
					  ' of ' +inttostr(QRPrinter.PageCount);
	 bbPrev.enabled := true;
	 bbNext.enabled := false;
	 bbPrev.setfocus;
	 end
  else if (((Key = VK_PRIOR) and (Shift = [ssCtrl])) or (Key = VK_HOME))
											 and bbPrev.enabled then begin
	 QRPreview1.PageNumber := 1; {GOTO FIRST PAGE}
	 Label1.caption := 'Page 1' +
					  ' of ' +inttostr(QRPrinter.PageCount);
	 bbPrev.enabled := false;
	 bbNext.enabled := true;
	 bbNext.setfocus;
	 end
  else if (Key = VK_NEXT) and bbNext.enabled then bbNextClick(Sender)
  else if (Key = VK_PRIOR) and bbPrev.enabled then bbPrevClick(Sender);
end;

end.

{ the following contains additional files that should be included with this
  file.  To extract, you need XX3402 available with the SWAG distribution.

  1.     Cut the text below out, and save to a file  ..  filename.xx
  2.     Use XX3402  :   xx3402 d filename.xx
  3.     The decoded file should be created in the same directory.
  4.     If the file is a archive file, use the proper archive program to
         extract the members.

{ ------------------            CUT              ----------------------}

*XX3402-001873-240597--72--85-09701-----PREVIEW.DFM--1-OF--1
zkc+J2NBI373JYZ3Jk+k21o5++-II2Mk0ZF4PJ-mNLNdNLQ7FapEQaJqOKJr-2lZNbE0++BI
Pr+0++h0Pr7YNL77MqxiQkgAMaZHSLBoNKpBNKtp++d-RLFjIqBmPqlg0+R1ML-oOKxi-UpE
QaZiR0-EQaJqOKJr12BgOKJiR2VZOKRcR+Cn+Eh1P4ZZPbFLOKFoO+Bs+Ud4Pqto9YBjP4xm
-klXP3RdPaFjRpFZS5E9FaxiR0t6NKZbO5E0x+Z4Pqto9YtVPKI4-I3mOK3g0YNjPbEiIrFt
P4I9++d9NLZEQaJqOKJr0EpEOLVZP5BENL77PaBc+a+6I4xnOLFdPqs51b-jIqBmNKJiEqJi
R4Jm-ZBXMKlZN+U8Hqt-MrFdRa3oNEQAFaxmPI3XR4ZqMLFZ-oxiEqljQqI50INjQap1P4xn
NEZDPYhZSIFjRqs50oNjQap9NLZ2PrRi-YxiIqVjRkQ6FaxmPJBcPrQ8J4JsR2VZOKRcR+6D
++NII43iNKk4I43iNKkl-2lZNbE0++BIPr+0++JLOKFoO+Bs+UN6NKZbO5E04UJ-P4ZbPUQ3
MKlIPr+6J43WHr7YNL60+++4J2lVMaJg-YlVMaJgAEFANKNo+sU++pFjQ+64-JRdN5Fc+b+4
G4JdNqVo+Uw7EKldNqthNKto-kVoMIBZPbFZQUV-RLFjIqZuNEU5Eq3kR4ZjPUM9I43bNG+l
64xa612+++RIEaZoEbFi-a7WI57ZRUFANKNo+U21J4xk+U63JqZYR4U0EUN6NKZbO5E03UR1
ML-oOKxi-UdEQaIaRW-EMKRZ-oJiMK7gNKE603FVMYxmN4Jm+U+5Hqt1P4ZXOkQ9Ma7EQaJq
EqldMqg+++RIEaZoEbFi-a7WHaJsR+FANKNo+YE1J4xk+U63JqZYR4U0EUN6NKZbO5E03UR1
ML-oOKxi-UcaHaJsR0-EMKRZ03FVMYxmN4Jm+U25Hqt1P4ZXOkQ9Ma7CNLVoEqldMqg+++RI
EaZoEbFi0K7WKaxjPIxpR+FANKNo+zc++pFjQ+60-JRdN5Fc+YQ4G4JdNqVo+VM5Eq3kR4Zj
PUM7KaxjPG+aHrJo03FVMYxmN4Jm+U65Hqt1P4ZXOkQCMa7OPqxhHrJoEqldMqg+++RIEaZo
EbFi-q7WKaxjPJQ2H4JaR+B0+EBIPr+0+UJLOKFoO+77-YVZOKRcR+6K-oBVQ5FdPqs40p-V
NqIU7ZRdN5Fc03FVMYxmN4Jm+UA5Hqt1P4ZXOkQAMa7OPqxhJoBgOKBf+++5J27dR27oPUVW
MZdjPqp7PUFANKNo+sk-+pFjQ+60-JRdN5Fc+YQ4G4JdNqVo+VM5Eq3kR4ZjPUM6KaxjPG+a
GKs5FKtVMalZN+U6J43WHr7YNL60-+RDPYBgOKBf-kpWMZdjPqp7PYBgOKBf+++5J27dR27o
PURWMZ-mOKto-2lZNbE1wE21J4xk+U63JqZYR4U0EUN6NKZbO5E03UR1ML-oOKxi-UNEQaZi
7bE6J43WHr7YNL60-ERDPYBgOKBf-klWMZ-mOKtoEqldMqg+++RIEaZoEbFi-q7WEqljQqI2
H4JaR+Ao+UBIPr+0+UJLOKFoO+70-YVZOKRcR+6K-YBVPaBZP+Y5Eq3kR4ZjPUM47YBgPrBZ
03FVMYxmN4Jm+UM5Hqt1P4ZXOkQAMa71P4xnNIBgOKBf0YRgSL-c9YFVR428M+2++3k-++-0
HJk-++++++++RU+++0U++++F++++2E++++2+-+++++++n+++++++++++++++++++++++++++
++++++0+++0+++++U6++U++++6++U+0+U+++kA1++60+U++++Dw++Dw+++1zzk1z++++zk1z
+Dzz++1zzzw+RrRrRrRrRrRk++++Xzzzzzzzzzzk++++VrRrRrRrRrTk++++VsW6RrRsW6Tk
++++VsaNVrS7aMTk++++VsaNa5WNaMTk++++VrWNaMaNa5Tk++++VrS7aNaNVrTk++++VrRs
aNaMRrTk++++VrS7aNaNVrTk++++VrWNaMaNa5Tk++++VsaNa5WNaMTk++++VsaNVrS7aMTk
++++VsW6RrRsW6Tk++++VrRrRrRrRrTk++++W6W6W6W6W6Xk++++RrRrRrRrRrRk++++++++
+++++++++++++++++++++++++++++++++++8J33GI57ZRaZZRkdFIZ-mNLNdNLQl-2lZNbE0
++BIPr+04UJLOKFoO+Bs+UN6NKZbO5E1aE23EKldNqs5043gEqldNKto0YNjPbEiEqxgPr65
14BgJqZiN4xrJ4JsR+h4Pqto9YVZOKRcR+9k0INjPbEiHa3hNEM3EL7dMKk8FaxiR0tHR5Zg
NEg+0Z-VQaJiR2NjPbE603FVMYxmN4Jm+U28I43bNItpPK7ZQU6--3djPqo0N+++13FEQaZi
R2FdMKljNklEQaZiR2FdMKljNn22H4JaR+B5+UBIPr+05U++++++
***** END OF BLOCK 1 *****