Контакти

Нарис з приводу створення PDF-файлів. Додаємо в програму перегляд PDF за допомогою ActiveX Delphi відкрити pdf файл

У цій статті, розглянемо, як створювати свої pdf-документи, а в наступній статті розглянемо, як можна переглядати pdf-документи в своїх проектах, а також друкувати вміст, переміщатися по документу і так далі.

Для цього нам знадобляться компоненти з вкладки Rave. Давайте ж встановимо, необхідні нам, для роботи компоненти, а це:

  • TRvNDRWriter
  • TRvRenderPdf
  • TButton

компонент TRvNDRWriter призначений для запису в pdf-файл інформацію (текстову, графічну), через потік.

компонент TRvRenderPdfпризначений для створення, відтворення інформації (текстової, графічної і так далі). Ну і після натискання на кнопку, ми будемо щось заносити в наш pdf-файл.

З теорії багато писати нічого не будемо, а відразу перейдемо до програмування, але необхідно ще спершу створити звичайний порожній pdf-файл і покласти його в корінь з програмою. Далі на подію OnClickнашій кнопки ми напишемо наступний код:

procedure TForm1. Button1Click (Sender: TObject); var Streams: TMemoryStream; begin Streams: \u003d TMemoryStream. create; RvNDrWriter1. Stream: \u003d Streams; RvNDRWriter1. Execute; RvRenderPdf1. PrintRender (Streams, "test.pdf"); ShellExecute (Handle, nil, "test.pdf", "", "", SW_SHOW); FreeAndNil (Streams); end;

Створюємо потік, в якому і будемо отрісовивовать всю інформацію, потім запускаємо отрисовку, вказуємо файл, в який буде проводитися отрисовка даних і в кінці знищуємо потік.

Все тепер, нам необхідно подія, яке виникає при відображенні даних, в ньому ми і будемо виводити всю нашу інформацію. виділяємо компонент TRvNDRWriterі переходимо список подій даного компонента, після чого, знаходимо подія OnPrintі в даній подія пишемо наступний код:

procedure TForm1. Print (Sender: TObject); begin bmp: \u003d TBitmap. Create; bmp. LoadFromFile ( "test.bmp"); with RvNDRWriter1 do begin SetFont ( "Arial", 16); FontColor: \u003d clGreen; Print ( "Test Text"); PrintHeader ( "Begin PDF File", pjCenter); PrintFooter ( "End PDF File", pjCenter); LineTo (10, 10); PrintBitmap (1, 1, 1, 1, bmp); end; FreeAndNil (bmp); end;

Ну, спершу, ми завантажуємо картинку * .bmp, Природно змінна bmp, У нас об'єкт класу TBitmap. Завантажуємо ми для того, щоб потім її отрисовать в нашому pdf-Документи.

А далі, я думаю все зрозуміло, процедура PrintHeader- виводить напис в заголовок документа (сторінки), процедура PrintFooter- виводить напис в кінець документа (сторінки). процедура PrintBitmap- виводить зображення в документ, процедура SetFont- встановлює шрифт документа, процедура FontColor- встановлює колір шрифту документа.

Для цього прикладу нам будуть необхідні наступні компоненти, які знаходяться у вкладці Rave. І так, приступимо до встановлення потрібних нам компонентів, а саме:

  • TRvNDRWriter
  • TRvRenderPdf
  • TButton

Пропоную трохи зупинитися на цих компонентах і зрозуміти для чого вони служать. До речі про них я вичіл інформацію з пару книг які придбав progbook.ru. Тому якщо хочете придбати гідні книги по Delphi, то ласкаво прошу в даний магазин.

Отже, першим у нас йде компонент TRvNDRWriter. Цей компонент необхідний нам для запису в pdf-файл інформації, байдуже якої, текстової або графічної, через потік.

Procedure TForm1.Button1Click (Sender: TObject); var Streams: TMemoryStream; begin Streams: \u003d TMemoryStream.create; RvNDrWriter1.Stream:\u003dStreams; RvNDRWriter1.Execute; RvRenderPdf1.PrintRender (Streams, "test.pdf"); ShellExecute (Handle, nil, "test.pdf", "", "", SW_SHOW); FreeAndNil (Streams); end;

