本教程探讨了 多页查看器 示例,它扩展了基本的 PDF 查看器,增加了连续滚动功能。这种查看模式类似于现代 PDF 阅读器(如 Adobe Acrobat)显示文档的方式,允许用户无缝滚动浏览所有页面。
概述
多页查看器示例展示了 PDFium VCL 中的高级查看模式,包括单页连续滚动和双页连续滚动(书籍模式)。这些功能对于创建专业的 PDF 阅读体验至关重要。
显示模式
PDFium VCL 通过 DisplayMode 属性支持多种显示模式:
|
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; |
主要特性
- 连续滚动 无需逐页浏览,即可滚动浏览所有页面。
- 双页模式。 像翻书一样,同时查看两页内容。
- 跨页文本选择。 选取并复制跨越多个页面的文本。
- 书签导航。 快速跳转到已添加书签的部分。
- 带有高亮显示的搜索功能。 查找并高亮文档中的文本。
- 键盘导航。 箭头键、Page Up/Down、Home/End 快捷键支持。
- 优化性能。 只渲染可见页面,以实现流畅的滚动。
PDFium DLL 的要求
在运行任何 PDFium VCL 应用程序之前,必须安装 PDFium DLL 文件。这些 DLL 文件位于: DLLs 文件夹:
pdfium32.dll/pdfium64.dll标准版本,适用于大多数应用程序。pdfium32v8.dll/pdfium64v8.dll扩展版本,采用 V8 JavaScript 引擎。
安装: 运行 PDFiumVCL\DLLs\CopyDlls.bat 以管理员身份复制 DLL 文件到 Windows 系统目录。在 64 位 Windows 系统上,32 位 DLL 文件应放置在 SysWOW64 ,而 64 位 DLL 文件应放置在 System32.
组件设置。
该演示程序实现了复杂的文本选择系统:
|
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; |
字符索引检测。
为了实现精确的文本选择,该演示程序使用基于缩放的容差来进行字符检测:
|
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; |
突出显示选定的文本。
演示中,选中的内容会以高亮显示。 OnPaint 事件:
|
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; |
复制选中文本到剪贴板。
|
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; |
搜索功能。
实现带高亮的文本搜索:
|
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; |
页面切换事件。
处理页面切换以更新 UI 元素:
|
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; |
键盘导航。
演示程序支持键盘快捷键进行导航。
|
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; |
双页导航
在双页模式下,一次导航两个页面。
|
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; |
结论。
Multi-Page Viewer 演示程序展示了如何构建一个功能完善的 PDF 阅读器,具有连续滚动、文本选择和搜索功能。 这些是用户期望在现代 PDF 查看应用程序中看到的特性。
PDFium VCL 负责复杂的渲染和文本提取,而您可以专注于用户界面和特定于应用程序的功能。 结果是流畅、响应迅速的 PDF 查看体验,可与商业 PDF 阅读器相媲美。
获取 PDFium VCL 组件 at loslab.com,立即开始使用 Delphi 构建专业的 PDF 应用程序。