Convertir archivos RTF a PDF: Una guía para desarrolladores de Delphi, C# y VB.Net.
En el mundo del procesamiento de documentos, convertir archivos de formato de texto enriquecido (RTF) a formato de documento portátil (PDF) es una tarea común. Esta conversión garantiza que el diseño del documento se mantenga coherente en diferentes plataformas. Esta guía proporciona soluciones detalladas para una conversión eficiente de RTF a PDF utilizando nuestra biblioteca de desarrollo de PDF. en Delphi, C# y VB.Net. Siguiendo esta guía, puede convertir archivos RTF en documentos PDF de forma fluida, manteniendo una alta fidelidad al contenido original. Vamos a recorrer el proceso paso a paso.
Declaración del problema.
El principal desafío aquí es convertir un archivo RTF en un archivo PDF, al tiempo que se garantiza que el formato y el diseño del documento original se conserven. Esto implica:
- Cargar el archivo RTF.
- Configurar un contexto de dispositivo virtual para la renderización.
- Imprimir el contenido RTF en el contexto del dispositivo virtual.
- Guardar el contenido renderizado como un archivo PDF.
Pasos para lograr el objetivo.
- Inicializar el entorno:
- Cargar la biblioteca PDF de losLab.
- Cargar el archivo RTF en un control de texto enriquecido.
- Configurar el contexto del dispositivo:
- Crear un contexto de dispositivo virtual que imite las dimensiones de una página A4.
- Calcule el escalado necesario para que el contenido quepa dentro de la página del PDF.
- Procesa el contenido RTF:
- Utiliza el contexto del dispositivo virtual para formatear e imprimir el contenido RTF.
- Captura el contenido impreso y crea una nueva página PDF a partir de él.
- Guarda el documento PDF:
- Guarda las páginas PDF generadas en el disco.
- Maneja múltiples páginas recorriendo el contenido RTF y creando nuevos documentos PDF según sea necesario.
Ejemplo de código Delphi.
A continuación, se muestra una implementación en Delphi que demuestra la conversión de un archivo RTF a un archivo PDF utilizando nuestra biblioteca PDF.
Lo siguiente utiliza la versión DLL de la biblioteca de desarrollo PDF (también está disponible una versión de código fuente en Pascal para 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. |
Ejemplo de código en C#.
A continuación, se muestra una implementación en C# que logra la misma funcionalidad que el ejemplo de 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; } } } } |
Explicación y justificación.
- Inicialización: Tanto la versión de Delphi como la versión de C# inicializan la losLab PDF Library. edición DLL. El archivo RTF se carga en un control de texto enriquecido (RichEdit en Delphi y RichTextBox en C#).
- Configuración del contexto del dispositivo: El contexto del dispositivo se configura para simular un tamaño de página A4, lo que garantiza que el contenido se ajuste correctamente al renderizarse.
- Procesamiento de contenido: El
PrintRtfBoxLa función (o método) formatea el contenido RTF e lo imprime en el contexto del dispositivo. Este método calcula las dimensiones necesarias y llama a la API de Windows adecuada para manejar el formato de texto. - Generación de PDF: El bucle en ambos ejemplos procesa el contenido RTF página por página, creando nuevos documentos PDF según sea necesario. Cada página se guarda en el disco y luego se elimina de la memoria para administrar los recursos de manera eficiente.
- Notificación de finalización: Después de procesar todas las páginas, un cuadro de mensaje informa al usuario de que la conversión se ha completado.
Siguiendo estos pasos, garantizamos una transformación confiable y precisa de archivos RTF a documentos PDF, aprovechando las capacidades de la biblioteca losLab PDF. Este enfoque asegura que el formato y la disposición originales se conserven, lo que resulta en salidas PDF de calidad profesional.
Ejemplo de conversión de RTF a PDF en VisualBasic.Net.
Además, también proporcionamos una implementación en VB.Net, que tiene la misma funcionalidad que los ejemplos de Delphi y 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 |