Наступний компонент це TRvRenderPdf. Він необхідний нам для створення, а точніше для відтворення інформації, будь то текстова або графічна. Відповідно після натискання кнопки, ми запишемо потрібну нам інформацію в наш pdf-файл.

Але не будемо сильно просторікувати, а перейдемо відразу до цікавить нас темі, а саме до програмування :)

Для початку нам необхідно створити звичайний порожній pdf-файл і розмістити його в кореневій папці нашої програми.

Власне цим кодом ми створюємо потік, де будемо отрісовивовать потрібну нам інформацію, після чого запускаємо отрисовку, вказуємо наш кінцевий pdf-файл, в який буде проводитися отрисовка даних і в кінці закриття гілки.

Після виконання даного коли, нам необхідно подія, яке виникає при промальовуванні даних, в цій події ми будемо виводити потрібну нам інформацію.

Розберемо код. Для початку я завантажую картинку * .bmp, створюємо змінну bmp, і об'єкт класу TBitmap. Завантажую я її для того, щоб потім малювати в нашому pdf-файлі.

Я думаю далі особливо описувати не варто все зрозуміло і так, процедура PrintHeader - додає напис в заголовок документа, процедура PrintFooter - додає напис в кінець документа. Процедура PrintBitmap - додає зображення в документ, процедура SetFont - задає необхідний шрифт документа, процедура FontColor - задає потрібний колір шрифту документа.

Усі наступні графічні функції і процедури, точно такі ж, як і при виведенні графічної інформації на Canvas інших компонентів.

Функцію NewPage я використовую для створення нового листа в документі. Все що буде додано після неї на висновок інформації, буде виводитися на новому аркуші документа.

важливо, Що б все модулі: RpRender, RpRenderPDF, RpDefine, RpBase, RpFiler, RpRave, RpCon були підключені до проекту!

Можливості компонента, заявлені розробниками:

  • Підтримка векторної і растрової графіки в PDF-документах
  • Захист PDF-документів паролем
  • Підтримки AcroForms / PDF-форм
  • Водяні знаки
  • Генерація PDF документів з внутрішніми і зовнішніми посиланнями, веб-посиланнями і закладками
  • Повна підтримка Unicode
  • Підтримка різних шрифтів, форматування тексту, розташування тексту в декілька стовпців
  • підтримка TCanvas
  • Вбудований архіватор для стиснення текстової та графічної інформації в документі
  • Перетворення TIFF в PDF

Як приклад, я вирішив зібрати демонстраційний додаток, що йде в комплекті разом з компонентом THotPDF. Додаток досить простеньке - генерує PDF-ку з двома посиланнями і простим текстом. Код теж простий і зрозумілий:

procedure TForm1. HelloWorldButtonClick (Sender: TObject); begin HPDF. BeginDoc; HPDF. CurrentPage. PrintHyperlink (20, 35, "Website:" + MainEdit. Text, MainEdit. Text); HPDF. CurrentPage. SetFont ( "Times New Roman",, 16); HPDF. CurrentPage. SetRGBHyperlinkColor (clRed); HPDF. CurrentPage. PrintHyperlink (20, 50, "Order page:" + BuyEdit. Text, BuyEdit. Text); HPDF. CurrentPage. SetFont ( "Times New Roman",, 14); HPDF. CurrentPage. TextOut (20, 75, 0, "Click the link to navigate"); HPDF. EndDoc; end;

Навіть не вдаючись у тонкощі роботи компонента можна зрозуміти, що і як відбувається в цьому демонстраційному прикладі. Запускаємо, дивимося на зовнішній вигляд згенерованого документа:

Ось ці два синіх прямокутника в документі - посилання на дві сторінок ... а простого тексту «Click the link to navigate» взагалі не спостерігається ніде. Хоча, треба віддати належне, при кліці по прямокутнику посилання дійсно відкривається. Загалом, чи то розробники поквапилися заявити підтримку Delphi аж до XE3, то це так цікаво працює trial-версія, але після запуску цього демонстраційного прикладу у мене якось відпало бажання використовувати THotPDF навіть за безкоштовно. Рухаємося далі.

