{*************************************************************} {* *} {* Thanks to Chris Wallace for most of the ideas and *} {* code associated with Print Preview and the Preview Form *} {* *} {*************************************************************} {$ifDef ver150} {Delphi 7} {$Define Delphi7_Plus} {$endif} {$ifDef ver170} {Delphi 2005} {$Define Delphi7_Plus} {$endif} {$ifDef ver180} {Delphi 2006} {$Define Delphi7_Plus} {9.4} {$endif} unit PreviewForm; interface uses {$IFNDEF LCL} Windows, Messages, {$ELSE} LclIntf, LMessages, LclType, LResources, {$ENDIF} SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Buttons, MetaFilePrinter, HTMLView, PrintStatusForm; const crZoom = 40; crHandDrag = 41; ZOOMFACTOR = 1.5; type TPreviewForm = class(TForm) ToolBarPanel: TPanel; GridBut: TSpeedButton; ZoomCursorBut: TSpeedButton; HandCursorBut: TSpeedButton; OnePageBut: TSpeedButton; TwoPageBut: TSpeedButton; PrintBut: TBitBtn; NextPageBut: TBitBtn; PrevPageBut: TBitBtn; CloseBut: TBitBtn; ZoomBox: TComboBox; StatBarPanel: TPanel; CurPageLabel: TPanel; ZoomLabel: TPanel; Panel1: TPanel; HintLabel: TLabel; MoveButPanel: TPanel; FirstPageSpeed: TSpeedButton; PrevPageSpeed: TSpeedButton; NextPageSpeed: TSpeedButton; LastPageSpeed: TSpeedButton; PageNumSpeed: TSpeedButton; ScrollBox1: TScrollBox; ContainPanel: TPanel; PagePanel: TPanel; PB1: TPaintBox; PagePanel2: TPanel; PB2: TPaintBox; PrintDialog1: TPrintDialog; FitPageBut: TSpeedButton; FitWidthBut: TSpeedButton; Bevel1: TBevel; Bevel2: TBevel; Bevel3: TBevel; Bevel4: TBevel; Bevel5: TBevel; Bevel6: TBevel; UnitsBox: TComboBox; Bevel7: TBevel; procedure CloseButClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure ScrollBox1Resize(Sender: TObject); procedure PBPaint(Sender: TObject); procedure GridButClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure ZoomBoxChange(Sender: TObject); procedure TwoPageButClick(Sender: TObject); procedure NextPageButClick(Sender: TObject); procedure PrevPageButClick(Sender: TObject); procedure FirstPageSpeedClick(Sender: TObject); procedure LastPageSpeedClick(Sender: TObject); procedure ZoomCursorButClick(Sender: TObject); procedure HandCursorButClick(Sender: TObject); procedure PB1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure PB1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure PB1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure PrintButClick(Sender: TObject); procedure PageNumSpeedClick(Sender: TObject); procedure OnePageButMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure FitPageButClick(Sender: TObject); procedure FitWidthButClick(Sender: TObject); procedure UnitsBoxChange(Sender: TObject); private Viewer: ThtmlViewer; protected FCurPage : integer; OldHint : TNotifyEvent; DownX, DownY : integer; Moving : boolean; MFPrinter : TMetaFilePrinter; procedure DrawMetaFile(PB: TPaintBox; mf: TMetaFile); procedure OnHint(Sender: TObject); procedure SetCurPage(Val: integer); procedure CheckEnable; property CurPage: integer read FCurPage write SetCurPage; public Zoom : double; constructor CreateIt(AOwner: TComponent; AViewer: ThtmlViewer; var Abort: boolean); destructor Destroy; override; end; implementation uses Gopage; {$IFNDEF LCL} {$R *.DFM} {$ENDIF} {$R GRID.RES} constructor TPreviewForm.CreateIt(AOwner: TComponent; AViewer: ThtmlViewer; var Abort: boolean); var StatusForm: TPrnStatusForm; begin inherited Create(AOwner); ZoomBox.ItemIndex := 0; UnitsBox.ItemIndex := 0; Screen.Cursors[crZoom] := LoadCursor(hInstance, 'ZOOM_CURSOR'); Screen.Cursors[crHandDrag] := LoadCursor(hInstance, 'HAND_CURSOR'); ZoomCursorButClick(nil); Viewer := AViewer; MFPrinter := TMetaFilePrinter.Create(Self); StatusForm := TPrnStatusForm.Create(Self); try StatusForm.DoPreview(Viewer, MFPrinter, Abort); finally StatusForm.Free; end; end; destructor TPreviewForm.Destroy; begin inherited; end; procedure TPreviewForm.CloseButClick(Sender: TObject); begin Close; end; procedure TPreviewForm.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := caFree; Application.OnHint := OldHint; MFPrinter.Free; end; procedure TPreviewForm.ScrollBox1Resize(Sender: TObject); const BORD = 20; var z : double; tmp : integer; TotWid : integer; begin case ZoomBox.ItemIndex of 0 : FitPageBut.Down := True; 1 : FitWidthBut.Down := True; else begin FitPageBut.Down := False; FitWidthBut.Down := False; end; end; if ZoomBox.ItemIndex = -1 then ZoomBox.ItemIndex := 0; Case ZoomBox.ItemIndex of 0: z := ((ScrollBox1.ClientHeight - BORD) / PixelsPerInch) / (MFPrinter.PaperHeight / MFPrinter.PixelsPerInchY); 1: z := ((ScrollBox1.ClientWidth - BORD) / PixelsPerInch) / (MFPrinter.PaperWidth / MFPrinter.PixelsPerInchX); 2: z := Zoom; 3: z := 0.25; 4: z := 0.50; 5: z := 0.75; 6: z := 1.00; 7: z := 1.25; 8: z := 1.50; 9: z := 2.00; 10: z := 3.00; 11: z := 4.00; else z := 1; end; if ZoomBox.ItemIndex<>0 then OnePageBut.Down := True; PagePanel.Height := TRUNC(PixelsPerInch * z * MFPrinter.PaperHeight / MFPrinter.PixelsPerInchY); PagePanel.Width := TRUNC(PixelsPerInch * z * MFPrinter.PaperWidth / MFPrinter.PixelsPerInchX); PagePanel2.Visible := TwoPageBut.Down; if TwoPageBut.Down then begin PagePanel2.Width := PagePanel.Width; PagePanel2.Height := PagePanel.Height; end; TotWid := PagePanel.Width + BORD; if TwoPageBut.Down then TotWid := TotWid + PagePanel2.Width + BORD; // Resize the Contain Panel tmp := PagePanel.Height + BORD; if tmp < ScrollBox1.ClientHeight then tmp := ScrollBox1.ClientHeight-1; ContainPanel.Height := tmp; tmp := TotWid; if tmp < ScrollBox1.ClientWidth then tmp := ScrollBox1.ClientWidth-1; ContainPanel.Width := tmp; // Center the Page Panel if PagePanel.Height + BORD < ContainPanel.Height then PagePanel.Top := ContainPanel.Height div 2 - PagePanel.Height div 2 else PagePanel.Top := BORD div 2; PagePanel2.Top := PagePanel.Top; if TotWid < ContainPanel.Width then PagePanel.Left := ContainPanel.Width div 2 - (TotWid - BORD) div 2 else PagePanel.Left := BORD div 2; PagePanel2.Left := PagePanel.Left + PagePanel.Width + BORD; {Make sure the scroll bars are hidden if not needed} if (PagePanel.Width +BORD <= ScrollBox1.Width) and (PagePanel.Height +BORD <= ScrollBox1.Height) then begin ScrollBox1.HorzScrollBar.Visible := False; ScrollBox1.VertScrollBar.Visible := False; end else begin ScrollBox1.HorzScrollBar.Visible := True; ScrollBox1.VertScrollBar.Visible := True; end; // Set the Zoom Variable Zoom := z; ZoomLabel.Caption := Format('%1.0n', [z * 100]) + '%'; end; procedure TPreviewForm.DrawMetaFile(PB: TPaintBox; mf: TMetaFile); begin PB.Canvas.Draw(0, 0, mf); end; procedure TPreviewForm.PBPaint(Sender: TObject); var PB : TPaintBox; x1, y1 : integer; x, y : integer; Factor : double; Draw : boolean; Page : integer; begin PB := Sender as TPaintBox; if PB = PB1 then begin Draw := CurPage < MFPrinter.LastAvailablePage; Page := CurPage; end else begin // PB2 Draw := TwoPageBut.Down and (CurPage+1 < MFPrinter.LastAvailablePage); Page := CurPage + 1; end; SetMapMode(PB.Canvas.Handle, MM_ANISOTROPIC); SetWindowExtEx(PB.Canvas.Handle, MFPrinter.PaperWidth, MFPrinter.PaperHeight, nil); SetViewportExtEx(PB.Canvas.Handle, PB.Width, PB.Height, nil); SetWindowOrgEx(PB.Canvas.Handle, -MFPrinter.OffsetX, -MFPrinter.OffsetY, nil); if Draw then DrawMetaFile(PB, MFPrinter.MetaFiles[Page]); if GridBut.Down then begin SetWindowOrgEx(PB.Canvas.Handle, 0, 0, nil); PB.Canvas.Pen.Color := clLtGray; if UnitsBox.ItemIndex = 0 then Factor := 1.0 else Factor := 2.54; for x := 1 to Round(MFPrinter.PaperWidth / MFPrinter.PixelsPerInchX * Factor) do begin x1 := Round(MFPrinter.PixelsPerInchX * x / Factor); PB.Canvas.MoveTo(x1, 0); PB.Canvas.LineTo(x1, MFPrinter.PaperHeight); end; for y := 1 to Round(MFPrinter.PaperHeight / MFPrinter.PixelsPerInchY * Factor) do begin y1 := Round(MFPrinter.PixelsPerInchY * y / Factor); PB.Canvas.MoveTo(0, y1); PB.Canvas.LineTo(MFPrinter.PaperWidth, y1); end; end; end; procedure TPreviewForm.GridButClick(Sender: TObject); begin PB1.Invalidate; PB2.Invalidate; end; procedure TPreviewForm.OnHint(Sender: TObject); begin HintLabel.Caption := Application.Hint; end; procedure TPreviewForm.FormShow(Sender: TObject); begin CurPage := 0; OldHint := Application.OnHint; Application.OnHint := OnHint; CheckEnable; {$ifdef delphi7_plus} PagePanel.ParentBackground := False; PagePanel2.ParentBackground := False; {$endif} ScrollBox1Resize(Nil); {make sure it gets sized} end; procedure TPreviewForm.SetCurPage(Val: integer); var tmp : integer; begin FCurPage := Val; tmp := 0; if MFPrinter <> nil then tmp := MFPrinter.LastAvailablePage; CurPageLabel.Caption := Format('Page %d of %d', [Val+1, tmp]); PB1.Invalidate; PB2.Invalidate; end; procedure TPreviewForm.ZoomBoxChange(Sender: TObject); begin ScrollBox1Resize(nil); ScrollBox1Resize(nil); end; procedure TPreviewForm.TwoPageButClick(Sender: TObject); begin ZoomBox.ItemIndex := 0; ScrollBox1Resize(nil); end; procedure TPreviewForm.NextPageButClick(Sender: TObject); begin CurPage := CurPage + 1; CheckEnable; end; procedure TPreviewForm.PrevPageButClick(Sender: TObject); begin CurPage := CurPage - 1; CheckEnable; end; procedure TPreviewForm.CheckEnable; begin NextPageBut.Enabled := CurPage+1 < MFPrinter.LastAvailablePage; PrevPageBut.Enabled := CurPage > 0; NextPageSpeed.Enabled := NextPageBut.Enabled; PrevPageSpeed.Enabled := PrevPageBut.Enabled; FirstPageSpeed.Enabled := PrevPageBut.Enabled; LastPageSPeed.Enabled := NextPageBut.Enabled; PageNumSpeed.Enabled := MFPrinter.LastAvailablePage > 1; end; procedure TPreviewForm.FirstPageSpeedClick(Sender: TObject); begin CurPage := 0; CheckEnable; end; procedure TPreviewForm.LastPageSpeedClick(Sender: TObject); begin CurPage := MFPrinter.LastAvailablePage-1; CheckEnable; end; procedure TPreviewForm.ZoomCursorButClick(Sender: TObject); begin PB1.Cursor := crZoom; PB2.Cursor := crZoom; end; procedure TPreviewForm.HandCursorButClick(Sender: TObject); begin PB1.Cursor := crHandDrag; PB2.Cursor := crHandDrag; end; procedure TPreviewForm.PB1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var sx, sy : single; nx, ny : integer; begin if ZoomCursorBut.Down then begin sx := X / PagePanel.Width; sy := Y / PagePanel.Height; if (ssLeft in Shift) and (Zoom < 20.0) then Zoom := Zoom * ZOOMFACTOR; if (ssRight in Shift) and (Zoom > 0.1) then Zoom := Zoom / ZOOMFACTOR; ZoomBox.ItemIndex := 2; ScrollBox1Resize(nil); nx := TRUNC(sx * PagePanel.Width); ny := TRUNC(sy * PagePanel.Height); ScrollBox1.HorzScrollBar.Position := nx - ScrollBox1.Width div 2; ScrollBox1.VertScrollBar.Position := ny - ScrollBox1.Height div 2; end; if HandCursorBut.Down then begin DownX := X; DownY := Y; Moving := True; end; end; procedure TPreviewForm.PB1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if Moving then begin ScrollBox1.HorzScrollBar.Position := ScrollBox1.HorzScrollBar.Position + (DownX - X); ScrollBox1.VertScrollBar.Position := ScrollBox1.VertScrollBar.Position + (DownY - Y); end; end; procedure TPreviewForm.PB1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Moving := False; end; procedure TPreviewForm.PrintButClick(Sender: TObject); var StatusForm: TPrnStatusForm; Dummy: boolean; begin with PrintDialog1 do begin MaxPage := 9999; ToPage := 1; Options := [poPageNums]; StatusForm := TPrnStatusForm.Create(Self); if Execute then if PrintRange = prAllPages then StatusForm.DoPrint(Viewer, FromPage, 9999, Dummy) else StatusForm.DoPrint(Viewer, FromPage, ToPage, Dummy); StatusForm.Free; end; end; procedure TPreviewForm.PageNumSpeedClick(Sender: TObject); var gp : TGoPageForm; begin gp := TGoPageForm.Create(Self); gp.PageNum.MaxValue := MFPrinter.LastAvailablePage; gp.PageNum.Value := CurPage + 1; if gp.ShowModal = mrOK then begin CurPage := gp.PageNum.Value - 1; CheckEnable; end; gp.Free; end; procedure TPreviewForm.OnePageButMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin ZoomBox.ItemIndex := 0; ScrollBox1Resize(nil); end; procedure TPreviewForm.FitPageButClick(Sender: TObject); begin ZoomBox.ItemIndex := 0; ZoomBoxChange(nil); end; procedure TPreviewForm.FitWidthButClick(Sender: TObject); begin ZoomBox.ItemIndex := 1; ZoomBoxChange(nil); end; procedure TPreviewForm.UnitsBoxChange(Sender: TObject); begin if GridBut.down then begin PB1.Invalidate; PB2.Invalidate; end; end; initialization {$IFDEF LCL} {$I PreviewForm.lrs} {Include form's resource file} {$ENDIF} end.