expertcad/SRC/Main/U_PDFView.pas
2025-05-12 10:07:51 +03:00

594 lines
16 KiB
ObjectPascal
Raw Blame History

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 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> PDF <20><> <20><><EFBFBD><EFBFBD><EFBFBD>
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; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
gtPDFViewer.Active := false;
gtPDFDoc.Filename := aFile;
if gtPDFDoc.IsLoaded then
begin
// 19/07/2017 -- <20><><EFBFBD><EFBFBD> 200 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 5-6 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 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 <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> = 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.