4. PDF Creator Pilot

вартість: від 450 $ без початкових кодів до 9950 $ (!!!) з кодами
5-XE4
http://www.colorpilot.com/pdflibrary.html#download

Бібліотека вартістю майже як Delphi XE3 Professional ... Ну да ладно, подивимося, що являє собою ця бібліотечка.

Можливості, заявлені розробниками:

  • Розширений набір методів і властивостей для легкого створення PDF;
  • Читання і злиття існуючих PDF-документів;
  • Додавання і видалення сторінок PDF-документа;
  • Підтримка Unicode;
  • Створення водяних знаків для кожної сторінки;
  • Додавання ескізів для PDF-документа;
  • Використання і вбудовування шрифтів (TrueType, OpenType, Type1 і т.д.);
  • Створення інтерактивних PDF-документів, використовуючи JavaScript і гіперпосилання;
  • Підтримка інтерактивних елементів AcroForm: текстові поля введення, кнопки, радіо-кнопки, що випадають списки, прапорці;
  • шифрування і захист паролем створених PDF-документів;
  • Створення і управління змістом документа;
  • Доступ до HDC для малювання на PDF-сторінках за допомогою WinAPI функцій.
  • Використання зображень в різних форматах (JPEG, TIFF, PNG, BMP, GIF);
  • Створення і використання анотацій;
  • Створення PDF-документів на диску або в пам'яті;
  • Вилучення тексту з PDF документів;

Загалом, досить значний список можливостей. Подивимося як деякі з цих можливостей працюють на практиці. Викачуємо демонстраційну версію, встановлюємо.

Після установки запускаємо Delphi (в моєму випадку - це Delphi XE3) і переходимо в меню:

Component - Import Component - Import Type Library

У списку шукаємо бібліотеку

Імпортуємо, створюємо новий проект і підключаємо в uses модуль PDFCreatorPilotLib_TLB.

Тепер можемо протестувати роботу бібліотеки на якомусь живому прикладі. Спочатку спробуємо згенерувати документ з простим текстом:

procedure TForm1. Button1Click (Sender: TObject); var fnt: integer; begin (initialization) PDF: \u003d TPDFDocument4. Create (nil); PDF. SetLicenseData ( "demo", "demo"); fnt: \u003d pdf. AddFont ( "Verdana", false, false, false, false, fcANSI); PDF. UseFont (fnt, 14); PDF. ShowTextAt (20, 40, "HELLO, PDF!"); (Save) PDF. SaveToFile ( "HelloPDF.pdf", true); PDF. Destroy; end;

Запускаємо програму і дивимося на створений PDF-документ:

Тепер спробуємо записати російський текст в файл:

procedure TForm1. Button1Click (Sender: TObject); begin (initialization) (...) PDF. ShowTextAt (20, 40, "Привіт, PDF!"); (Save) (...) end;


Може десь у властивостях класу треба щось налаштувати, викликати який-небудь метод, який включить-таки підтримку юникода, АЛЕ за такі бабки хотілося б отримати бібліотеку, яка запрацює відразу «з коробки» без всяких проблем з настройками і підкруткою ... До речі, метод для вставки посилання (AddHyperLink) теж не спрацював - документ залишився невинно чистий незважаючи на те, що посилання нібито вставила. Але, треба віддати належне, спроба вставити в новий документ вже раніше створену PDF-ку - спрацював на ура - документ вставився на нову сторінку як треба, без косяків.

5. PDFtoolkit VCL v4.0.1.293

вартість: від 349 $ без початкових кодів до 499 $ з кодами
Підтримувані версії Delphi: 6-XE4
Сторінка завантаження trial-версії: http://www.gnostice.com/PDFtoolkit_VCL.asp?show\u003ddownloads

Про цю бібліотеку компонентів від Gnostice є досить багато позитивних відгуків в Мережі.

