مقالة تقنية

طباعة مستندات PDF باستخدام PDFium VCL في دلفي

· برمجة PDF

طباعة مستندات PDF بدقة عالية ومقياس مناسب هو مطلب شائع. Print PDF يوضح العرض التوضيحي كيفية تنفيذ الطباعة الاحترافية لمستندات PDF مع معاينة، واختيار الصفحات، وخيارات الجودة باستخدام مكون PDFium VCL.

نظرة عامة

يوفر هذا العرض التوضيحي الشامل حلاً كاملاً للطباعة، بما في ذلك معاينة الطباعة، واختيار نطاق الصفحات، وإعدادات الجودة، وخيارات المقياس، وسجل الملفات الأخير. يوضح أفضل الممارسات للطباعة في تطبيقات Delphi.

الميزات الرئيسية

  • معاينة الطباعة. – معاينة مرئية قبل الطباعة.
  • Page Selection – طباعة جميع الصفحات أو نطاقات محددة.
  • إعدادات الجودة. – أوضاع المسودة، والعادية، وعالية الجودة.
  • خيارات التحجيم. – ملاءمة الصفحة، أو تصغير لتناسب، أو عدم التحجيم.
  • نسخ متعددة. – طباعة نسخ متعددة مع الترتيب.
  • تتبع التقدم. – ملاحظات مرئية أثناء الطباعة.
  • الملفات الأخيرة. - وصول سريع إلى المستندات المطبوعة سابقًا.

متطلبات ملف PDFium DLL.

قبل تشغيل أي تطبيق PDFium VCL، تأكد من تثبيت ملفات PDFium DLL:

  • pdfium32.dll / pdfium64.dll – الإصدارات القياسية (حوالي 5-6 ميجابايت).
  • pdfium32v8.dll / pdfium64v8.dll – مع محرك JavaScript V8 (حوالي 23-27 ميجابايت).

التثبيت: تشغيل PDFiumVCL\DLLs\CopyDlls.bat بصلاحيات المسؤول لنسخ ملفات DLL تلقائيًا إلى مجلدات نظام Windows.

الطباعة الأساسية لملفات 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
procedure PrintPdfSimple(const FileName: string);
var
  Pdf: TPdf;
  I: Integer;
  Bitmap: TBitmap;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := FileName;
    Pdf.Active := True;
    
    Printer.Title := Pdf.Title;
    Printer.BeginDoc;
    try
      for I := 1 to Pdf.PageCount do
      begin
        if I > 1 then
          Printer.NewPage;
          
        Pdf.PageNumber := I;
        
        // Render page to printer
        Bitmap := Pdf.RenderPage(
          0, 0,
          Printer.PageWidth,
          Printer.PageHeight,
          ro0,
          [rePrinting]
        );
        try
          PrintBitmap(Printer, Bitmap);
        finally
          Bitmap.Free;
        end;
      end;
    finally
      Printer.EndDoc;
    end;
    
  finally
    Pdf.Active := False;
    Pdf.Free;
  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 PrintBitmap(Printer: TPrinter; Bitmap: TBitmap);
var
  InfoHeaderSize, ImageSize: DWORD;
  InfoHeader: PBitmapInfo;
  Image: Pointer;
begin
  GetDIBSizes(Bitmap.Handle, InfoHeaderSize, ImageSize);
  
  InfoHeader := AllocMem(InfoHeaderSize);
  try
    Image := AllocMem(ImageSize);
    try
      GetDIB(Bitmap.Handle, 0, InfoHeader^, Image^);
      
      StretchDIBits(
        Printer.Canvas.Handle,
        0, 0, Bitmap.Width, Bitmap.Height,
        0, 0, Bitmap.Width, Bitmap.Height,
        Image, InfoHeader^,
        DIB_RGB_COLORS, SRCCOPY
      );
    finally
      FreeMem(Image);
    end;
  finally
    FreeMem(InfoHeader);
  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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
procedure TFormMain.PrintPDFPages;
var
  FromPage, ToPage, Page, Copy, CopyCount: Integer;
  FirstPage: Boolean;
  Bitmap: TBitmap;
  ScaleX, ScaleY, Scale: Double;
  DestWidth, DestHeight: Integer;
  Dpi: Integer;
