unit OrgPrevForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Buttons, PrevPrinter, ImgList;

const
   crZoom = 40;
   ZOOMFACTOR = 1.5;

type                                                  

  TPage = class(TPanel)
  private
  	PB1: TPaintBox;
  public
  	procedure SetPageNum(Value: String);
	  constructor Create(AOwner: TComponent); override;
		destructor Destroy; override;
  end;

  TPreviewForm = class(TForm)
    StatBarPanel: TPanel;
    CurPageLabel: TPanel;
    ZoomLabel: TPanel;
    Panel1: TPanel;
    HintLabel: TLabel;
    ScrollBox1: TScrollBox;
    ContainPanel: TPanel;
    PrintDialog1: TPrintDialog;
    Images: TImageList;
    Image1: TImage;
    FitPageBut: TSpeedButton;
    Zoom100: TSpeedButton;
    FitWidthBut: TSpeedButton;
    ZoomCursorBut: TSpeedButton;
    HandCursorBut: TSpeedButton;
    Print: TSpeedButton;
    PrintSetup: TSpeedButton;
    ZoomBox: TComboBox;
    SpeedButton9: TSpeedButton;
    procedure FormCreate(Sender: TObject);
    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 OnePageButMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FitPageButClick(Sender: TObject);
    procedure FitWidthButClick(Sender: TObject);
    procedure ZoomToWidthClick(Sender: TObject);
    procedure ZoomFitClick(Sender: TObject);
    procedure PreviousPageClick(Sender: TObject);
    procedure ZoomCursorBut1Click(Sender: TObject);
    procedure Print1Click(Sender: TObject);
    procedure ExitButtonClick(Sender: TObject);
    procedure FirstPageClick(Sender: TObject);
    procedure LastPageClick(Sender: TObject);
    procedure HandCursorBut1Click(Sender: TObject);
    procedure ToolButton4Click(Sender: TObject);
    procedure PrintSetup1Click(Sender: TObject);
    procedure SpeedButton9Click(Sender: TObject);
    procedure Zoom100Click(Sender: TObject);
  private
  	FColPage, FRowPage: Integer;
	  FPrevPrinter: TPreviewPrinter;
  	FPageList: TStringList;
    FCurPage      : Integer;
    OldHint       : TNotifyEvent;
    DownX, DownY  : Integer;
    Moving        : Boolean;
    procedure DrawMetaFile(PB: TPaintBox; mf: TMetaFile);
    procedure OnHint(Sender: TObject);
    procedure SetCurPage(Val: integer);
    procedure CheckEnable;
    procedure SetPrevPrinter(const Value: TPreviewPrinter);

		function CurrentPage: TPage;
  public
    Zoom: Double;
    procedure SetPageRC(RowPage, ColPage: Integer);
    property PrevPrinter: TPreviewPrinter read FPrevPrinter write SetPrevPrinter;
    property CurPage: Integer read FCurPage write SetCurPage;
  end;


implementation
{$R *.DFM}

procedure TPreviewForm.FormCreate(Sender: TObject);
begin
	FPageList := TStringList.Create;

  ZoomBox.ItemIndex := 0;
  WindowState := wsMaximized;
  Screen.Cursors[crZoom] := LoadCursor(hInstance, 'ZOOM_CURSOR');
  ZoomCursorButClick(nil);
end;

procedure TPreviewForm.CloseButClick(Sender: TObject);
begin
	Close;
end;

procedure TPreviewForm.FormClose(Sender: TObject;
  var Action: TCloseAction);
var
	I: Integer;
begin
  Action := caFree;
  Application.OnHint := OldHint;

	for I := 0 to FPageList.Count - 1 do
  	TPage(FPageList.Objects[I]).Free;
end;

procedure TPreviewForm.ScrollBox1Resize(Sender: TObject);
const
   BORD = 10;
var
	Z: Double;
  Tmp, I, Col, Row, PG, Top, Left, nSLeft: Integer;
  TotWid: Integer;
  PageTemp: TPage;