по можливостях PDFtoolkitпрактично 1 в 1 відповідає PDF Creator Pilot, тобто вміє «склеювати» PDF-ки, розпізнавати текст, вставляти посилання, проводити пошук в документах і т.д. Але, на відміну від PDF Creator Pilot, PDFtoolkit if gtPDFDocument1. IsLoaded then begin gtPDFDocument1. TextOut ( "Привіт, Світ!" , IntToStr (gtPDFDocument1. PageCount), // діапазон сторінок в який буде вставлений текст gtPDFDocument1. GetPageSize (gtPDFDocument1. PageCount, muPixels). Width / 2, // вставляємо текст в центр сторінки gtPDFDocument1. GetPagesize (gtPDFDocument1. PageCount, muPixels). Height / 2); (Зберігаємо документ) gtPDFDocument1. SaveToFile ( "modified_doc.pdf"); end; finally gtPDFDocument1. Free end;

Звичайно, стосовно моєї задачі PDFtoolkit виявляється практично марним, тому що мене цікавить саме створення з нуля PDF-ки, але для тих, хто пише власний переглядач PDF-ок, думаю, ця бібліотека повинна підійти більш ніж.

Отже, що маємо в підсумку. Є 5 різних рішень для створення і роботи з PDF-документами в Delphi. Кожне рішення має як свої переваги (безкоштовність, «навороченность»), так і недоліки (кінська вартість, проблеми з юнікодом і т.д.). Стосовно до моєї задачі треба усіма рішеннями доведеться «працювати напилком». З іншого боку, в Мережі є купа платних і безкоштовних сервісів для генерації PDF, але, пам'ятаючи про те, що такі сервіси мають властивість раптом брати і вмирати, то якось не тягне з ними зв'язуватися. Є, звичайно, ще одне рішення - самопісний і не зовсім в тему Delphi, але про це якось наступного разу, а поки піду подумаю що ж робити з клієнтом для DelphiFeeds


До зустрічі в онлайні!


дата публікації 23-09-2005 7:00 Нарис з приводу створення PDF-файлів

Останнім часом на просторах інтернету виявилося дуже багато PDF converter "ов, reader" ов і write "ов. І переважна більшість з них пропонується за гроші. Сама програма від 10 $ до 300 $. А вже вихідний код за набагато більші гроші ціна починається від 200 $ а в одному місці (зацікавившись цим полазив по інету) аж за 900 євро.

Дана проблемма мене зацікавила в плані програмування і ось результати доводжу до вашого відома. (Дані результати отримані мною при вивченні нутрощів PDF файлу, коли відкриваєш його в total commander через F3)

Звичайний PDF файл складається з чотирьох частин :=

Що таке таке

? Це звичайне згадка про версію PDF specification. Яке присутнє в першому рядку PDF файлу. Наприклад "% PDF-1.3" У сьомій версії акробата яка вийшла де то на початку літа цього року, цей номер "% PDF-1.7", але це не версія продукту, це версія саме специфікації. Другий рядок PDF йде невелика аброкадабра (мабуть призначена для подальшого використання) "% ВДПУ"

Всі з першою частиною PDF розібралися.

Що з себе являє друга частина яка називається ?

Відповідь дуже проста: це послідовність об'єктів, опис яких як і хедера представлені в текстовому вигляді.

Кожен об'єкт це текстовий фрагмент з порядковим номером в імені наприклад "4 0 obj"

  • 4 це порядковий номер об'єкта
  • 0 це номер (ре) створення файлу тобто коли файл оновлюється (редагується) то цей номер збільшується
  • obj це кодове слово означає що в тілі документа нам зустрівся об'єкт

Всі об'єкти діляться на непрямі і прямі. Всі непрямі, і їх більшість, після слова obj мають в своєму тілі деліметер "<<", означающее начало данных объекта. И в конце данных закрывающий делиметер ">\u003e "І кодове слово endobj

Прямі об'єкти не повинні мати в своєму тілі які відкривають і закривають деліметеров "<<", ">\u003e "Всі непрямі об'єкти доступні через cross-reference table. У ній представлені посилання у вигляді зміщення від початку файлу до початку об'єкта (Дані (рядки) в об'єкті розділяються #13#10 або #13 )

Тип "найголовнішого" об'єкта в тілі PDF файлу носить горде ім'я "/ Catalog"

4 0 obj<< /Type /Catalog /Pages 2 0 R /OpenAction [ 5 0 R /XYZ null 364 1 ] /PageMode /UseNone >\u003e endobj

Насправді в тілі мінімального PDF файлу типу "Hello world" повинне бути 3 "головних" об'єкта. Давайте я їх перерахую за типами:

  • "/ Catalog" містить в собі посилання: на дерево сторінок ( / Pages)
  • "/ Pages"містить в собі посилання на групу сторінок документа (Наприклад 2 0 obj\u003e endobj)
  • "/ Page" містить в собі посилання на об'єкти відносяться до конкретної сторінці. (Наприклад 3 0 obj\u003e / Rotate 0 \u003e\u003e)
І кілька "другорядних"

Розберемо об'єкт сторінка:

  • / Rotate поле показує на скільки градусів зображення сторінки повинно бути повернуто при відображення в програмі
  • / MediaBoxі / CropBox поля описують розмір сторінки
  • / Parent посилання на батьківський об'єкт "/ Pages"
  • / Resources це поле описує який фонт повинен бути використаний при відображенні сторінки (фонт це окремий об'єкт) і установку ProcSet ця установка показує яке вміст потоку даних даної сторінки (теж може бути визначений як об'єкт, а не як поле)
  • / Contents Найцікавіше поле в об'єкті "сторінка", дає посилання на об'єкт вмісту даної сторінки, причому: якщо це поле відсутнє в об'єкті "сторінка" означає сторінка порожня
Вміст сторінки:
об'єкт "Stream" 4 0 obj\u003e stream BT / F12 9 Tf 10 782 TD 0 -12.5 TD (Max Fokin) Tj 0 -12.5 TD (mnb) Tj 0 -12.5 TD () Tj 0 -12.5 TD (Max Privet) Tj 0 -12.5 TD (1) Tj 0 -12.5 TD (1) Tj 0 -12.5 TD (2) Tj 0 -12.5 TD (3) Tj 0 -12.5 TD (45) Tj ET endstream endobj / Length 305 це поле показиввающее скільки байт від слова stream до слова endstream

Найпростіший варіант - це некодований і нестислий потік даних в об'єкті stream. Він обмежується операторами BT і ET

BT Begins a Text Object - характеризує початок тексту ET Ends a Text Object. - характеризує кінець тексту / F12 9 Tf

  • / F12 це кодове ім'я об'єкта який характеризує фонт що використовується на даній сторінці
  • 9 це розмір фонта
  • Tf це оператор який характеризує що даний рядок в об'єкті steam є установка фонт та розміру
10 782 TD це цифри звідки починається даний рядок (відлік здійснюватися від лівого верхнього кута) Tj це оператор перекладу на новий рядок Ну а в круглих дужках наш текст

Кодований потік я сдесь не пояснюю тут. Він заснований на алгоритмах RC4, RC5, MD5.

Що таке об'єкт Font 12 0 obj\u003e

  • / Type / Font Природно назва типу
  • / Subtype / Type1 назва підтипу
  • / Name / F7 F7 це кодове ім'я

PDF підтримує кілька видів фонтів. Вони перераховані нижче

  • Type 1, including subsets and Multiple Master "snapshots"
  • Type 3
  • TrueType, including subsets
  • Type 0
Чесно кажучи, я не розбирався з Type 3, TrueType, including subsets, Type 0 нічого по ним сказати не можу
А Type 1 - це такі фонти Courier Courier-Bold Courier-BoldOblique Courier-Oblique Helvetica Helvetica-Bold Helvetica-BoldOblique Helvetica-Oblique Times-Roman Times-Bold Times-Italic Times-BoldItalic Symbol ZapfDingbats

20 0 obj\u003e endobj Це об'єкт з назвами кодових імен для фонтів першого типу. З цього кодовому імені можна легко отримати сам об'єкт фонт. 6 0 obj\u003e

ВСЕ: тобто мінімальний Складається з наступних об'єктів: "Catalog", "pages", "page", "Resources" (Опіціонально може бути присутнім, як поле в об'єкті сторінка), нетипізований об'єкт "Stream", Група об'єктів "Font"

