Artigo técnico

Criando um visualizador de PDF de várias páginas com rolagem contínua em Delphi

· Programação PDF

Este tutorial explora a demonstração do Visualizador de Múltiplas Páginas (Multi-Page Viewer), que estende o visualizador de PDF básico com recursos de rolagem contínua. Este modo de visualização é semelhante à forma como os leitores de PDF modernos, como o Adobe Acrobat, exibem documentos, permitindo que os usuários naveguem por todas as páginas de forma contínua.

Visão Geral

A demonstração do Visualizador de Múltiplas Páginas mostra os modos de visualização avançados no PDFium VCL, incluindo a rolagem contínua de uma única página e a rolagem contínua de duas páginas (modo livro). Esses recursos são essenciais para criar uma experiência de leitura de PDF profissional.

Modos de Exibição

O PDFium VCL suporta vários modos de exibição através da propriedade: DisplayMode Rolagem Contínua (Continuous Scrolling)

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;

Principais Características

  • Rolagem Contínua (Continuous Scrolling) – Navegue por todas as páginas sem a necessidade de passar página por página.
  • Modo de Duas Páginas – Visualize duas páginas lado a lado, como em um livro físico.
  • Seleção de Texto entre Páginas – Selecione e copie texto que abrange várias páginas.
  • Navegação por Marcadores – Acesse instantaneamente as seções marcadas.
  • Pesquisa com Realce – Encontre e destaque texto em todo o documento.
  • Navegação por teclado. – Suporte para as teclas de seta, Page Up/Down, Home/End.
  • Desempenho otimizado. – Renderiza apenas as páginas visíveis para uma rolagem suave.

Requisitos da DLL PDFium

Antes de executar qualquer aplicação PDFium VCL, você deve instalar os arquivos DLL do PDFium. Os arquivos DLL estão localizados em: DLLs pasta:

  • pdfium32.dll / pdfium64.dll – Versões padrão para a maioria das aplicações.
  • pdfium32v8.dll / pdfium64v8.dll – Versões estendidas com o motor JavaScript V8.

Instalação: Executar PDFiumVCL\DLLs\CopyDlls.bat Como administrador, copie os arquivos DLL para os diretórios do sistema Windows. No Windows de 64 bits, os arquivos DLL de 32 bits devem ser colocados em SysWOW64 e os arquivos DLL de 64 bits devem ser colocados em System32.

Configuração do Componente.

A demonstração implementa um sistema sofisticado de seleção de texto:

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;

Detecção do Índice de Caracteres.

Para uma seleção de texto precisa, a demonstração usa uma tolerância adaptada ao zoom para a detecção 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;

Realce do Texto Selecionado.

A demonstração destaca as seleções. 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 selecionado para a área de transferência.

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;

Funcionalidade de pesquisa.

Implementar pesquisa de texto com destaque:

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 mudança de página.

Lidar com as mudanças de página para atualizar os elementos da interface do usuário:

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;

Navegação por teclado.

A demonstração lida com atalhos de teclado para navegação:

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;

Navegação em Duas Páginas

No modo de duas páginas, navegue duas páginas por 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;

Conclusão.

A demonstração do Visualizador de Múltiplas Páginas mostra como criar um leitor de PDF completo com rolagem contínua, seleção de texto e funcionalidade de pesquisa. Essas são as funcionalidades que os usuários esperam de aplicativos modernos de visualização de PDF.

O PDFium VCL lida com a renderização e extração de texto complexas, enquanto você se concentra na interface do usuário e nos recursos específicos do aplicativo. O resultado é uma experiência de visualização de PDF suave e responsiva que rivaliza com os leitores de PDF comerciais.

Obtenha Componente PDFium VCL em loslab.com e comece a criar aplicativos de PDF profissionais em Delphi hoje mesmo.