并排比较多个PDF文档对于修订审查、质量控制和文档验证至关重要。 分屏视图 该演示程序展示了如何使用PDFium VCL同时显示两个或三个PDF文档。
概述
该高级演示程序以同步视图显示多个PDF文档,允许用户直观地比较文档。它支持双向和三向比较模式,并为每个视图提供独立的导航和缩放控件。
主要特性
- 双面板模式 – 并排比较两个文档。
- 三面板模式 – 同时比较三个文档
- 独立导航 – 独立浏览每个文档
- 同步缩放 – 对所有视图或单独的视图应用缩放
- 文本选择 – 从任何面板选择和复制文本
- 保存为图像 – 将当前视图导出为图像
- 激活面板高亮 – 激活面板的视觉指示
PDFium DLL 的要求
在运行任何 PDFium VCL 应用程序之前,请确保已安装 PDFium DLL 文件:
pdfium32.dll/pdfium64.dll– 标准版本(约 5-6 MB)pdfium32v8.dll/pdfium64v8.dll– 包含 V8 JavaScript 引擎的版本(约 23-27 MB)
安装: 运行 PDFiumVCL\DLLs\CopyDlls.bat 以管理员身份,自动将 DLL 文件复制到 Windows 系统目录。
设置多个视图
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
type TFormMain = class(TForm) // Three PDF components Pdf1: TPdf; Pdf2: TPdf; Pdf3: TPdf; // Three view components PdfView1: TPdfView; PdfView2: TPdfView; PdfView3: TPdfView; // Container panels ScrollBox1: TScrollBox; ScrollBox2: TScrollBox; ScrollBox3: TScrollBox; // Splitters for resizing Splitter1: TSplitter; Splitter2: TSplitter; private FActivePdfView: TPdfView; // Currently active view FAllViewsMode: Boolean; // Apply actions to all views ThreeViewMode: Boolean; // Three-panel mode enabled end; |
在不同的视图模式之间切换
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
procedure TFormMain.SpeedButtonThreeViewClick(Sender: TObject); begin ThreeViewMode := not ThreeViewMode; SpeedButtonThreeView.Down := ThreeViewMode; UpdateLayout; end; procedure TFormMain.UpdateLayout; var TotalWidth: Integer; begin if ThreeViewMode then begin // Three view mode: equal thirds ScrollBox1.Align := alNone; ScrollBox2.Align := alNone; ScrollBox3.Align := alNone; Splitter1.Visible := False; Splitter2.Visible := False; TotalWidth := ClientWidth; ScrollBox1.Left := 0; ScrollBox1.Width := TotalWidth div 3; ScrollBox1.Height := ClientHeight - PanelButtons.Height; ScrollBox2.Left := ScrollBox1.Width; ScrollBox2.Width := TotalWidth div 3; ScrollBox2.Height := ClientHeight - PanelButtons.Height; ScrollBox3.Left := ScrollBox2.Left + ScrollBox2.Width; ScrollBox3.Width := TotalWidth - ScrollBox3.Left; ScrollBox3.Height := ClientHeight - PanelButtons.Height; ScrollBox3.Visible := True; SpeedButtonOpenPdf3.Visible := True; end else begin // Two view mode: equal halves ScrollBox3.Visible := False; Splitter2.Visible := False; TotalWidth := ClientWidth; ScrollBox1.Left := 0; ScrollBox1.Width := TotalWidth div 2; ScrollBox1.Height := ClientHeight - PanelButtons.Height; ScrollBox2.Left := ScrollBox1.Width; ScrollBox2.Width := TotalWidth - ScrollBox2.Left; ScrollBox2.Height := ClientHeight - PanelButtons.Height; SpeedButtonOpenPdf3.Visible := False; end; end; |
在每个面板中打开 PDF 文件
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
procedure TFormMain.OpenPdfFile(PdfComponent: TPdf; PdfViewComponent: TPdfView; const Title: string); var Password: string; begin if OpenDialog.Execute then begin PdfComponent.Active := False; PdfComponent.FileName := OpenDialog.FileName; PdfComponent.Password := ''; try PdfViewComponent.Active := True; except on Error: EPdfError do if Error.Message = 'Password required or incorrect password' then begin if InputQuery('Enter Password', 'Password: ', Password) then begin PdfComponent.Password := Password; PdfViewComponent.Active := True; end else raise; end else raise; end; SetActivePdfView(PdfViewComponent); UpdateControlsState; end; end; procedure TFormMain.SpeedButtonOpenPdf1Click(Sender: TObject); begin OpenPdfFile(Pdf1, PdfView1, 'PDF 1'); end; procedure TFormMain.SpeedButtonOpenPdf2Click(Sender: TObject); begin OpenPdfFile(Pdf2, PdfView2, 'PDF 2'); end; procedure TFormMain.SpeedButtonOpenPdf3Click(Sender: TObject); begin OpenPdfFile(Pdf3, PdfView3, 'PDF 3'); end; |
管理当前活动面板
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
procedure TFormMain.SetActivePdfView(PdfView: TPdfView); begin FActivePdfView := PdfView; // Visual feedback for active panel if PdfView = PdfView1 then begin ScrollBox1.Color := clHighlight; ScrollBox2.Color := clWindow; ScrollBox3.Color := clWindow; end else if PdfView = PdfView2 then begin ScrollBox1.Color := clWindow; ScrollBox2.Color := clHighlight; ScrollBox3.Color := clWindow; end else if PdfView = PdfView3 then begin ScrollBox1.Color := clWindow; ScrollBox2.Color := clWindow; ScrollBox3.Color := clHighlight; end; UpdateControlsState; end; procedure TFormMain.PdfView1Click(Sender: TObject); begin SetActivePdfView(PdfView1); end; procedure TFormMain.PdfView2Click(Sender: TObject); begin SetActivePdfView(PdfView2); end; procedure TFormMain.PdfView3Click(Sender: TObject); begin SetActivePdfView(PdfView3); end; |
将操作应用于当前活动视图或所有视图
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
procedure TFormMain.ApplyToAllViews(const Operation: string); begin if FAllViewsMode then begin // Apply to all active views if PdfView1.Active then ApplyOperation(PdfView1, Operation); if PdfView2.Active then ApplyOperation(PdfView2, Operation); if PdfView3.Active and ThreeViewMode then ApplyOperation(PdfView3, Operation); end else begin // Apply only to active view if Assigned(FActivePdfView) then ApplyOperation(FActivePdfView, Operation); end; end; procedure TFormMain.SpeedButtonZoomInClick(Sender: TObject); begin ApplyToAllViews('ZoomIn'); end; procedure TFormMain.SpeedButtonZoomOutClick(Sender: TObject); begin ApplyToAllViews('ZoomOut'); end; |
同步页面导航(可选)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
procedure TFormMain.SynchronizePages(SourceView: TPdfView); var PageNum: Integer; begin if not chkSynchronize.Checked then Exit; PageNum := SourceView.PageNumber; // Apply to other views if (SourceView <> PdfView1) and PdfView1.Active then if PageNum <= PdfView1.PageCount then PdfView1.PageNumber := PageNum; if (SourceView <> PdfView2) and PdfView2.Active then if PageNum <= PdfView2.PageCount then PdfView2.PageNumber := PageNum; if (SourceView <> PdfView3) and PdfView3.Active and ThreeViewMode then if PageNum <= PdfView3.PageCount then PdfView3.PageNumber := PageNum; end; |
独立的缩放控件
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
procedure TFormMain.DoZoom1; begin if PdfView1.Active and (PdfView1.PageNumber > 0) then begin case ComboBoxZoom.ItemIndex of 0: PdfView1.Zoom := 0.5; 1: PdfView1.Zoom := 0.75; 2: PdfView1.Zoom := 1.0; 3: PdfView1.Zoom := 1.5; 4: PdfView1.Zoom := 2.0; 5: PdfView1.Zoom := PdfView1.PageWidthZoom[PdfView1.PageNumber]; 6: PdfView1.Zoom := PdfView1.PageZoom[PdfView1.PageNumber]; end; end; end; procedure TFormMain.DoZoom2; begin if PdfView2.Active and (PdfView2.PageNumber > 0) then begin // Same zoom logic for view 2 end; end; procedure TFormMain.DoZoom3; begin if PdfView3.Active and (PdfView3.PageNumber > 0) then begin // Same zoom logic for view 3 end; end; |
将当前视图保存为图像
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
procedure TFormMain.MenuItemSaveAsImage1Click(Sender: TObject); begin SaveViewAsImage(PdfView1, Pdf1); end; procedure TFormMain.SaveViewAsImage(PdfView: TPdfView; Pdf: TPdf); var Bitmap: TBitmap; JpegImage: TJpegImage; begin if not PdfView.Active then begin ShowMessage('No document loaded in this view.'); Exit; end; SavePictureDialog.FileName := 'page_' + IntToStr(PdfView.PageNumber) + '.jpg'; if SavePictureDialog.Execute then begin Pdf.PageNumber := PdfView.PageNumber; Bitmap := Pdf.RenderPage( 0, 0, Round(Pdf.PageWidth * 2), // 2x resolution Round(Pdf.PageHeight * 2), PdfView.Rotation, [], clWhite ); try JpegImage := TJpegImage.Create; try JpegImage.Assign(Bitmap); JpegImage.CompressionQuality := 90; JpegImage.SaveToFile(SavePictureDialog.FileName); ShowMessage('Image saved successfully.'); finally JpegImage.Free; end; finally Bitmap.Free; end; end; end; |
在每个面板中进行文本选择
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
procedure TFormMain.PdfView1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin SetActivePdfView(PdfView1); if Button = mbLeft then begin Selecting := True; SelectionStart := PdfView1.CharacterIndexAtPos(X, Y, 5.0, 5.0); SelectionEnd := SelectionStart; end; end; procedure TFormMain.PdfView1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if Selecting then begin SelectionEnd := PdfView1.CharacterIndexAtPos(X, Y, 5.0, 5.0); PdfView1.Invalidate; end; end; procedure TFormMain.PdfView1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Selecting := False; end; |
用例
- 文档修订审查 – 比较原始文档和修订后的文档
- 质量控制 验证生产环境与模板的一致性。
- 法律审核。 比较合同版本。
- 翻译验证。 查看原始文档和已翻译文档。
- 多语言文档。 查看相同内容的不同语言版本。
结论。
Split View 演示展示了 PDFium VCL 在构建高级文档比较工具方面的灵活性。它支持多个独立的视图,同步导航以及每个面板的控件,您可以创建专业的比较应用程序。
能够在每个面板中打开不同的 PDF 文件并进行视觉比较,对于修订审查和质量控制工作流程非常有价值。
构建强大的文档比较工具 使用 Delphi PDFium VCL 组件.