Що таке ? Насправді це звичайна текстова таблиця, вона починається зі слова xref і своє тіло має посилання на всі непрямі об'єкти в документі. Ось приклад xref 0 27 0000000021 65535 f 0000000016 00000 n 0000000105 00000 n 0000000169 00000 n 0000000356 00000 n 0000000713 00000 n 0000000892 00000 n 0000001006 00000 n 0000001125 00000 n 0000001247 00000 n 0000001373 00000 n 0000001486 00000 n 0000001604 00000 n 0000001725 00000 n 0000001850 00000 n 0000001967 00000 n 0000002084 00000 n 0000002203 00000 n 0000002326 00000 n 0000002439 00000 n 0000002558 00000 n 0000000024 00001 f 0000002751 00000 n 0000002831 00000 n 0000000000 00001 f 0000002915 00000 n 0000002955 00000 n 0 27 Ці цифри позначають наступне:

  • 0 - перший object number в таблиці
  • 27 - кількість елементів таблиці

Перший елемент таблиці завжди иммет вид " XXXXXXXXXX 65535 f"Де X це цифра, а 65535 це значення за замовчуванням для першого елемента в таблиці. Символ" f "позначає" free", Тобто об'єкт не використовується

Розберемо елемент цієї таблиці.

  • Перші 10 цифр - це зсув від початку файлу до початку об'єкта.
  • 0000000016 означає що через 16 байт від початку файлу Вас зустріне перша згадка про об'єкт тобто, наприклад, 4 0 obj