begin
  // Get print quality DPI
  case cmbQuality.ItemIndex of
    0: Dpi := 150;  // Draft
    1: Dpi := 300;  // Normal
    2: Dpi := 600;  // High
  else
    Dpi := 300;
  end;
  
  // Determine page range
  if radAllPages.Checked then
  begin
    FromPage := 1;
    ToPage := Pdf.PageCount;
  end
  else
  begin
    FromPage := StrToIntDef(edtFromPage.Text, 1);
    ToPage := StrToIntDef(edtToPage.Text, Pdf.PageCount);
  end;
  
  // Handle copies and collation
  if chkCollate.Checked then
    CopyCount := 1  // Will repeat entire job
  else
    CopyCount := spnCopies.Value;
    
  FProcessing := True;
  FCancelled := False;
  
  Printer.Title := ExtractFileName(Pdf.FileName);
  Printer.BeginDoc;
  try
    FirstPage := True;
    progressPrint.Max := (ToPage - FromPage + 1) * spnCopies.Value;
    progressPrint.Position := 0;
    
    for Page := FromPage to ToPage do
    begin
      for Copy := 1 to CopyCount do
      begin
        if FCancelled then
          Break;
          
        if FirstPage then
          FirstPage := False
        else
          Printer.NewPage;
          
        Pdf.PageNumber := Page;
        
        // Calculate scaling based on settings
        case cmbScaling.ItemIndex of
          0: // No scaling
          begin
            DestWidth := Round(Pdf.PageWidth * Dpi / 72);
            DestHeight := Round(Pdf.PageHeight * Dpi / 72);
          end;
          
          1: // Fit to page
          begin
            ScaleX := Printer.PageWidth / (Pdf.PageWidth * Dpi / 72);
            ScaleY := Printer.PageHeight / (Pdf.PageHeight * Dpi / 72);
            Scale := Min(ScaleX, ScaleY);
            DestWidth := Round(Pdf.PageWidth * Dpi / 72 * Scale);
            DestHeight := Round(Pdf.PageHeight * Dpi / 72 * Scale);
          end;
          
          2: // Shrink to fit (only if needed)
          begin
            ScaleX := Printer.PageWidth / (Pdf.PageWidth * Dpi / 72);
            ScaleY := Printer.PageHeight / (Pdf.PageHeight * Dpi / 72);
            Scale := Min(ScaleX, ScaleY);
            if Scale > 1 then Scale := 1;
            DestWidth := Round(Pdf.PageWidth * Dpi / 72 * Scale);
            DestHeight := Round(Pdf.PageHeight * Dpi / 72 * Scale);
          end;
        end;
        
        // Render and print
        Bitmap := Pdf.RenderPage(0, 0, DestWidth, DestHeight,
          ro0, [rePrinting, reAnnotations]);
        try
          PrintBitmap(Printer, Bitmap);
        finally
          Bitmap.Free;
        end;
        
        progressPrint.Position := progressPrint.Position + 1;
        Application.ProcessMessages;
      end;
      
      if FCancelled then
        Break;
    end;
    
  finally
    Printer.EndDoc;
    FProcessing := False;
  end;
end;

استخدام مربع حوار الطباعة.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
procedure TFormMain.btnPrintClick(Sender: TObject);
begin
  if not FileExists(edtPdfFile.Text) then
  begin
    ShowError('Please select a valid PDF file first.');
    Exit;
  end;
  
  // Setup print dialog
  PrintDialog.MinPage := 1;
  PrintDialog.MaxPage := Pdf.PageCount;
  PrintDialog.FromPage := 1;
  PrintDialog.ToPage := Pdf.PageCount;
  PrintDialog.Options := [poPageNums, poSelection];
  
  if PrintDialog.Execute then
  begin
    PrintPDFPages;
  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
procedure TFormMain.UpdatePreview;
var
  PreviewWidth, PreviewHeight: Integer;
  Scale: Double;
begin
  if not Pdf.Active then
    Exit;
    
  Pdf.PageNumber := FCurrentPreviewPage;
  
  // Calculate preview size to fit panel
  Scale := Min(
    pnlPreview.Width / Pdf.PageWidth,
    pnlPreview.Height / Pdf.PageHeight
  ) * (FCurrentZoom / 100);
  
  PreviewWidth := Round(Pdf.PageWidth * Scale);
  PreviewHeight := Round(Pdf.PageHeight * Scale);
  
  // Render preview
  FPreviewBitmap.Free;
  FPreviewBitmap := Pdf.RenderPage(
    0, 0, PreviewWidth, PreviewHeight,
    ro0, [reAnnotations], clWhite
  );
  
  // Display in image control
  imgPreview.Picture.Assign(FPreviewBitmap);
  
  // Update page info
  lblPageInfo.Caption := Format('Page %d of %d',
    [FCurrentPreviewPage, Pdf.PageCount]);
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
procedure TFormMain.btnFirstPageClick(Sender: TObject);
begin
  if Pdf.Active then
  begin
    FCurrentPreviewPage := 1;
    edtPreviewPage.Text := '1';
    UpdatePreview;
  end;
