Artículo técnico

Creación de un visor de PDF de varias páginas con desplazamiento continuo en Delphi

· Programación PDF

Este tutorial explora el Visor de múltiples páginas. demo, que extiende el visor de PDF básico con capacidades de desplazamiento continuo. Este modo de visualización es similar a cómo los lectores de PDF modernos, como Adobe Acrobat, muestran los documentos, lo que permite a los usuarios desplazarse por todas las páginas de forma fluida.

Resumen

La demostración del visor de múltiples páginas muestra modos de visualización avanzados en PDFium VCL, incluyendo la navegación continua de una sola página y la navegación continua de dos páginas (modo libro). Estas características son esenciales para crear una experiencia de lectura de PDF profesional.

Modos de visualización.

PDFium VCL admite múltiples modos de visualización a través de. DisplayMode propiedad:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type
  TPdfDisplayMode = (
    dmSingleContinuous,  // Single page with continuous vertical scrolling
    dmDoubleContinuous   // Two pages side-by-side (book layout)
  );
 
// Switch between display modes
procedure TFormMain.ComboBoxDisplayModeChange(Sender: TObject);
begin
  case ComboBoxDisplayMode.ItemIndex of
    0: PdfView.DisplayMode := dmSingleContinuous;
    1: PdfView.DisplayMode := dmDoubleContinuous;
  end;
end;

Características principales

  • Desplazamiento continuo. – Desplázate por todas las páginas sin navegación página por página.
  • Modo de doble página. – Visualiza dos páginas una al lado de la otra, como un libro físico.
  • Selección de texto entre páginas. – Selecciona y copia texto que abarca varias páginas.
  • Navegación por marcadores. – Salta instantáneamente a las secciones marcadas.
  • Búsqueda con resaltado. – Buscar y resaltar texto en todo el documento.
  • Navegación con el teclado – Soporte para las teclas de flecha, Page Up/Down, Home/End.
  • Rendimiento optimizado. – Solo renderiza las páginas visibles para una navegación fluida.

Requisitos de la DLL PDFium

Antes de ejecutar cualquier aplicación PDFium VCL, debe instalar los archivos DLL de PDFium. Los archivos DLL se encuentran en: DLLs carpeta:

  • pdfium32.dll / pdfium64.dll – Versiones estándar para la mayoría de las aplicaciones.
  • pdfium32v8.dll / pdfium64v8.dll – Versiones extendidas con el motor de JavaScript V8.

Instalación: Ejecutar PDFiumVCL\DLLs\CopyDlls.bat Como administrador, copie los archivos DLL en los directorios del sistema de Windows. En Windows de 64 bits, los archivos DLL de 32 bits deben ir a SysWOW64 y los archivos DLL de 64 bits deben ir a System32.

Configuración del componente.

La demostración implementa un sistema de selección de texto sofisticado:

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
procedure TFormMain.PdfViewMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  CharIndex: Integer;
begin
  if Button = mbLeft then
  begin
    // Get character index at click position
    CharIndex := GetPreciseCharacterIndex(X, Y);
    
    if CharIndex >= 0 then
    begin
      SelectionMode := True;
      Selecting := True;
      SelectionStart := CharIndex;
      SelectionEnd := CharIndex;
    end;
  end;
end;
 
procedure TFormMain.PdfViewMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
var
  CharIndex: Integer;
begin
  if Selecting then
  begin
    CharIndex := GetPreciseCharacterIndex(X, Y);
    if CharIndex >= 0 then
    begin
      SelectionEnd := CharIndex;
      PdfView.Invalidate; // Redraw to show selection
    end;
  end;
end;

Detección del índice de caracteres.

Para una selección de texto precisa, la demostración utiliza una tolerancia adaptada al zoom para la detección de caracteres:

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
function TFormMain.GetPreciseCharacterIndex(X, Y: Integer): Integer;
var
  BaseTolerance: Single;
  ZoomFactor: Single;
  AdjustedTolerance: Single;
  CharIndex: Integer;
begin
  Result := -1;
  
  if not PdfView.Active then
    Exit;
    
  // Calculate dynamic tolerance based on zoom level
  ZoomFactor := PdfView.Zoom;
  BaseTolerance := 5.0;
  
  // Adjust tolerance inversely to zoom
  AdjustedTolerance := BaseTolerance / ZoomFactor;
  
  // Get character at position with tolerance
  CharIndex := PdfView.CharacterIndexAtPos(X, Y,
    AdjustedTolerance, AdjustedTolerance);
    
  Result := CharIndex;
end;

Resaltado del texto seleccionado.

La demostración resalta las selecciones en la OnPaint evento:

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.PdfViewPaint(Sender: TObject);
var
  I, StartIdx, EndIdx: Integer;
  Rect: TPdfRectangle;
  R: TRect;
begin
  if (SelectionStart >= 0) and (SelectionEnd >= 0) then
  begin
    StartIdx := Min(SelectionStart, SelectionEnd);
    EndIdx := Max(SelectionStart, SelectionEnd);
    
    // Draw highlight for each character in selection
    for I := StartIdx to EndIdx do
    begin
      Rect := PdfView.CharacterRectangle[I];
      
      // Convert PDF coordinates to screen coordinates
      if PdfView.PageToDevice(
        Rect.Left, Rect.Top,
        PdfView.Left, PdfView.Top,
        PdfView.Width, PdfView.Height,
        PdfView.Rotation, R.Left, R.Top) then
      begin
        // Draw highlight rectangle
        PdfView.Canvas.Brush.Color := clHighlight;
        PdfView.Canvas.Brush.Style := bsSolid;
        PdfView.Canvas.FillRect(R);
      end;
    end;
  end;