begin
  case ZoomBox.ItemIndex of
  	0 : FitPageBut.Down  := True;
    1 : FitWidthBut.Down := True;
  else
  	FitPageBut.Down := False;
    FitWidthBut.Down := False;
  end;

  if ZoomBox.ItemIndex = -1 then
  	ZoomBox.ItemIndex := 0;

  case ZoomBox.ItemIndex of
    0: Z := ((ScrollBox1.ClientHeight - BORD) / PixelsPerInch) / (PrevPrinter.PageHeight / PrevPrinter.PixelsPerInchY);
    1: Z := ((ScrollBox1.ClientWidth - BORD) / PixelsPerInch) / (PrevPrinter.PageWidth / PrevPrinter.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;

  CurrentPage.Height  := TRUNC(PixelsPerInch * Z * PrevPrinter.PageHeight / PrevPrinter.PixelsPerInchY);
  CurrentPage.Width   := TRUNC(PixelsPerInch * Z * PrevPrinter.PageWidth / PrevPrinter.PixelsPerInchX);
  CurrentPage.Visible := True;
  for I := 0 to FPageList.Count - 1 do
  begin
    PageTemp := TPage(FPageList.Objects[I]);
    PageTemp.Visible := True;
    PageTemp.Width   := CurrentPage.Width;
    PageTemp.Height  := CurrentPage.Height;
  end;

  TotWid := BORD * 2;
  for Col := 0 to FColPage - 1 do
    TotWid := TotWid + CurrentPage.Width;

  Tmp := Bord * 2;
  for Row := 0 to FRowPage - 1 do
    Tmp := Tmp + CurrentPage.Height;
//    Tmp := Tmp + CurrentPage.Height + BORD;

  // Resize the Contain Panel
  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 CurrentPage.Height + BORD < ContainPanel.Height then
  	CurrentPage.Top := ((ContainPanel.Height div FRowPage) div FRowPage)  - (CurrentPage.Height div FRowPage)
  else
  	CurrentPage.Top := BORD div FRowPage;

  Top := CurrentPage.Top;
  for Row := 0 to FRowPage - 1 do
  begin
  	Top := (CurrentPage.Height * Row) + BORD;
    for Col := (FColPage * Row) to (FColPage * Row) + FColPage - 1 do
      TPage(FPageList.Objects[Col]).Top := Top;
  end;

  if CurrentPage.Width + BORD < ContainPanel.Width then
  	CurrentPage.Left := (((ContainPanel.Width div FColPage) div FColPage) - (TotWid div FColPage) div FColPage) + (BORD div 3)
  else
  	CurrentPage.Left := BORD div 3;

  nSLeft := CurrentPage.Left + (BORD div 2);
  for Row := 0 to FRowPage - 1 do
  begin
    Left := nSLeft;
    for Col := (FColPage * Row) to (FColPage * Row) + FColPage - 1 do
    begin
      TPage(FPageList.Objects[Col]).Left := Left;
      Left := Left + CurrentPage.Width;
    end;
  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;
	Page: Integer;
begin
	PB := Sender as TPaintBox;
  Page := StrToInt(Copy(PB.Name, 4, 5));

  SetMapMode(PB.Canvas.Handle, MM_ANISOTROPIC);
  SetWindowExtEx(PB.Canvas.Handle, PrevPrinter.PageWidth, PrevPrinter.PageHeight, nil);
  SetViewportExtEx(PB.Canvas.Handle, PB.Width, PB.Height, nil);

 	DrawMetaFile(PB, PrevPrinter.MetaFiles[Page]);
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;
end;

procedure TPreviewForm.SetCurPage(Val: integer);
var
  Tmp, I : Integer;
begin
  FCurPage := Val;
  Tmp := 0;
  if PrevPrinter<>nil then
  	Tmp := PrevPrinter.LastAvailPage;
  CurPageLabel.Caption := Format('Page %d of %d', [Val+1, tmp]);

  for I := 0 to FPageList.Count - 1 do
		TPage(FPageList.Objects[I]).PB1.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 < PrevPrinter.LastAvailPage;
//  PrevPageBut.Enabled := CurPage > 0;
end;

procedure TPreviewForm.FirstPageSpeedClick(Sender: TObject);
begin
	CurPage := 0;
  CheckEnable;
end;

procedure TPreviewForm.LastPageSpeedClick(Sender: TObject);
begin
  CurPage := PrevPrinter.LastAvailPage-1;
  CheckEnable;
end;

procedure TPreviewForm.ZoomCursorButClick(Sender: TObject);
var
	I: Integer;
begin
  for I := 0 to FPageList.Count - 1 do
		TPage(FPageList.Objects[I]).PB1.Cursor := crZoom;
end;

procedure TPreviewForm.HandCursorButClick(Sender: TObject);
var
	I: Integer;
begin
  for I := 0 to FPageList.Count - 1 do
		TPage(FPageList.Objects[I]).PB1.Cursor := crHandPoint;
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 / CurrentPage.Width;
    sy := Y / CurrentPage.Height;

    if ssLeft  in Shift then
    	Zoom := Zoom * ZOOMFACTOR;

    if ssRight in Shift then
    	Zoom := Zoom / ZOOMFACTOR;

    ZoomBox.ItemIndex := 2;
    ScrollBox1Resize(nil);

    nx := TRUNC(sx * CurrentPage.Width);
    ny := TRUNC(sy * CurrentPage.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);
begin
  PrevPrinter.PrintDialog;
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.ZoomToWidthClick(Sender: TObject);
begin
  ZoomBox.ItemIndex := 1;
  ZoomBoxChange(nil);
end;

procedure TPreviewForm.ZoomFitClick(Sender: TObject);
begin
  ZoomBox.ItemIndex := 0;
  ZoomBoxChange(nil);
end;

procedure TPreviewForm.PreviousPageClick(Sender: TObject);
begin
  CurPage := CurPage - 1;
  CheckEnable;
end;

procedure TPreviewForm.ZoomCursorBut1Click(Sender: TObject);
begin
  CurPage := CurPage + 1;
  CheckEnable;
end;

procedure TPreviewForm.Print1Click(Sender: TObject);
begin
	PrevPrinter.Print;
end;

procedure TPreviewForm.ExitButtonClick(Sender: TObject);
begin
	Close;
end;

procedure TPreviewForm.FirstPageClick(Sender: TObject);
begin
	CurPage := 0;
  CheckEnable;
end;

procedure TPreviewForm.LastPageClick(Sender: TObject);
begin
  CurPage := PrevPrinter.LastAvailPage-1;
  CheckEnable;
end;

procedure TPreviewForm.HandCursorBut1Click(Sender: TObject);
var
	I: Integer;
begin
  for I := 0 to FPageList.Count - 1 do
		TPage(FPageList.Objects[I]).PB1.Cursor := crHandPoint;
end;

procedure TPreviewForm.ToolButton4Click(Sender: TObject);
begin
  ZoomBox.ItemIndex := 0;
  ScrollBox1Resize(nil);
end;

procedure TPreviewForm.SetPrevPrinter(const Value: TPreviewPrinter);
var
	I: Integer;
  PageTemp: TPage;
begin
  FPrevPrinter := Value;
 	for I := 0 to PrevPrinter.MetaFileCount - 1 do
  begin
	  PageTemp := TPage.Create(ContainPanel);
    PageTemp.SetPageNum(IntToStr(I));
    PageTemp.PB1.OnPaint     := PBPaint;
    PageTemp.PB1.OnMouseDown := PB1MouseDown;
    PageTemp.PB1.OnMouseMove := PB1MouseMove;
    PageTemp.PB1.OnMouseUp   := PB1MouseUp;

	 	FPageList.AddObject(IntToStr(I), PageTemp);
  end;
end;

function TPreviewForm.CurrentPage: TPage;
begin
	Result := TPage(FPageList.Objects[FCurPage]);
end;

procedure TPreviewForm.SetPageRC(RowPage, ColPage: Integer);
begin
	FColPage := ColPage;
  FRowPage := RowPage;
end;

//-------------------------------------------
//
// TPage
//-------------------------------------------
constructor TPage.Create(AOwner: TComponent);
begin
  inherited;
  Visible     := False;
  Parent      := TPanel(AOwner);
  BevelInner  := bvNone;
  BevelOuter  := bvNone;
  BorderStyle := bsNone;
	Color := clWhite;

	PB1 := TPaintBox.Create(Self);
  PB1.Parent := Self;
  PB1.Align := alClient;
end;

destructor TPage.Destroy;
begin
	PB1.Free;
  inherited;
end;

procedure TPage.SetPageNum(Value: String);
begin
	PB1.Name := 'PB_' + Value;
end;


procedure TPreviewForm.PrintSetup1Click(Sender: TObject);
begin
  PrevPrinter.PrintDialog;
end;

procedure TPreviewForm.SpeedButton9Click(Sender: TObject);
begin
	Close;
end;

procedure TPreviewForm.Zoom100Click(Sender: TObject);
begin
  ZoomBox.ItemIndex := 6;
  ZoomBoxChange(nil);
end;

end.
