Conversione di file RTF in PDF: una guida per sviluppatori Delphi, C# e VB.Net.
Nel mondo dell'elaborazione dei documenti, la conversione di file Rich Text Format (RTF) in Portable Document Format (PDF) è un'attività comune. Questa conversione garantisce che il layout del documento rimanga coerente su diverse piattaforme. Questa guida fornisce soluzioni dettagliate per una conversione efficiente da RTF a PDF utilizzando la nostra libreria per sviluppatori PDF. in Delphi, C# e VB.Net. Seguendo questa guida, è possibile convertire senza problemi i file RTF in documenti PDF mantenendo un'alta fedeltà al contenuto originale. Seguiamo passo dopo passo il processo.
Descrizione del problema.
La sfida principale è convertire un file RTF in un file PDF garantendo che la formattazione e il layout del documento originale siano preservati. Ciò comporta:
- Caricamento del file RTF.
- Configurazione di un contesto dispositivo virtuale per il rendering.
- Stampa il contenuto RTF nel contesto del dispositivo virtuale.
- Salva il contenuto renderizzato come file PDF.
Passaggi per raggiungere l'obiettivo.
- Inizializza l'ambiente.
- Carica la libreria PDF losLab.
- Carica il file RTF in un controllo di testo ricco.
- Configura il contesto del dispositivo.
- Crea un contesto del dispositivo virtuale che simula le dimensioni di una pagina A4.
- Calcola la scala necessaria per adattare il contenuto all'interno della pagina PDF.
- Elabora il contenuto RTF:
- Utilizza il contesto del dispositivo virtuale per formattare e stampare il contenuto RTF.
- Cattura il contenuto stampato e crea una nuova pagina PDF da esso.
- Salva il documento PDF:
- Salva le pagine PDF generate su disco.
- Gestisci più pagine iterando attraverso il contenuto RTF e creando nuovi documenti PDF, se necessario.
Esempio di codice Delphi.
Di seguito è riportata un'implementazione in Delphi che dimostra la conversione di un file RTF in un file PDF utilizzando la nostra libreria PDF.
Il seguente esempio utilizza la versione DLL della libreria di sviluppo PDF (è disponibile anche una versione in codice sorgente Pascal per Delphi).
|
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 |
unit MainUnit; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, PDFlibAX_TLB, ActiveX; type TForm1 = class(TForm) RichEdit1: TRichEdit; Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private function PrintRtfBox(hDc: HDC; rtfBox: TRichEdit; FirstChar: Integer): Integer; public end; var Form1: TForm1; PdfDoc: TPDFLibrary; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin PdfDoc := TPDFLibrary.Create(Self); RichEdit1.Width := Round(ScaleX(210, mmPixel)); RichEdit1.Height := Round(ScaleY(297, mmPixel)); RichEdit1.Lines.LoadFromFile(ExtractFilePath(Application.ExeName) + 'Test.rtf'); end; procedure TForm1.Button1Click(Sender: TObject); var Dc: HDC; PageNumber, LastChar, PdfDocId: Integer; begin PageNumber := 1; LastChar := 0; repeat Dc := PdfDoc.GetCanvasDC(Round(ScaleX(210, mmPixel)), Round(ScaleY(297, mmPixel))); LastChar := PrintRtfBox(Dc, RichEdit1, LastChar); PdfDoc.LoadFromCanvasDc(96, 0); PdfDocId := PdfDoc.SelectedPdfDocument; PdfDoc.SaveToFile(ExtractFilePath(Application.ExeName) + 'Test' + IntToStr(PageNumber) + '.pdf'); PdfDoc.RemovePdfDocument(PdfDocId); Inc(PageNumber); until LastChar = 0; ShowMessage('Done'); end; function TForm1.PrintRtfBox(hDc: HDC; rtfBox: TRichEdit; FirstChar: Integer): Integer; var RcDrawTo, RcPage: TRect; Fr: TFormatRange; NextCharPosition: Integer; begin RcPage.Left := 0; RcPage.Right := rtfBox.Left + rtfBox.Width + 100; RcPage.Top := 0; RcPage.Bottom := rtfBox.Top + rtfBox.Height + 100; RcDrawTo.Left := rtfBox.Left; RcDrawTo.Top := rtfBox.Top; RcDrawTo.Right := rtfBox.Left + rtfBox.Width; RcDrawTo.Bottom := rtfBox.Top + rtfBox.Height; Fr.hdc := hDc; Fr.hdcTarget := hDc; Fr.rc := RcDrawTo; Fr.rcPage := RcPage; Fr.chrg.cpMin := FirstChar; Fr.chrg.cpMax := -1; NextCharPosition := SendMessage(rtfBox.Handle, EM_FORMATRANGE, 1, LPARAM(@Fr)); if NextCharPosition < Length(rtfBox.Text) then Result := NextCharPosition else Result := 0; end; end. |
Esempio di codice C#.
Di seguito è riportata un'implementazione in C# che realizza la stessa funzionalità dell'esempio Delphi.
|
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 111 112 113 114 115 116 117 118 119 120 121 122 |
using System; using System.Runtime.InteropServices; using System.Windows.Forms; using PDFLibrary; namespace RtfToPdf { public partial class Form1 : Form { private PDFLibrary PdfDoc; [StructLayout(LayoutKind.Sequential)] private struct RECT { public int Left; public int Top; public int Right; public int Bottom; } [StructLayout(LayoutKind.Sequential)] private struct CharRange { public int cpMin; public int cpMax; } [StructLayout(LayoutKind.Sequential)] private struct FormatRange { public IntPtr hDc; public IntPtr hdcTarget; public RECT rc; public RECT RcPage; public CharRange chrg; } private const int WM_USER = 0x400; private const int EM_FORMATRANGE = WM_USER + 57; [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, ref FormatRange lParam); public Form1() { InitializeComponent(); PdfDoc = new PDFLibrary(); } private void Form1_Load(object sender, EventArgs e) { richTextBox1.SetBounds(0, 0, Convert.ToInt32(ScaleX(210, GraphicsUnit.Millimeter, GraphicsUnit.Pixel)), Convert.ToInt32(ScaleY(297, GraphicsUnit.Millimeter, GraphicsUnit.Pixel))); richTextBox1.LoadFile(Application.StartupPath + "\\Test.rtf"); } private void button1_Click(object sender, EventArgs e) { IntPtr Dc; int PageNumber = 1; int LastChar = 0; int PdfDocId; do { Dc = PdfDoc.GetCanvasDC(Convert.ToInt32(ScaleX(210, GraphicsUnit.Millimeter, GraphicsUnit.Pixel)), Convert.ToInt32(ScaleY(297, GraphicsUnit.Millimeter, GraphicsUnit.Pixel))); LastChar = PrintRtfBox(Dc, richTextBox1, LastChar); PdfDoc.LoadFromCanvasDc(96, 0); PdfDocId = PdfDoc.SelectedPdfDocument; PdfDoc.SaveToFile(Application.StartupPath + "\\Test" + PageNumber + ".pdf"); PdfDoc.RemovePdfDocument(PdfDocId); PageNumber++; } while (LastChar != 0); MessageBox.Show("Done"); } private int PrintRtfBox(IntPtr hDc, RichTextBox rtfBox, int FirstChar) { RECT RcDrawTo = new RECT(); RECT RcPage = new RECT(); FormatRange Fr = new FormatRange(); RcPage.Left = 0; RcPage.Right = rtfBox.Left + rtfBox.Width + 100; RcPage.Top = 0; RcPage.Bottom = rtfBox.Top + rtfBox.Height + 100; RcDrawTo.Left = rtfBox.Left; RcDrawTo.Top = rtfBox.Top; RcDrawTo.Right = rtfBox.Left + rtfBox.Width; RcDrawTo.Bottom = rtfBox.Top + rtfBox.Height; Fr.hDc = hDc; Fr.hdcTarget = hDc; Fr.rc = RcDrawTo; Fr.RcPage = RcPage; Fr.chrg.cpMin = FirstChar; Fr.chrg.cpMax = -1; IntPtr wParam = new IntPtr(1); IntPtr NextCharPosition = SendMessage(rtfBox.Handle, EM_FORMATRANGE, wParam, ref Fr); if (NextCharPosition.ToInt32() < rtfBox.Text.Length) return NextCharPosition.ToInt32(); else return 0; } private float ScaleX(float value, GraphicsUnit fromUnit, GraphicsUnit toUnit) { using (Graphics g = this.CreateGraphics()) { return value * g.DpiX / 96.0f; } } private float ScaleY(float value, GraphicsUnit fromUnit, GraphicsUnit toUnit) { using (Graphics g = this.CreateGraphics()) { return value * g.DpiY / 96.0f; } } } } |
Spiegazione e giustificazione.
- Inizializzazione: Sia la versione Delphi che la versione C# inizializzano la losLab PDF Library. versione DLL. Il file RTF viene caricato in un controllo di testo ricco (RichEdit in Delphi e RichTextBox in C#).
- Configurazione del contesto del dispositivo: Il contesto del dispositivo è configurato per simulare una dimensione di pagina A4, garantendo che il contenuto si adatti correttamente durante la visualizzazione.
- Elaborazione del contenuto: Il
PrintRtfBoxLa funzione (o metodo) formatta il contenuto RTF e lo stampa nel contesto del dispositivo. Questo metodo calcola le dimensioni necessarie e chiama l'API Windows appropriata per gestire la formattazione del testo. - Generazione di PDF: Il ciclo in entrambi gli esempi elabora il contenuto RTF pagina per pagina, creando nuovi documenti PDF se necessario. Ogni pagina viene salvata su disco e quindi rimossa dalla memoria per gestire le risorse in modo efficiente.
- Notifica di completamento: Dopo aver elaborato tutte le pagine, una finestra di messaggio informa l'utente che la conversione è completa.
Seguendo questi passaggi, garantiamo una trasformazione affidabile e precisa dei file RTF in documenti PDF, sfruttando le funzionalità della libreria losLab PDF. Questo approccio garantisce che la formattazione e il layout originali siano preservati, ottenendo risultati PDF di qualità professionale.
Esempio di conversione da RTF a PDF in VisualBasic.Net.
Inoltre, forniamo anche un'implementazione in VB.Net, che ha la stessa funzionalità degli esempi in Delphi e C#:
|
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 |
Imports System.Runtime.InteropServices Imports PDFlibDLL Public Class Form1 Private PdfDoc As PDFlibrary <StructLayout(LayoutKind.Sequential)> Private Structure RECT Public Left As Integer Public Top As Integer Public Right As Integer Public Bottom As Integer End Structure <StructLayout(LayoutKind.Sequential)> Private Structure CharRange Public cpMin As Integer Public cpMax As Integer End Structure <StructLayout(LayoutKind.Sequential)> Private Structure FormatRange Public hDc As IntPtr Public hdcTarget As IntPtr Public rc As RECT Public rcPage As RECT Public chrg As CharRange End Structure Private Const WM_USER As Integer = &H400 Private Const EM_FORMATRANGE As Integer = WM_USER + 57 <DllImport("user32.dll", CharSet:=CharSet.Auto)> Private Shared Function SendMessage(hWnd As IntPtr, wMsg As Integer, wParam As IntPtr, ByRef lParam As FormatRange) As IntPtr End Function Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load PdfDoc = New PDFlibrary() RichTextBox1.SetBounds(0, 0, Convert.ToInt32(ScaleX(210, GraphicsUnit.Millimeter, GraphicsUnit.Pixel)), Convert.ToInt32(ScaleY(297, GraphicsUnit.Millimeter, GraphicsUnit.Pixel))) RichTextBox1.LoadFile(Application.StartupPath & "\Test.rtf") End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim Dc As IntPtr Dim PageNumber As Integer = 1 Dim LastChar As Integer = 0 Dim PdfDocId As Integer Do Dc = PdfDoc.GetCanvasDC(Convert.ToInt32(ScaleX(210, GraphicsUnit.Millimeter, GraphicsUnit.Pixel)), Convert.ToInt32(ScaleY(297, GraphicsUnit.Millimeter, GraphicsUnit.Pixel))) LastChar = PrintRtfBox(Dc, RichTextBox1, LastChar) PdfDoc.LoadFromCanvasDc(96, 0) PdfDocId = PdfDoc.SelectedPdfDocument PdfDoc.SaveToFile(Application.StartupPath & "\Test" & PageNumber & ".pdf") PdfDoc.RemovePdfDocument(PdfDocId) PageNumber += 1 Loop While LastChar <> 0 MessageBox.Show("Done") End Sub Private Function PrintRtfBox(hDc As IntPtr, rtfBox As RichTextBox, FirstChar As Integer) As Integer Dim RcDrawTo As New RECT() Dim RcPage As New RECT() Dim Fr As New FormatRange() RcPage.Left = 0 RcPage.Right = rtfBox.Left + rtfBox.Width + 100 RcPage.Top = 0 RcPage.Bottom = rtfBox.Top + rtfBox.Height + 100 RcDrawTo.Left = rtfBox.Left RcDrawTo.Top = rtfBox.Top RcDrawTo.Right = rtfBox.Left + rtfBox.Width RcDrawTo.Bottom = rtfBox.Top + rtfBox.Height Fr.hDc = hDc Fr.hdcTarget = hDc Fr.rc = RcDrawTo Fr.rcPage = RcPage Fr.chrg.cpMin = FirstChar Fr.chrg.cpMax = -1 Dim wParam As IntPtr = New IntPtr(1) Dim NextCharPosition As IntPtr = SendMessage(rtfBox.Handle, EM_FORMATRANGE, wParam, Fr) If NextCharPosition.ToInt32() < rtfBox.Text.Length Then Return NextCharPosition.ToInt32() Else Return 0 End If End Function Private Function ScaleX(value As Single, fromUnit As GraphicsUnit, toUnit As GraphicsUnit) As Single Using g As Graphics = Me.CreateGraphics() Return value * g.DpiX / 96.0F End Using End Function Private Function ScaleY(value As Single, fromUnit As GraphicsUnit, toUnit As GraphicsUnit) As Single Using g As Graphics = Me.CreateGraphics() Return value * g.DpiY / 96.0F End Using End Function End Class |