Convertendo arquivos RTF em PDF: Um guia para desenvolvedores Delphi, C# e VB.Net.
No mundo do processamento de documentos, converter arquivos Rich Text Format (RTF) para Portable Document Format (PDF) é uma tarefa comum. Essa conversão garante que o layout do documento permaneça consistente em diferentes plataformas. Este guia fornece soluções detalhadas para a conversão eficiente de RTF para PDF usando nossa biblioteca de desenvolvimento PDF. em Delphi, C# e VB.Net. Seguindo este guia, você pode transformar arquivos RTF em documentos PDF, mantendo alta fidelidade ao conteúdo original. Vamos percorrer o processo passo a passo.
Declaração do problema.
O principal desafio aqui é converter um arquivo RTF em um arquivo PDF, garantindo que a formatação e o layout do documento original sejam preservados. Isso envolve:
- Carregar o arquivo RTF.
- Configurar um contexto de dispositivo virtual para renderização.
- Imprimir o conteúdo RTF no contexto do dispositivo virtual.
- Salvar o conteúdo renderizado como um arquivo PDF.
Passos para alcançar o objetivo.
- Inicializar o ambiente:
- Carregar a biblioteca PDF losLab.
- Carregar o arquivo RTF em um controle de texto rico.
- Configurar o contexto do dispositivo:
- Criar um contexto de dispositivo virtual que imita as dimensões de uma página A4.
- Calcule o dimensionamento necessário para ajustar o conteúdo dentro da página do PDF.
- Processar o conteúdo RTF:
- Utilize o contexto do dispositivo virtual para formatar e imprimir o conteúdo RTF.
- Capture o conteúdo impresso e crie uma nova página PDF a partir dele.
- Salvar o documento PDF:
- Salve as páginas PDF geradas no disco.
- Lide com várias páginas percorrendo o conteúdo RTF e criando novos documentos PDF conforme necessário.
Exemplo de código Delphi.
Abaixo está uma implementação em Delphi que demonstra a conversão de um arquivo RTF para um arquivo PDF usando nossa biblioteca PDF.
O exemplo a seguir utiliza a versão DLL da biblioteca de desenvolvimento PDF (uma versão em código fonte Pascal também está disponível 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. |
Exemplo de código C#:
Abaixo está uma implementação em C# que alcança a mesma funcionalidade do exemplo em 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; } } } } |
Explicação e justificativa:
- Inicialização: Tanto a versão Delphi quanto a versão C# inicializam a losLab PDF Library. edição DLL. O arquivo RTF é carregado em um controle de texto rico (RichEdit em Delphi e RichTextBox em C#).
- Configuração do Contexto do Dispositivo: O contexto do dispositivo é configurado para simular um tamanho de página A4, garantindo que o conteúdo se ajuste adequadamente quando renderizado.
- Processamento de Conteúdo: O
PrintRtfBoxA função (ou método) formata o conteúdo RTF e o imprime no contexto do dispositivo. Este método calcula as dimensões necessárias e chama a API Windows apropriada para lidar com a formatação do texto. - Geração de PDF: O loop em ambos os exemplos processa o conteúdo RTF página por página, criando novos documentos PDF conforme necessário. Cada página é salva em disco e, em seguida, removida da memória para gerenciar os recursos de forma eficiente.
- Notificação de Conclusão: Após processar todas as páginas, uma caixa de mensagem informa ao usuário que a conversão foi concluída.
Ao seguir estes passos, garantimos uma transformação confiável e precisa de arquivos RTF em documentos PDF, aproveitando as capacidades da biblioteca losLab PDF. Esta abordagem garante que a formatação e o layout originais sejam preservados, resultando em resultados PDF de qualidade profissional.
Exemplo de conversão de RTF para PDF em VisualBasic.Net.
Além disso, também fornecemos uma implementação em VB.Net, que possui a mesma funcionalidade dos exemplos em 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 |