end;

Copiar texto seleccionado al portapapeles

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
procedure TFormMain.MenuItemCopyClick(Sender: TObject);
var
  StartIdx, EndIdx: Integer;
  SelectedText: string;
begin
  if (SelectionStart >= 0) and (SelectionEnd >= 0) then
  begin
    StartIdx := Min(SelectionStart, SelectionEnd);
    EndIdx := Max(SelectionStart, SelectionEnd);
    
    // Set page number for text extraction
    Pdf.PageNumber := PdfView.PageNumber;
    
    // Extract text from selection range
    SelectedText := Pdf.Text(StartIdx, EndIdx - StartIdx + 1);
    
    // Copy to clipboard
    Clipboard.AsText := SelectedText;
  end;
end;

Funcionalidad de búsqueda

Implementar búsqueda de texto con resaltado:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
procedure TFormMain.SpeedButtonSearchClick(Sender: TObject);
var
  SearchText: string;
  FoundIndex: Integer;
begin
  SearchText := EditSearch.Text;
  
  if SearchText = '' then
    Exit;
    
  // Find first occurrence
  FoundIndex := Pdf.FindFirst(SearchText, [], 0, True);
  
  if FoundIndex >= 0 then
  begin
    SearchStart := FoundIndex;
    SearchEnd := FoundIndex + Length(SearchText) - 1;
    PdfView.Invalidate; // Redraw to show highlight
  end
  else
    ShowMessage('Text not found');
end;

Evento de cambio de página

Manejar los cambios de página para actualizar los elementos de la interfaz de usuario:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
procedure TFormMain.PdfViewPageChanged(Sender: TObject);
begin
  if PdfView.Active then
  begin
    // Update page indicator
    SpeedButtonPageNumber.Caption :=
      IntToStr(PdfView.PageNumber) + ' of ' + IntToStr(PdfView.PageCount);
    
    // Update navigation button states
    SpeedButtonFirstPage.Enabled := PdfView.PageNumber > 1;
    SpeedButtonPreviousPage.Enabled := PdfView.PageNumber > 1;
    SpeedButtonNextPage.Enabled := PdfView.PageNumber < PdfView.PageCount;
    SpeedButtonLastPage.Enabled := PdfView.PageNumber < PdfView.PageCount;
    
    // Update bookmark tree selection
    if not DisableBookmarks then
      UpdateBookmarkSelection(PdfView.PageNumber);
  end;
end;

Navegación con el teclado

La demostración gestiona atajos de teclado para la navegación:

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
procedure TFormMain.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
    VK_ESCAPE:
      begin
        // Exit selection mode on Escape
        if SelectionMode then
        begin
          SelectionMode := False;
          SelectionStart := -1;
          SelectionEnd := -1;
          PdfView.Invalidate;
        end;
        Key := 0;
      end;
      
    VK_PRIOR, VK_UP, VK_LEFT:
      begin
        if SpeedButtonPreviousPage.Enabled then
          SpeedButtonPreviousPage.Click;
        Key := 0;
      end;
      
    VK_NEXT, VK_DOWN, VK_RIGHT:
      begin
        if SpeedButtonNextPage.Enabled then
          SpeedButtonNextPage.Click;
        Key := 0;
      end;
      
    VK_HOME:
      begin
        if SpeedButtonFirstPage.Enabled then
          SpeedButtonFirstPage.Click;
        Key := 0;
      end;
      
    VK_END:
      begin
        if SpeedButtonLastPage.Enabled then
          SpeedButtonLastPage.Click;
        Key := 0;
      end;
  end;
end;

Navegación de doble página

En modo de doble página, navegue dos páginas a la vez:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
procedure TFormMain.SpeedButtonNextPageClick(Sender: TObject);
begin
  if PdfView.DisplayMode = dmSingleContinuous then
    PdfView.PageNumber := PdfView.PageNumber + 1
  else
    PdfView.PageNumber := PdfView.PageNumber + 2;
end;
 
procedure TFormMain.SpeedButtonPreviousPageClick(Sender: TObject);
begin
  if PdfView.DisplayMode = dmSingleContinuous then
    PdfView.PageNumber := PdfView.PageNumber - 1
  else
    PdfView.PageNumber := PdfView.PageNumber - 2;
end;

Conclusión.

La demostración de visor de múltiples páginas muestra cómo crear un lector de PDF con todas las funciones, con desplazamiento continuo, selección de texto y funcionalidad de búsqueda. Estas son las funciones que los usuarios esperan de las aplicaciones modernas de visualización de PDF.

PDFium VCL se encarga de la renderización y extracción de texto complejas, mientras que usted se centra en la interfaz de usuario y las funciones específicas de la aplicación. El resultado es una experiencia de visualización de PDF fluida y receptiva que rivaliza con los lectores de PDF comerciales.

Obtenga Componente PDFium VCL en loslab.com y comience a crear aplicaciones de PDF profesionales en Delphi hoy mismo.