unit U_PDFView; interface uses U_Constants, U_BaseConstants, U_LNG, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, siComp, siLngLnk, gtScrollingPanel, gtPDFViewer, gtPDFClasses, gtCstPDFDoc, gtExPDFDoc, gtExProPDFDoc, gtPDFDoc, ExtCtrls, RzPanel, Buttons, gtViewerTypes, gtPDFConsts, jpeg, Math, RzButton, RzRadChk, ImgList; type TF_PDFView = class(TForm) siLangLinked1: TsiLangLinked; RzPanel1: TRzPanel; RzPanel2: TRzPanel; gbOkCancel: TRzPanel; gtPDFDoc: TgtPDFDocument; gtPDFViewer: TgtPDFViewer; BtnOpenfile: TSpeedButton; BtnActive: TSpeedButton; BtnActualSize: TSpeedButton; btnFitWidth: TSpeedButton; BtnFitPage: TSpeedButton; BtnFirstPage: TSpeedButton; BtnPriorPage: TSpeedButton; lbGoToPage: TLabel; EdtGotoPage: TEdit; lbPageOf: TLabel; BtnNextPage: TSpeedButton; BtnLastPage: TSpeedButton; BtnZoomIn: TSpeedButton; edZoom: TEdit; BtnZoomOut: TSpeedButton; BtnPrint: TSpeedButton; lbPageCount: TLabel; TimerGotoPage: TTimer; btOK: TRzBitBtn; btCancel: TRzBitBtn; TimerDocOpenDialog: TTimer; cbConsiderScale: TRzCheckBox; BtnClkRotate: TSpeedButton; BtnResetRotate: TSpeedButton; ImageList1: TImageList; BtnUnClkRotate: TSpeedButton; procedure gtPDFViewerPageChange(Sender: TgtPDFViewer; const CurrentPageIndex: TPageIndex); procedure BtnOpenfileClick(Sender: TObject); procedure BtnActiveClick(Sender: TObject); procedure BtnFirstPageClick(Sender: TObject); procedure BtnActualSizeClick(Sender: TObject); procedure btnFitWidthClick(Sender: TObject); procedure BtnFitPageClick(Sender: TObject); procedure BtnPriorPageClick(Sender: TObject); procedure EdtGotoPageKeyPress(Sender: TObject; var Key: Char); procedure TimerGotoPageTimer(Sender: TObject); procedure BtnNextPageClick(Sender: TObject); procedure BtnLastPageClick(Sender: TObject); procedure BtnZoomInClick(Sender: TObject); procedure edZoomChange(Sender: TObject); procedure edZoomExit(Sender: TObject); procedure edZoomKeyPress(Sender: TObject; var Key: Char); procedure BtnZoomOutClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure gbOkCancelResize(Sender: TObject); procedure TimerDocOpenDialogTimer(Sender: TObject); procedure BtnPrintClick(Sender: TObject); procedure gtPDFDocPassword(Sender: TObject; var Password: String; var Continue: Boolean; const Tries: Integer); procedure FormCreate(Sender: TObject); procedure BtnClkRotateClick(Sender: TObject); procedure BtnResetRotateClick(Sender: TObject); procedure BtnUnClkRotateClick(Sender: TObject); private FOpenDialogOnShow: Boolean; FActiveViewAfterOpen: Boolean; FLastPassTries: Integer; FPassAllTries: Integer; FFile: String; procedure DefineRatateGlyph; function GetRotationAngle: Integer; function UpdateButton: string; procedure UpdateStatusBar; function OpenFileDialog(aActiveView: Boolean): Boolean; procedure LoadPDF(const aFile: string); procedure PrepareForm; public function GetDocBitmap(const aTitle: String; aFile: String = ''): TBitmap; function GetDocJpeg(const aTitle: String): TJPEGImage; end; function CreateFPDFView: TF_PDFView; const ActiveBtnHint: array[False..True] of string = (cPDFView_Msg2, cPDFView_Msg1); ZoomIncrement = 25; var F_PDFView: TF_PDFView; implementation Uses U_BaseCommon, U_Common, USCS_Main; {$R *.dfm} function CreateFPDFView: TF_PDFView; begin if F_PDFView = nil then begin F_PDFView := TF_PDFView.Create(Application); FSCS_Main.SetCursors; //11.07.2013 - восстановить курсоры, которые этот компонент для PDF их херит end; Result := F_PDFView; end; { TF_PDFView } function TF_PDFView.OpenFileDialog(aActiveView: Boolean): Boolean; var OpenDialog: TOpenDialog; begin Result := false; OpenDialog := TOpenDialog.Create(nil); try OpenDialog.Title := cPDFView_Msg3+'...'; OpenDialog.DefaultExt := '*.'+enPdf; OpenDialog.Filter := cProgressExp_Msg9_1 +'|'+ GetDialogFilter(exdAll, '*'); OpenDialog.Options := OpenDialog.Options - [ofNoChangeDir] + [ofOverwritePrompt]; if OpenDialog.Execute then begin Result := True; LoadPDF(OpenDialog.FileName); end; finally FreeAndNil(OpenDialog); end; end; procedure TF_PDFView.LoadPDF(const aFile: string); begin if gtPDFDoc.IsLoaded then begin gtPDFDoc.Reset; end; FLastPassTries := FPassAllTries + 1; // Запоминаем номер последней следующей попытки проверки пароля gtPDFViewer.Active := false; gtPDFDoc.Filename := aFile; if gtPDFDoc.IsLoaded then begin // 19/07/2017 -- если 200 - пользователь не утруждается усеньшить масштаб, в результете чего при // загрузке 5-6 листов получаем OUt OF MEMORY //gtPDFViewer.Zoom := 200; gtPDFViewer.Zoom := 100; // BtnPrint.Enabled := True; gtPDFViewer.PageNo := 1; gtPDFViewer.Active := False; gtPDFViewer.RotationAngle := ra0; gtPDFViewer.Active := True; //aActiveView; UpdateButton; UpdateStatusBar; EdtGotoPage.SetFocus; DefineRatateGlyph; //LBmp := TBitmap.Create; //ImageList1.GetBitmap(0, LBmp); //BtnClkRotate.Glyph.Assign(LBmp); //LBmp.Free; end; end; function TF_PDFView.GetDocBitmap(const aTitle: String; aFile: String = ''): TBitmap; var pSize: TgtPageSize; dpi: Integer; //Rotation: Integer; Rotation: Double; aImageProperties: TgtImageProperties; begin Result := nil; Caption := aTitle; FFile := aFile; FOpenDialogOnShow := aFile = ''; FActiveViewAfterOpen := false; PrepareForm; if ShowModal = mrOk then begin if gtPDFDoc.IsLoaded then begin gtPDFViewer.Active := false; Application.ProcessMessages; BeginProgress; try //pSize := gtPDFDoc.GetPageSize(gtPDFViewer.PageNo, muPixels); //Result.Width := Trunc(pSize.Width); //Result.Height := Trunc(pSize.Height); //gtPDFDoc.RenderToCanvas(gtPDFViewer.PageNo, Result.Canvas, tpDefault); ////gtPDFDoc.RenderToCanvas(gtPDFViewer.PageNo, Result.Canvas, tpAlignment); Rotation := GetRotationAngle; //gtPDFDoc.GetPageRotate(gtPDFViewer.PageNo); (* aImageProperties := TgtImageProperties.Create; aImageProperties.BMPpixelformat := pf16bit; gtPDFDoc.SaveAsImage('1', itBitmap, 'c:\', 'ddd', aImageProperties); *) //AddExceptionToLog('Memory before reading PDF'); if cbConsiderScale.Checked then begin try //gtPDFDoc. dpi := 72; dpi := Round(gtPDFViewer.Zoom / 100 * dpi); Result := gtPDFDoc.GetBitmap(gtPDFViewer.PageNo, dpi, dpi, 0); //Result.SaveToFile('c:\pdf_bitmap_'+IntToStr(dpi)+'.bmp'); except try dpi := 72; dpi := Round(gtPDFViewer.Zoom / 100 * dpi * 0.75 ); Result := gtPDFDoc.GetBitmap(gtPDFViewer.PageNo, dpi, dpi, 0); except try dpi := 72; dpi := Round(gtPDFViewer.Zoom / 100 * dpi * 0.5 ); Result := gtPDFDoc.GetBitmap(gtPDFViewer.PageNo, dpi, dpi, 0); except on E: Exception do AddExceptionToLogEx('F_PDFView.GetDocBitmap', E.Message, true); end; end; end; end else begin try Result := TBitmap.Create; pSize := gtPDFDoc.GetPageSize(gtPDFViewer.PageNo, muPixels); Result.Width := Trunc(pSize.Width); Result.Height := Trunc(pSize.Height); gtPDFDoc.RenderToCanvas(gtPDFViewer.PageNo, Result.Canvas, tpDefault, 0); except on E: Exception do AddExceptionToLogEx('F_PDFView.GetDocBitmap', E.Message, true); end; end; if Rotation <> 0 then try RotateBitmap(Result, Rotation, clWhite); except on E: Exception do AddExceptionToLogEx('RotateBitmap', E.Message, true); end; finally EndProgress; end; gtPDFDoc.FileName := ''; end; end; end; function TF_PDFView.GetDocJpeg(const aTitle: String): TJPEGImage; var Bmp: TBitmap; begin Result := nil; Bmp := GetDocBitmap(aTitle); if Bmp <> nil then begin Result := TJPEGImage.Create; Result.CompressionQuality := 100; Result.Assign(bmp); Bmp.Free; end; end; procedure TF_PDFView.gtPDFViewerPageChange(Sender: TgtPDFViewer; const CurrentPageIndex: TPageIndex); begin UpdateButton; UpdateStatusBar; end; procedure TF_PDFView.DefineRatateGlyph; var LBmp: TBitmap; begin LBmp := TBitmap.Create; {if (gtPDFViewer.RotationAngle = ra0) then begin ImageList1.GetBitmap(0, LBmp); BtnClkRotate.Glyph.Assign(LBmp); end else if (gtPDFViewer.RotationAngle = raCW90) then begin ImageList1.GetBitmap(1, LBmp); BtnClkRotate.Glyph.Assign(LBmp); end else if (gtPDFViewer.RotationAngle = raCW180) then begin ImageList1.GetBitmap(2, LBmp); BtnClkRotate.Glyph.Assign(LBmp); end else if (gtPDFViewer.RotationAngle = raCW270) then begin ImageList1.GetBitmap(3, LBmp); BtnClkRotate.Glyph.Assign(LBmp); end;} ImageList1.GetBitmap(Ord(gtPDFViewer.RotationAngle), LBmp); BtnClkRotate.Glyph.Assign(LBmp); LBmp.Free; end; function TF_PDFView.GetRotationAngle: Integer; begin Result := 0; case gtPDFViewer.RotationAngle of ra0: Result := 0; raCW90: Result := 90; raCW180: Result := 180; raCW270: Result := 270; raACW90: Result := 270; raACW180: Result := 180; raACW270: Result := 90; end; end; function TF_PDFView.UpdateButton: string; begin BtnFirstPage.Enabled := not gtPDFViewer.IsFirst; BtnPriorPage.Enabled := not gtPDFViewer.IsFirst; BtnNextPage.Enabled := not gtPDFViewer.IsLast; BtnLastPage.Enabled := not gtPDFViewer.IsLast; BtnActive.Enabled := True; BtnActive.Down := Not gtPDFViewer.Active; BtnActive.Hint := ActiveBtnHint[BtnActive.down]; BtnFitPage.Enabled := True; btnFitWidth.Enabled := True; BtnActualSize.Enabled := True; if round(gtPDFViewer.Zoom) = round(gtPDFViewer.GetStandardZoomValue(sztActualSize)) then BtnActualSize.Down := True; if round(gtPDFViewer.Zoom) = round(gtPDFViewer.GetStandardZoomValue(sztFitPage)) then BtnFitPage.Down := True; if round(gtPDFViewer.Zoom) = round(gtPDFViewer.GetStandardZoomValue(sztFitWidth)) then btnFitWidth.Down := True; //SearchButton.Enabled := True; BtnZoomOut.Enabled := True; BtnZoomIn.Enabled := True; EdtGotoPage.Enabled := True; edZoom.Enabled := True; BtnClkRotate.Enabled := True; BtnResetRotate.Enabled := True; EdtGotoPage.Text := IntToStr(gtPDFViewer.PageNo); //Label2.Caption := ' of ' + IntToStr(gtPDFViewer1.PDFDocument.PageCount); lbPageCount.Caption := IntToStr(gtPDFViewer.PDFDocument.PageCount); end; procedure TF_PDFView.UpdateStatusBar; begin edZoom.Text := FormatFloat(GetDisplayFormatForFloatByPrecision(2), gtPDFViewer.Zoom); BtnZoomIn.Enabled := (StrToFloat_My(edZoom.Text)) <> 1 ; end; procedure TF_PDFView.BtnOpenfileClick(Sender: TObject); begin OpenFileDialog(Not BtnActive.Down); end; procedure TF_PDFView.BtnActiveClick(Sender: TObject); begin //BtnActive.Hint := ActiveBtnHint[BtnActive.down]; gtPDFViewer.Active := Not BtnActive.Down; //not gtPDFViewer.Active; BtnPrint.Enabled := gtPDFViewer.Active; UpdateButton; end; procedure TF_PDFView.BtnActualSizeClick(Sender: TObject); begin gtPDFViewer.Zoom := gtPDFViewer.GetStandardZoomValue(sztActualSize); UpdateStatusBar; end; procedure TF_PDFView.btnFitWidthClick(Sender: TObject); begin gtPDFViewer.Zoom := gtPDFViewer.GetStandardZoomValue(sztFitWidth); UpdateStatusBar; end; procedure TF_PDFView.BtnFitPageClick(Sender: TObject); begin gtPDFViewer.Zoom := gtPDFViewer.GetStandardZoomValue(sztFitPage); UpdateStatusBar; end; procedure TF_PDFView.BtnFirstPageClick(Sender: TObject); begin gtPDFViewer.First; UpdateButton; UpdateStatusBar; end; procedure TF_PDFView.BtnPriorPageClick(Sender: TObject); begin gtPDFViewer.Prior; UpdateButton; UpdateStatusBar; end; procedure TF_PDFView.EdtGotoPageKeyPress(Sender: TObject; var Key: Char); begin if not (Key in ['0'..'9', #13]) and (Ord(Key) <> VK_BACK) then begin Key := #0; end; TimerGotoPage.Enabled := true; end; procedure TF_PDFView.TimerGotoPageTimer(Sender: TObject); begin TTimer(Sender).Enabled := false; gtPDFViewer.GoToPage(StrToIntDef(EdtGotoPage.Text,1)); UpdateButton; UpdateStatusBar; end; procedure TF_PDFView.BtnNextPageClick(Sender: TObject); begin gtPDFViewer.Next; UpdateButton; UpdateStatusBar; end; procedure TF_PDFView.BtnLastPageClick(Sender: TObject); begin gtPDFViewer.Last; UpdateButton; UpdateStatusBar; end; procedure TF_PDFView.BtnZoomInClick(Sender: TObject); var Lfactor: Integer; begin if edZoom.Text = '' then begin gtPDFViewer.Zoom := 1; UpdateStatusBar; end else begin Lfactor := Floor((gtPDFViewer.Zoom)/ ZoomIncrement); if ((gtPDFViewer.Zoom) - (ZoomIncrement * Lfactor)) = 0 then gtPDFViewer.Zoom := (ZoomIncrement * (Lfactor-1)) else gtPDFViewer.Zoom := (ZoomIncrement * (Lfactor)); UpdateStatusBar; end; end; procedure TF_PDFView.edZoomChange(Sender: TObject); begin if edZoom.Text <> '' then gtPDFViewer.Zoom := StrToFloat_My(edZoom.text) else gtPDFViewer.Zoom := 1; UpdateButton; end; procedure TF_PDFView.edZoomExit(Sender: TObject); begin if edZoom.Text <> '' then gtPDFViewer.Zoom := StrToFloat_My(edZoom.Text); end; procedure TF_PDFView.edZoomKeyPress(Sender: TObject; var Key: Char); begin if not (Key in ['0'..'9','.', #13]) and (Ord(Key) <> VK_BACK) then begin Key := #0; end; end; procedure TF_PDFView.BtnZoomOutClick(Sender: TObject); var Lfactor: Integer; begin if edZoom.Text = '' then begin gtPDFViewer.Zoom := ZoomIncrement; UpdateStatusBar; end else begin Lfactor := Floor(StrToFloat_My(edZoom.text)/ ZoomIncrement); gtPDFViewer.Zoom := (ZoomIncrement * (Lfactor+1)); UpdateStatusBar; end; end; procedure TF_PDFView.FormShow(Sender: TObject); begin if FFile = '' then begin if FOpenDialogOnShow then TimerDocOpenDialog.Enabled := true; end else LoadPDF(FFile); end; procedure TF_PDFView.gbOkCancelResize(Sender: TObject); begin SetMiddleControlChilds(TControl(Sender), TControl(Self)); end; procedure TF_PDFView.PrepareForm; begin gtPDFViewer.Active := false; UpdateButton; gbOkCancelResize(gbOkCancel); end; procedure TF_PDFView.TimerDocOpenDialogTimer(Sender: TObject); begin TTimer(Sender).Enabled := false; OpenFileDialog(FActiveViewAfterOpen); end; procedure TF_PDFView.BtnPrintClick(Sender: TObject); begin gtPDFViewer.PrintDoc; end; procedure TF_PDFView.gtPDFDocPassword(Sender: TObject; var Password: String; var Continue: Boolean; const Tries: Integer); begin FPassAllTries := Tries; if Tries = 0 then FLastPassTries := 0; if (Tries > FLastPassTries) and (Tries < (FLastPassTries + 3)) then ShowMessage(cPDFView_Msg4_1 + CRLF + cPDFView_Msg4_2); if Tries < (FLastPassTries + 3) then Continue := InputPassQuery(cPDFView_Msg4_4, cPDFView_Msg4_5, Password) else begin Continue := False; ShowMessage(cPDFView_Msg4_1 + CRLF + cPDFView_Msg4_3); end; end; procedure TF_PDFView.FormCreate(Sender: TObject); begin FLastPassTries := 0; FPassAllTries := -1; //-1 так как номер первой попытки проверки пароля = 0 end; procedure TF_PDFView.BtnClkRotateClick(Sender: TObject); var LBmp: TBitmap; begin gtPDFViewer.RotateClockwise90; DefineRatateGlyph; end; procedure TF_PDFView.BtnResetRotateClick(Sender: TObject); begin gtPDFViewer.RotationAngle := ra0; DefineRatateGlyph; end; procedure TF_PDFView.BtnUnClkRotateClick(Sender: TObject); begin gtPDFViewer.RotateAntiClockwise90; //DefineRatateGlyph; end; end.