Articolo tecnico

Utilizzo di PDFium VCL in Delphi per il confronto affiancato di documenti PDF

· Programmazione PDF

Confrontare più documenti PDF affiancati è essenziale per la revisione, il controllo qualità e la verifica dei documenti. Vista Divisa La demo mostra come visualizzare contemporaneamente due o tre documenti PDF utilizzando PDFium VCL.

Panoramica

Questa demo avanzata visualizza più documenti PDF in viste sincronizzate, consentendo agli utenti di confrontare visivamente i documenti. Supporta sia la modalità di confronto a due vie che a tre vie, con controlli di navigazione e zoom indipendenti per ogni vista.

Caratteristiche Principali

  • Modalità a Due Pannelli – Confronta due documenti affiancati.
  • Modalità a tre pannelli. – Confronta contemporaneamente tre documenti.
  • Navigazione indipendente. – Naviga in ciascun documento in modo indipendente.
  • Zoom sincronizzato. – Applica lo zoom a tutte le visualizzazioni o individualmente.
  • Selezione del testo. – Seleziona e copia il testo da qualsiasi pannello.
  • Salva come immagine – Esporta la vista corrente come immagine
  • Evidenziazione del pannello attivo – Indicazione visiva del pannello attivo

Requisiti delle librerie DLL di PDFium

Prima di eseguire qualsiasi applicazione VCL di PDFium, assicurarsi che i file DLL di PDFium siano installati:

  • pdfium32.dll / pdfium64.dll – Versioni standard (~5-6 MB)
  • pdfium32v8.dll / pdfium64v8.dll – Con il motore JavaScript V8 (~23-27 MB)

Installazione: Esegui PDFiumVCL\DLLs\CopyDlls.bat come amministratore per copiare automaticamente i file DLL nelle directory di sistema di Windows.

Configurazione di più visualizzazioni.

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;

Passaggio tra le modalità di visualizzazione.

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;

Apertura di file PDF in ciascun pannello.

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;

Gestione del pannello attivo.

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;

Applicazione di azioni al pannello attivo o a tutte le visualizzazioni.

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;

Navigazione sincronizzata delle pagine (opzionale).

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;

Controlli di zoom indipendenti.

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;

Salvare la visualizzazione corrente come immagine.

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;

Selezione del testo in ogni pannello.

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;

Casi d'uso.

  • Revisione delle revisioni dei documenti. – Confronta i documenti originali e le versioni riviste.
  • Controllo qualità. Verifica della produzione rispetto ai modelli.
  • Revisione legale. Confronta le versioni dei contratti.
  • Verifica della traduzione. Visualizza i documenti originali e tradotti.
  • Documenti multilingue. Visualizza lo stesso contenuto in lingue diverse.

Conclusione.

La demo di Split View mostra la flessibilità di PDFium VCL per la creazione di strumenti avanzati di confronto documenti. Grazie al supporto per viste multiple e indipendenti, alla navigazione sincronizzata e ai controlli per pannello, è possibile creare applicazioni di confronto professionali.

La possibilità di aprire diversi file PDF in ciascun pannello e confrontarli visivamente è preziosa per le revisioni e i processi di controllo qualità.

Crea potenti strumenti di confronto documenti. con Componente Delphi PDFium VCL..