RTF 파일을 PDF로 변환하는 방법: Delphi, C#, VB.Net 개발자를 위한 가이드
문서 처리의 세계에서 Rich Text Format (RTF) 파일을 Portable Document Format (PDF)로 변환하는 것은 일반적인 작업입니다. 이 변환은 문서의 레이아웃이 다양한 플랫폼에서 일관성을 유지하도록 합니다. 이 가이드는 당사의 PDF 개발 라이브러리를 사용하여 효율적인 RTF에서 PDF로의 변환을 위한 자세한 솔루션을 제공합니다. Delphi, C# 및 VB.Net에서 이 가이드를 따르면 RTF 파일을 PDF 문서로 원본 콘텐츠의 충실도를 유지하면서 원활하게 변환할 수 있습니다. 단계별로 과정을 살펴보겠습니다.
문제 정의
여기서의 주요 과제는 RTF 파일을 PDF 파일로 변환하는 동시에 원본 문서의 서식과 레이아웃이 유지되도록 하는 것입니다. 이는 다음을 포함합니다.
- RTF 파일을 로드합니다.
- 렌더링을 위한 가상 장치 컨텍스트를 설정합니다.
- RTF 콘텐츠를 가상 장치 컨텍스트에 인쇄합니다.
- 렌더링된 콘텐츠를 PDF 파일로 저장합니다.
목표 달성을 위한 단계
- 환경 초기화:
- losLab PDF 라이브러리를 로드합니다.
- RTF 파일을 리치 텍스트 컨트롤에 로드합니다.
- 장치 컨텍스트 설정:
- A4 페이지 크기에 해당하는 가상 장치 컨텍스트를 생성합니다.
- PDF 페이지 내에 콘텐츠를 맞추기 위해 필요한 스케일링을 계산합니다.
- RTF 콘텐츠 처리:
- 가상 장치 컨텍스트를 사용하여 RTF 콘텐츠를 서식 지정하고 인쇄합니다.
- 인쇄된 콘텐츠를 캡처하고 이를 사용하여 새 PDF 페이지를 만듭니다.
- PDF 문서 저장:
- 생성된 PDF 페이지를 디스크에 저장합니다.
- RTF 콘텐츠를 반복 처리하고 필요한 경우 새 PDF 문서를 생성하여 여러 페이지를 처리합니다.
Delphi 코드 예제
다음은 당사 PDF 라이브러리를 사용하여 RTF 파일을 PDF 파일로 변환하는 방법을 보여주는 Delphi 구현 예제입니다.
다음은 PDF 개발 라이브러리의 DLL 버전이며, Delphi용 Pascal 소스 코드 버전도 제공됩니다.
|
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. |
C# 코드 예제.
다음은 Delphi 예제와 동일한 기능을 수행하는 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 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; } } } } |
설명 및 근거
- 초기화: Delphi와 C# 버전 모두 다음을 초기화합니다. losLab PDF Library DLL 버전입니다. RTF 파일은 리치 텍스트 컨트롤(Delphi의 RichEdit 및 C#의 RichTextBox)에 로드됩니다.
- 장치 컨텍스트 설정: 장치 컨텍스트는 A4 페이지 크기로 설정되어 콘텐츠가 렌더링될 때 적절하게 맞도록 합니다.
- 콘텐츠 처리: The
PrintRtfBox함수(또는 메서드)는 RTF 콘텐츠를 포맷하고 장치 컨텍스트에 인쇄합니다. 이 메서드는 필요한 크기를 계산하고 텍스트 서식을 처리하기 위해 적절한 Windows API를 호출합니다. - PDF 생성: 두 예제 모두에서 루프는 RTF 콘텐츠를 페이지별로 처리하며 필요한 경우 새 PDF 문서를 생성합니다. 각 페이지는 디스크에 저장된 다음 메모리에서 제거하여 리소스를 효율적으로 관리합니다.
- 완료 알림: 모든 페이지를 처리한 후 메시지 상자가 사용자에게 변환이 완료되었음을 알립니다.
이러한 단계를 따르면 losLab PDF Library의 기능을 활용하여 RTF 파일을 PDF 문서로 안정적이고 정확하게 변환할 수 있습니다. 이 방법은 원래 서식과 레이아웃을 유지하여 전문적인 품질의 PDF 결과를 얻을 수 있도록 보장합니다.
VisualBasic.Net RTF를 PDF로 변환하는 예제
또한, Delphi 및 C# 예제와 동일한 기능을 제공하는 VB.Net 구현도 제공합니다.
|
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 |