Другі п'ять цифр - це номер створення файлу. Якщо файл щойно створений, то вони завжди нулі. Якщо файл модифікується, то це число збільшується на одиницю. Тобто, 0000000024 00001 f

Канонічний, тільки що створений PDF файл, має тільки одну таблицю. Але, якщо файл редагується, то таких таблиць може бути дуже багато.

Взаємозв'язок таблиць здійснюється за допомогою останнього елемента і кодового слова startxref

Канонічний, тільки що створений PDF файл, має тільки одну таблицю, після таблиці йде елемент trailer А після трайлер йде кодове слово startxref, Яке вказує на зсув від початку файлу до початку таблиці, ось приклад. trailer\u003e startxref 173 %% EOF Це означає, що через 173 байти від початку документа, буде присутній кодове слово xref. Але, якщо файл був відредагований, то останній у файлі трайлер матиме вигляд: xref 0 3 0000000000 65535 f 0000003609 00000 n 0000003832 00000 n trailer<7a15ab3ed3999575ff2f3034104a82c1>] \u003e\u003e startxref 173 %% EOF Але, якщо ми звернемося до таблиці, куди вказує посилання startxref 173, То ми знайдемо наступну таблицю, а за нею трайлер, який буде мати поле / Prev 3896 3 16 0000000016 00000 n 0000000664 00000 n 0000000936 00000 n 0000001106 00000 n 0000001133 00000 n 0000001250 00000 n 0000001395 00000 n 0000001811 00000 n 0000001992 00000 n 0000002180 00000 n 0000002360 00000 n 0000002760 00000 n 0000003438 00000 n 0000003516 00000 n 0000000776 00000 n 0000000916 00000 n trailer<7a15ab3ed3999575ff2f3034104a82c1>] \u003e\u003e startxref 567 %% EOF

дане поле / Prev 3896 вказує нам на попередню таблицю, а посилання startxref 567 вказує на наступну таблицю і так практично до нескінченності, поки в черговому полі startxref ми не побачимо 0 . Це означає, ми прочитали всі таблиці.

В даному нарисі, звичайно, не вистачає вихідного коду. Ось і він: представлені два модуля основний " PDFDocument"І допоміжний" PDFBaseFonts"

До матеріалу додаються файли:

  • Вихідний код модулів PDFDocument.pas і PDFBaseFonts.pas (16 K) оновлення від 9/23/2005 7:02:00 AM

Обговорення матеріалу [31-07-2006 6:33] 7 повідомлень



Сподобалася стаття? поділіться їй