end;
 
procedure TFormMain.btnPrevPageClick(Sender: TObject);
begin
  if Pdf.Active and (FCurrentPreviewPage > 1) then
  begin
    Dec(FCurrentPreviewPage);
    edtPreviewPage.Text := IntToStr(FCurrentPreviewPage);
    UpdatePreview;
  end;
end;
 
procedure TFormMain.btnNextPageClick(Sender: TObject);
begin
  if Pdf.Active and (FCurrentPreviewPage < Pdf.PageCount) then
  begin
    Inc(FCurrentPreviewPage);
    edtPreviewPage.Text := IntToStr(FCurrentPreviewPage);
    UpdatePreview;
  end;
end;
 
procedure TFormMain.btnLastPageClick(Sender: TObject);
begin
  if Pdf.Active then
  begin
    FCurrentPreviewPage := Pdf.PageCount;
    edtPreviewPage.Text := IntToStr(FCurrentPreviewPage);
    UpdatePreview;
  end;
end;

التحكم في التكبير.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
procedure TFormMain.cmbZoomChange(Sender: TObject);
begin
  case cmbZoom.ItemIndex of
    0: FCurrentZoom := 50;
    1: FCurrentZoom := 75;
    2: FCurrentZoom := 100;
    3: FCurrentZoom := 125;
    4: FCurrentZoom := 150;
    5: FCurrentZoom := 200;
  else
    FCurrentZoom := 100;
  end;
  
  UpdatePreview;
end;

معالجة تدوير الصفحة.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function GetPrintRotation(Rotation: TRotation): TRotation;
begin
  // Adjust rotation for printing (printer coordinate system)
  case Rotation of
    ro90:  Result := ro270;
    ro270: Result := ro90;
  else
    Result := Rotation;
  end;
end;
 
// Use in printing
Bitmap := Pdf.RenderPage(0, 0, Width, Height,
  GetPrintRotation(Pdf.PageRotation), [rePrinting]);

حفظ/تحميل الإعدادات.

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
procedure TFormMain.SaveSettings;
var
  Ini: TIniFile;
begin
  Ini := TIniFile.Create(FSettingsFile);
  try
    Ini.WriteInteger('Print', 'Quality', cmbQuality.ItemIndex);
    Ini.WriteInteger('Print', 'Scaling', cmbScaling.ItemIndex);
    Ini.WriteInteger('Print', 'Copies', spnCopies.Value);
    Ini.WriteBool('Print', 'Collate', chkCollate.Checked);
    Ini.WriteInteger('Preview', 'Zoom', FCurrentZoom);
  finally
    Ini.Free;
  end;
end;
 
procedure TFormMain.LoadSettings;
var
  Ini: TIniFile;
begin
  if FileExists(FSettingsFile) then
  begin
    Ini := TIniFile.Create(FSettingsFile);
    try
      cmbQuality.ItemIndex := Ini.ReadInteger('Print', 'Quality', 1);
      cmbScaling.ItemIndex := Ini.ReadInteger('Print', 'Scaling', 1);
      spnCopies.Value := Ini.ReadInteger('Print', 'Copies', 1);
      chkCollate.Checked := Ini.ReadBool('Print', 'Collate', False);
      FCurrentZoom := Ini.ReadInteger('Preview', 'Zoom', 100);
    finally
      Ini.Free;
    end;
  end;
end;

حالات الاستخدام.

  • طباعة المستندات. - طباعة عالية الجودة لمستندات PDF.
  • الطباعة المجمعة. - طباعة مستندات متعددة بالتسلسل.
  • توزيع التقارير. – طباعة التقارير للتوزيع.
  • طباعة معاينة. – قم بطباعة نماذج قبل الإنتاج النهائي.

الخلاصة.

تُظهر نسخة "Print PDF" التجريبية كيفية تنفيذ الطباعة الاحترافية لملفات PDF باستخدام PDFium VCL. بدءًا من الطباعة البسيطة لصفحة واحدة وصولًا إلى مهام الطباعة المتقدمة لنسخ متعددة مع إعدادات المعاينة والجودة، يوفر هذا المكون كل ما تحتاجه.

الـ RenderPage الطريقة مع. rePrinting تضمن هذه الإعدادات الحصول على أفضل النتائج عند الطباعة، بينما تتيح وظيفة المعاينة للمستخدمين التحقق من إعداداتهم قبل الطباعة.

أضف طباعة احترافية لمستندات PDF. أضفه إلى تطبيقاتك باستخدام. مكون PDFium لـ Delphi..