Секреты печати из программы на delphi


Содержание

Работа с принтером

Звонок в фирму, которая занимается ремонтом компьютеров:
— Мой принтер начал плохо печатать!
— Вероятно его надо просто почистить. Это стоит $50. Но для Вас будет лучше, если Вы прочтете инструкцию и выполните эту работу сами.
Клиент, удивленный такой откровенностью спрашивает:
— А Ваш босс знает, что Вы таким образом препятствуете бизнесу?
— На самом деле, это его идея. Мы получаем куда больше прибыли, когда позволяем нашим клиентам сначала самим попытаться что-то отремонтировать.

Delphi имеет стандартный объект для доступа к принтеру — TPRINTER, находящийся в модуле PRINTERS. В этом модуле имеется переменная Printer:Tpinter, что избавляет от необходимости описывать свою. Он позволяет выводить данные на печать и управлять процессом печати. Правда, в некоторых версиях Delphi 1 он имеет «глюк» — не работают функции Draw и StrethDraw. Но эта проблема поправима — можно использовать функции API. Далее приведены основные поля и методы объекта Printers :

  • Aborted: boolean — Показывает, что процесс печати прерван
  • Canvas: Tcanvas — Стандартный Canvas, как у любого графического объекта. Он позволяет рисовать на листе бумаге графику, выводить текст . . Тут есть несколько особенностей, они описаны после описания объекта.
  • Fonts: Tstrings — Возвращает список шрифтов, поддерживаемых принтером
  • Handle: HDS — Получить Handle на принтер для использования функций API (см. Далее)
  • Orientation: TprinterOrientation — Ориентация листа при печати : (poPortrait, poLandscape)
  • PageHeight: integer — Высота листа в пикселах
  • PageNumber: integer — Номер страницы, увеличивается на 1 при каждом NewPage
  • PageWidth: integer — Ширина листа в пикселах
  • PrinterIndex: integer — Номер используемого принтера по списку доступных принтеров Printers
  • Printers: TStrings — Список доступных принтеров
  • Printing: boolean — Флаг, показывающий, что сейчас идет процесс печати
  • Title: String — Имя документа или приложения. Под этим именем задание на печать регистрируется в диспетчере печати
  • AssignPrn(f: TextFile) — Связать текстовый файл с принтером. Далее вывод информации в этот файл приводит к ее печати. Удобно в простейших случаях.
  • Abort — Сбросить печать
  • BeginDoc — Начать печать
  • NewPage — Начать новую страницу
  • EndDoc — Завершить печать.

Особенности работы с TPrinter

  1. После команды BeginDoc шрифт у Canvas принтера сбрасывается и его необходимо задавать заново
  2. Все координаты даны в пикселах, а для нормальной работы необходимы миллиметры (по двум очевидным причинам: очень трудно произвести разметку страницы в пикселах (особенно если необходима точность), и , главное, при изменении разрешающей способности принтера будет изменяться число точек на дюйм, и все координаты «поедут».
  3. У TPrinter информация о принтере, по видимому, определяются один раз — в момент запуска программы (или смены принтера). Поэтому изменение настроек принтера в процессе работы программы может привести к некорректной работе, например, неправильной печать шрифтов True Type.

Определение параметров принтера через API

Для определения информации о принтере (плоттере, экране) необходимо знать Handle этого принтера, а его можно узнать объекта TPrinter — Printer.Handle.

Далее вызывается функция API (unit WinProcs):

Index — код параметра, который необходимо вернуть.

Для Index существует ряд констант :

  • DriverVersion — вернуть версию драйвера
  • Texnology — Технология вывода, их много, основные
  • dt_Plotter — плоттер
  • dt_RasPrinter — растровый принтер
  • dt_Display — дисплей
  • HorzSize — Горизонтальный размер листа (в мм)
  • VertSize — Вертикальный размер листа (в мм)
  • HorzRes — Горизонтальный размер листа (в пикселах)
  • VertRes — Вертикальный размер листа (в пикселах)
  • LogPixelX — Разрешение по оси Х в dpi (пиксел /дюйм)
  • LogPixelY — Разрешение по оси Y в dpi (пиксел /дюйм)

Кроме перечисленных еще около сотни, они позволяют узнать о принтере практически все. Параметры, возвращаемые по LogPixelX и LogPixelY очень важны — они позволяют произвести пересчет координат из миллиметров в пиксели для текущего разрешения принтера.

Пример таких функций:

Данную методику можно с успехом применять для печати картинок — зная размер картинки можно пересчитать ее размеры в пикселах для текущего разрешения принтера, масштабировать, и затем уже распечатать. Иначе на матричном принтере (180 dpi) картинка будет огромной, а на качественном струйнике (720 dpi) — микроскопической.

Я производил печать следующим образом:

Copyright © 2004-2020 «Delphi Sources». Delphi World FAQ

DelphiSite

Наиболее читаемое

Печать в delphi

Печать в delphi

Печать в delphi Объект printer автоматически создается в случае, если в программе указана ссылка на модуль printers. Этот объект предоставляет программисту все необходимое для того, чтобы научить приложение выводить данные на один из подключенных к компьютеру принтеров.
Вывод на принтер в windows ничем не отличается от вывода на экран: в распоряжение программиста предоставляется свойство canvas объекта printer, содержащее набор чертежных инструментов, и методы, свойственные классу tcanvas. Размер листа бумаги в пикселах определяют свойства height и width, а набор принтерных шрифтов – свойство fonts.
Печать текстаСуществует множество способов печати текста на принтере. Прежде всего следует назвать глобальную процедуру assignprn (она определена в модуле printers), позволяющую использовать принтер как текстовый файл и печатать текстовые строки с помощью процедуры writeln. В листинге 1 (printtext.dpr) приведен полный текст модуля, на форме которого расположены многострочный текстовый редактор memo1 и четыре кнопки: для выбора текстового файла и ввода его содержимого в редактор, для выбора нужного шрифта отображения/печати документа, для инициации процесса печати и для завершения работы программы.
Листинг 1unit unit1;

windows, messages, sysutils, classes, graphics, controls, forms, dialogs, stdctrls, buttons;

tform1 = class ( tform )

procedure button1click ( sender: tobject ) ;

procedure button2click ( sender: tobject ) ;

procedure button3click ( sender: tobject ) ;

uses printers; // Эта ссылка обязательна!

procedure tform1. button1click ( sender: tobject ) ;

// Выбор файла с текстом и его загрузка в редактор

if opendialog1. execute then

memo1. lines . loadfromfile ( opendialog1. filename )

procedure tform1. button3click ( sender: tobject ) ;

// Выбор шрифта и связывание его с memo1

if fontdialog1. execute then

memo1. font := fontdialog1. font

procedure tform1. button2click ( sender: tobject ) ;

// Печать содержимого редактора как вывод в текстовый файл

assignprn ( prn ) ; // Переназначаем вывод в файл на вывод в принтер

rewrite ( prn ) ; // Готовим принтер к печати (аналог begindoc)

printer. canvas . font := memo1. font ;

for k := 0 to memo1. lines . count -1 do

writeln ( prn, memo1. lines [ k ] ) ;

closefile ( prn ) ; // Аналог enddoc

Описанный способ печати — самый примитивный: с его помощью невозможно вывести линии, разделяющие колонки или строки, трудно форматировать текст, вставлять заголовки, номера страниц и т.д.
Значительно более гибкие средства обеспечивает свойство printer.canvas. Покажем, как с его помощью можно напечатать текст, содержащийся в редакторе memo1 (printtext.dpr, листинг 2):
Листинг 2

procedure tform1. button2click ( sender: tobject ) ;

// Печать содержимого редактора c помощью свойства printer.canvas

if memo1. lines . count = 0 then exit ;

screen. cursor := crhourglass;

with printer do

font := memo1. font ;

dy := textheight ( ‘1’ ) ; // Определяем высоту строки

y := 3 *dy; // Отступ от верхнего края листа

x := pagew >div 15 ; // Отступ от левого края

for k := 0 to memo1. lines . count -1 do

// Выводим очередную строку

textout ( x,y,memo1. lines [ k ] ) ;

// Смещаемся на следующую строку листа

if pageheight-y 2 *dy then // Нижний край листа?

newpage; // Переход на новый лист

// Выводим номер страницы посередине листа:

s := ‘- ‘ + inttostr ( pagenumber ) + ‘ -‘ ;

textout ( ( pagew >( s ) ) div 2 , dy, s ) ;

// и отчеркиваем его от текста:

moveto ( x, 3 *dy div 2 ) ;

lineto ( pagew >9 *dy div 4 ) ;

// Ордината первой строки:

end ; // if pageheight-y

end ; // for k := 0 to memo1.lines.count-1 do

end ; // with canvas do

end ; // with printer do

screen. cursor := crdefault;

Как можно увидеть, прямое обращение к чертежным инструментам свойства canvas требует от программиста значительно больших усилий, но зато предоставляет ему полный контроль над печатным изображением.
Во многих случаях для печати документа и внесения в него элементарных средств форматирования (печать общего заголовка, заголовка на каждой странице, номеров страниц и т.п.) проще использовать специальные компоненты, расположенные на странице qreport палитры компонентов delphi. Эти компоненты разработаны для создания отчетов по базам данных, но могут с успехом использоваться и для печати обычных документов (printtext.dpr).
Наконец, очень хороших результатов можно достичь, используя специализированные средства просмотра/печати документов, как, например, текстовый процессор ms word.
Печать изображенийПечать изображений может показаться очень сложным делом, однако свойство printer.canvas содержит метод:
procedure stretchdraw(const rect: trect; graphic: tgraphic ); который легко справляется с этой задачей. При обращении к нему в качестве первого параметра указывается прямоугольная область, отводимая на поверхности листа для распечатки изображения, а в качестве второго — объект класса tgraphic, в котором хранится изображение, например:

with printer do

canvas. stretchdraw ( canvas. cliprect , image1. picture . graphic ) ;

Секреты печати из программы на delphi

В данной статье рассказывается о возможных способах вывода информации на печать из программы, созданной в Delphi. Рассматривается вывод документа в текстовом режиме принтера, вывод графики с помощью объекта TPrinter и печать содержимого формы. О выводе на печать отчетов с помощью генератора отчетов ReportSmith рассказывается ниже.

Печать в текстовом режиме

Если Вам нужно напечатать на принтере документ в текстовом режиме, то это делается следующим образом. С принтером Вы работаете, как с обычным текстовым файлом, за исключением того, что вместо процедуры AssignFile нужно вызывать процедуру AssignPrn. В примере на принтер выводится одна строка текста:

Здесь необходимо, видимо, пояснить, что по сравнению с BP 7.0 в Delphi изменены названия некоторых функций и переменных в модуле System :

  • AssignFile вместо Assign
  • CloseFile вместо Close
  • TextFile вместо Text


Вывод содержимого формы на печать

Иногда в программе требуется просто получить твердую копию экранной формы. В Delphi это делается более, чем просто — у объекта TForm есть метод Print, который и нужно вызвать в нужный момент.

Графическая печать (объект TPrinter)

И все же, более интересно, как из программы созданной в Delphi можно вывести на печать графическую информацию. Для этого есть специальный объект Printer (класса TPrinter). Он становится доступен, если к программе подключить модуль Printers (т.е. добавить имя модуля в разделе uses ). С помощью этого объекта печать на принтере графической информации становится не сложнее вывода этой информации на экран. Основным является то, что Printer предоставляет разработчику свойство Canvas ( работа с канвой описана в предыдущем уроке) и методы, выводящие содержание канвы на принтер. Рассмотрим подробнее свойства и методы объекта Printer.

Aborted — тип булевский; показывает, прервал ли пользователь работу принтера методом Abort.
Canvas — канва, место для вывода графики; работа с Canvas описана в Уроке 5.
Fonts — список доступных шрифтов.
Handle — используется при прямых вызовах Windows API.
Orientation — ориентация страницы, вертикально или горизонтально.
PageWidth, PageHeight, PageNumber — соответственно ширина, высота и номер страницы.
Printers перечисляет все установленные в системе принтеры, а PrinterIndex указывает, какой из них является текущим. Чтобы печатать на принтере по умолчанию здесь должно быть значение -1.
Printing — тип булевский; показывает, начата ли печать (методом BeginDoc).
Title — заголовок для Print Manager и для заголовка перед выводом на сетевом принтере.

Abort — прерывает печать, начатую методом BeginDoc
BeginDoc — вызывается перед тем, как начать рисовать на канве.
EndDoc — вызывается когда все необходимое уже нарисовано на канве, принтер начинает печатать именно после этого метода.
NewPage — переход на новую страницу.

Остальными методами объекта в обычных случаях пользоваться не нужно.

Итак, порядок вывода на печать графической информации выглядит следующим образом:

  • выполняется метод BeginDoc
  • на канве (Canvas) рисуем все, что нужно
  • при необходимости разместить информацию на нескольких листах вызываем метод NewPage
  • посылаем нарисованное на принтер, выполняя метод EndDoc

Секреты печати из программы на delphi

Печать в текстовом режиме

Вывод содержимого формы на печать

Графическая печать (объект TPrinter)

    1. Обзор
    2. В данной статье рассказывается о возможных способах вывода информации на печать из программы, созданной в Delphi. Рассматривается вывод документа в текстовом режиме принтера, вывод графики с помощью объекта TPrinter и печать содержимого формы. О выводе на печать отчетов с помощью генератора отчетов ReportSmith рассказывается ниже.
    3. Печать в текстовом режиме

Если Вам нужно напечатать на принтере документ в текстовом режиме, то это делается следующим образом. С принтером Вы работаете, как с обычным текстовым файлом, за исключением того, что вместо процедуры AssignFile нужно вызывать процедуру AssignPrn. В примере на принтер выводится одна строка текста:

procedure TForm1.Button1Click(Sender: TObject);

Writeln(To_Prn, ‘Printer in Text Mode’);

Здесь необходимо, видимо, пояснить, что по сравнению с BP 7.0 в Delphi изменены названия некоторых функций и переменных в модуле System :

    • AssignFile вместо Assign
    • CloseFile вместо Close
    • TextFile вместо Text
      1. Вывод содержимого формы на печать
      2. Иногда в программе требуется просто получить твердую копию экранной формы. В Delphi это делается более, чем просто — у объекта TForm есть метод Print, который и нужно вызвать в нужный момент.
      3. Графическая печать (объект TPrinter)

И все же, более интересно, как из программы созданной в Delphi можно вывести на печать графическую информацию. Для этого есть специальный объект Printer (класса TPrinter). Он становится доступен, если к программе подключить модуль Printers (т.е. добавить имя модуля в разделе uses ). С помощью этого объекта печать на принтере графической информации становится не сложнее вывода этой информации на экран. Основным является то, что Printer предоставляет разработчику свойство Canvas ( работа с канвой описана в предыдущем уроке) и методы, выводящие содержание канвы на принтер. Рассмотрим подробнее свойства и методы объекта Printer.

  • Aborted — тип булевский; показывает, прервал ли пользователь работу принтера методом Abort.

    Canvas — канва, место для вывода графики; работа с Canvas описана в Уроке 5.

    Fonts — список доступных шрифтов.

    Handle — используется при прямых вызовах Windows API.

    Orientation — ориентация страницы, вертикально или горизонтально.

    PageWidth, PageHeight, PageNumber — соответственно ширина, высота и номер страницы.

    Printers перечисляет все установленные в системе принтеры, а

    PrinterIndex указывает, какой из них является текущим. Чтобы печатать на принтере по умолчанию здесь должно быть значение -1.

    Printing — тип булевский; показывает, начата ли печать (методом BeginDoc).

    Title — заголовок для Print Manager и для заголовка перед выводом на сетевом принтере.

    Abort — прерывает печать, начатую методом BeginDoc

  • BeginDoc — вызывается перед тем, как начать рисовать на канве.

    EndDoc — вызывается когда все необходимое уже нарисовано на канве, принтер начинает печатать именно после этого метода.

    NewPage — переход на новую страницу.

    Остальными методами объекта в обычных случаях пользоваться не нужно.

    Итак, порядок вывода на печать графической информации выглядит следующим образом:

    • выполняется метод BeginDoc
    • на канве (Canvas) рисуем все, что нужно
    • при необходимости разместить информацию на нескольких листах вызываем метод NewPage
    • посылаем нарисованное на принтер, выполняя метод EndDoc
        1. Пример

    Delphi. Различные способы печати из приложений

    Итак, начнем рассмотрение этих способов.

    Печать с помощью функций файлового ввода/вывода

    Здесь мы будем использовать простейшие функции ввода/вывода в файл, только свяжем выходной поток не с файлом, а с принтером. Рассмотрим пример печати текста, содержащегося в компоненте TEdit:

    var P:TextFile;
    begin
    AssignPrn(P);
    Rewrite(P);
    Writeln(P, Edit1.text);
    CloseFile(P);
    End;

    Здесь мы объявляем переменную P типа TextFile. Процедура AssignPrn является разновидностью процедуры Assign. Она настраивает переменную P на порт принтера и позволяет работать с ним как с файлом. Rewrite открывает порт для работы, а WriteLn — выводит информацию на печать. Важно закрыть порт принтера командой CloseFile.

    Этот способ можно использовать для распечатки строк списка или каких-нибудь других данных, по мере их поступления в программу.

    Печать текстов в обогащенном формате методом Print

    Если Вы пытались попробовать распечатать тексты из Вашего приложения, то , наверно, Вам известно, что компонент TRichEdit имеет метод Print, позволяющий печатать текст, хранящийся в этом компоненте. Этот метод имеет только один параметр — строку, которая при просмотре в Windows очереди печатаемых заданий является именем задания. Приведу пример использования (хотя он очевиден :)

    RichEdit1.Print(‘Print of our RichEdit1’);

    Следует заметить, что печать воспроизводит все особенности форматирования текста, так же происходит автоматический перенос строк и разбиение текста на страницы. При этом длина строк ни как не связана с размерами компонента RichEdit.

    Печать с помощью объекта Printer

    В Дельфи имеется класс печатающих объектов TPprinter, который обеспечивает печать текстов, изображений и других объектов, расположенных на его канве (Canvas).

    Модуль Дельфи Printers, содержит переменную Printer, которая является объектов типа TPrinter. Поэтому для использования этой переменной в Ваших программах, надо подключить модуль Printers в оператор Uses (к сожалению автоматически этого не делается)

    Рассмотрим подробнее некоторые свойства и методы объекта TPrinter:

    Свойство, метод Описание
    Canvas Канва — место в памяти, в котором формируется страница или документ перед печатью.
    TextOut Метод канвы, позволяющий посылать в нее текст
    BeginDoc Используется для начала задания печати
    EndDoc Используется для завершения задания печати. При этом печать начинается только после вызова этого метода!
    PageHeight Возвращает высоту страницы в пикселах
    NewPage Принудительно начинает новую страницу
    PageNumber Возвращает номер печатаемой страницы

    Приведу два примера печати с помощью объекта TPrinter текста и изображения.

    Печать текста можно осуществить так:

    Printer.BeginDoc;
    Printer.Canvas.TextOut(10,10,’Печатаем с помощью объекта Printer’);
    Printer.EndDoc;

    Если Вы хотите напечатать изображение, находящееся, например, в компоненте Image1, то код может быть таким: Printer.BeginDoc;
    with Image1.Picture.Bitmap do Printer.Canvas.CopyRect(Rect(0,0,Height,Width),Canvas,Rect(0,0,Height,Width));
    Printer.EndDoc;

    Казалось и бы и здесь все просто, но у объекта Printer есть существенный недостаток: он не производит автоматическое разбиение на строки и страницы, поэтому печатать длинные тексты предпочтительнее с помощью компонента RichEdit или Memo.

    Печать форм

    У форм в Delphi есть метод Print, который печатает всю клиентскую область формы. При этом полоса заголовка и полоса главного меню формы не печатаются.


    Свойство PrintScale определяет опции масштабирования изображения формы при печати:

    poNone Масштабирование не используется. Размер изображения может изменяться в зависимости от используемого принтера
    poPrintToFit Делается попытка напечатать изображение формы того же размера, который виден на экране
    poProportional Увеличивает или уменьшает размер изображения, подгоняя его под размер страницы.

    На этом мы заканчиваем обзор способов печати данных из Ваших приложений. Надеюсь, что еще одним вопросом у Вас стало меньше :))

    Delphi. Различные способы печати из приложений

    Delphi. Различные способы печати из приложений

    Delphi имеет стандартный объект для доступа к принтеру — TPRINTER, находящийся в модуле PRINTERS. В этом модуле имеется переменная Printer:Tpinter, что избавляет от необходимости описывать свою. Он позволяет выводить данные на печать и управлять процессом печати. Правда, в некоторых версиях Delphi 1 он имеет «глюк» — не работают функции Draw и StrethDraw. Но эта проблема поправима — можно использовать функции API. Далее приведены основные поля и методы объекта Printers:

    • Aborted: boolean — Показывает, что процесс печати прерван
    • Canvas: Tcanvas — Стандартный Canvas, как у любого графического объекта. Он позволяет рисовать на листе бумаге графику, выводить текст. . Тут есть несколько особенностей, они описаны после описания объекта.
    • Fonts: Tstrings — Возвращает список шрифтов, поддерживаемых принтером
    • Handle: HDS — Получить Handle на принтер для использования функций API (см. Далее)
    • Orientation: TprinterOrientation — Ориентация листа при печати: (poPortrait, poLandscape)
    • PageHeight: integer — Высота листа в пикселах
    • PageNumber: integer — Номер страницы, увеличивается на 1 при каждом NewPage
    • PageWidth: integer — Ширина листа в пикселах
    • PrinterIndex: integer — Номер используемого принтера по списку доступных принтеров Printers
    • Printers: TStrings — Список доступных принтеров
    • Printing: boolean — Флаг, показывающий, что сейчас идет процесс печати
    • Title: String — Имя документа или приложения. Под этим именем задание на печать регистрируется в диспетчере печати
    • AssignPrn(f: TextFile) — Связать текстовый файл с принтером. Далее вывод информации в этот файл приводит к ее печати. Удобно в простейших случаях.
    • Abort — Сбросить печать
    • BeginDoc — Начать печать
    • NewPage — Начать новую страницу
    • EndDoc — Завершить печать.

    Особенности работы с TPrinter

    1. После команды BeginDoc шрифт у Canvas принтера сбрасывается и его необходимо задавать заново
    2. Все координаты даны в пикселах, а для нормальной работы необходимы миллиметры (по двум очевидным причинам: очень трудно произвести разметку страницы в пикселах (особенно если необходима точность), и, главное, при изменении разрешающей способности принтера будет изменяться число точек на дюйм, и все координаты «поедут».
    3. У TPrinter информация о принтере, по видимому, определяются один раз — в момент запуска программы (или смены принтера). Поэтому изменение настроек принтера в процессе работы программы может привести к некорректной работе, например, неправильной печать шрифтов True Type.
    Илон Маск рекомендует:  Что такое код shm_remove_var

    Определение параметров принтера через API

    Для определения информации о принтере (плоттере, экране) необходимо знать Handle этого принтера, а его можно узнать объекта TPrinter — Printer.Handle.

    GetDevice(Handle:HDC; Index:integer):integer;

    Index — код параметра, который необходимо вернуть.

    Для Index существует ряд констант:

    • DriverVersion — вернуть версию драйвера
    • Texnology — Технология вывода, их много, основные
    • dt_Plotter — плоттер
    • dt_RasPrinter — растровый принтер
    • dt_Display — дисплей
    • HorzSize — Горизонтальный размер листа (в мм)
    • VertSize — Вертикальный размер листа (в мм)
    • HorzRes — Горизонтальный размер листа (в пикселах)
    • VertRes — Вертикальный размер листа (в пикселах)
    • LogPixelX — Разрешение по оси Х в dpi (пиксел /дюйм)
    • LogPixelY — Разрешение по оси Y в dpi (пиксел /дюйм)

    Кроме перечисленных еще около сотни, они позволяют узнать о принтере практически все. Параметры, возвращаемые по LogPixelX и LogPixelY очень важны — они позволяют произвести пересчет координат из миллиметров в пиксели для текущего разрешения принтера.

    Пример таких функций:

    Данную методику можно с успехом применять для печати картинок — зная размер картинки можно пересчитать ее размеры в пикселах для текущего разрешения принтера, масштабировать, и затем уже распечатать. Иначе на матричном принтере (180 dpi) картинка будет огромной, а на качественном струйнике (720 dpi) — микроскопической.

    Я производил печать следующим образом:

    procedure TForm6.SpeedButton1Click(Sender: TObject); var PRect: Trect; PBitMap: TBitmap; begin PBitmap:=TBitMap.Create; PBitmap.LoadFromFile(«C:\1.bmp»); with PRect do begin left:=0; top:=0; right:=Printer.PageW ; Canvas.StretchDraw(PRect,Bitmap); EndDoc; end ; PBitmap.Free; end ;

    Delphi: заметки программиста. Часть 2 | Программирование | КомпьютерПресс 5″2001

    Delphi: заметки программиста. Часть 2

    примеры к данной статье скачать

    Печать в Delphi

    Объект Printer автоматически создается в случае, если в программе указана ссылка на модуль Printers. Этот объект предоставляет программисту все необходимое для того, чтобы научить приложение выводить данные на один из подключенных к компьютеру принтеров.

    Вывод на принтер в Windows ничем не отличается от вывода на экран: в распоряжение программиста предоставляется свойство Canvas объекта Printer, содержащее набор чертежных инструментов, и методы, свойственные классу TCanvas. Размер листа бумаги в пикселах определяют свойства Height и Width, а набор принтерных шрифтов – свойство Fonts.

    Печать текста

    Существует множество способов печати текста на принтере. Прежде всего следует назвать глобальную процедуру AssignPrn (она определена в модуле Printers), позволяющую использовать принтер как текстовый файл и печатать текстовые строки с помощью процедуры WriteLn. В листинге 1 (PrintText.dpr) приведен полный текст модуля, на форме которого расположены многострочный текстовый редактор Memo1 и четыре кнопки: для выбора текстового файла и ввода его содержимого в редактор, для выбора нужного шрифта отображения/печати документа, для инициации процесса печати и для завершения работы программы.

    Листинг 1

    Описанный способ печати — самый примитивный: с его помощью невозможно вывести линии, разделяющие колонки или строки, трудно форматировать текст, вставлять заголовки, номера страниц и т.д.

    Значительно более гибкие средства обеспечивает свойство Printer.Canvas. Покажем, как с его помощью можно напечатать текст, содержащийся в редакторе Memo1 (PrintText.dpr , листинг 2):

    Листинг 2

    Как можно увидеть, прямое обращение к чертежным инструментам свойства Canvas требует от программиста значительно бо льших усилий, но зато предоставляет ему полный контроль над печатным изображением.

    Во многих случаях для печати документа и внесения в него элементарных средств форматирования (печать общего заголовка, заголовка на каждой странице, номеров страниц и т.п.) проще использовать специальные компоненты, расположенные на странице QReport палитры компонентов Delphi. Эти компоненты разработаны для создания отчетов по базам данных, но могут с успехом использоваться и для печати обычных документов (PrintText.dpr).

    Наконец, очень хороших результатов можно достичь, используя специализированные средства просмотра/печати документов, как, например, текстовый процессор MS Word.

    Печать изображений

    Печать изображений может показаться очень сложным делом, однако свойство Printer.Canvas содержит метод:

    procedure StretchDraw(const Rect: TRect; Graphic: TGraphic);

    который легко справляется с этой задачей. При обращении к нему в качестве первого параметра указывается прямоугольная область, отводимая на поверхности листа для распечатки изображения, а в качестве второго — объект класса TGraphic, в котором хранится изображение, например:

    with Printer do begin BeginDoc; Canvas.StretchDraw(Canvas.ClipRect, Image1.Picture.Graphic); EndDoc; end;

    Отображение файла в память

    Для работы с файлом динамической подкачки страниц виртуальной памяти в Windows 32 используется механизм отображения файлов в адресное пространство приложения. Соответствующие функции API доступны любому приложению и могут применяться к любому файлу (кстати, таким способом загружаются в адресное пространство процесса исполняемые файлы и DLL). В результате отображения приложение может работать с файловыми данными как с размещенными в динамической памяти. В большинстве случаев такая возможность не только повышает скорость работы с данными, но и предоставляет программисту уникальные средства обработки сразу всех записей файла. Например, он может с помощью единственного оператора проверить, входит ли заданный образец поиска в какую-либо строку текстового файла.

    Отображение файла осуществляется в три приема. Вначале файл создается обращением к функции:

    function FileCreate (FileName: String ): Integer;

    или открывается с помощью:

    function FileOpen (const FileName: String ; Mode: LongWord): Integer;

    В обеих функциях FileName — имя файла, возможно, с маршрутом доступа. Параметр Mode определяет режим доступа к файлу и может принимать одно из следующих значений: fmOpenRead — только чтение; fmOpenWrite — только запись; fmOpenReadWrite — чтение и запись. С помощью операции or эти константы можно комбинировать с одной из следующих нескольких функций, регулирующих совместный доступ к файлу: fmShareExclusive — совместный доступ запрещен; fmShareDenyWrite — другим приложениям запрещается запись; fmShareDenyRead — другим приложениям запрещается чтение; fmSchareDenyNone — совместный доступ неограничен. Обе функции возвращают дескриптор созданного (открытого) файла или 0, если операция оказалась неудачной.

    На втором этапе создается объект отображения в память. Для этого используется функция:

    function CreateFileMapping (hFile: THandle; lpFileMappingAttributes: PSecurityAttributes; flProtect, dwMaximumSizeHigh, dwMaximumSizeLow: DWord; lpName: PChar): THandle;

    Здесь hFile — дескриптор файла; lpFileMappingAttributes — указатель на структуру, в которой определяется, может ли создаваемый объект порождать дочерние объекты (обычно не может — NIL ); flProtect — определяет тип защиты, применяемый к окну отображения файла (см. об этом ниже); dwMaximumSizeHigh, dwMaximumSizeLow — соответственно старшие и младшие 32 разряда числа, содержащего размер файла (если вы будете отображать файлы длиной до 4 Гбайт, поместите в dwMaximumSizeHigh 0, если в dwMaximumSizeLow — длину файла; а если оба параметра равны 0, то размер окна отображения равен размеру файла); lpName — имя объекта отображения или NIL .

    Параметр flProtect задает тип защиты, применяемый к окну просмотра файла, и может иметь одно из следующих значений: PAGE_READONLY — файл можно только читать (файл должен быть создан или открыт в режиме fmOpenRead); PAGE_READWRITE — файл можно читать и записывать в него новые данные (файл открывается в режиме fmOpenReadWrite); PAGE_WRITECOPY — файл открыт для записи и чтения, однако обновленные данные сохраняются в отдельной защищенной области памяти (отображенные файлы могут разделяться приложениями, в этом режиме каждое приложение сохраняет изменения в отдельной области памяти или участке файла подкачки); файл открывается в режиме fmOpenReadWrite или fmOpenWrite; (этот тип защиты нельзя использовать в Windows 95/98). С помощью операции or к параметру flProtect можно присоединить такие атрибуты: SEC_COMMIT — выделяет для отображения физическую память или участок файла подкачки; SEC_IMAGE — информация об атрибутах отображения берется из образа файла; SEC_NOCASHE — отображаемые данные не кэшируются и записываются непосредственно на диск; SEC_RESERVE — резервируются страницы раздела без выделения физической памяти.

    Функция возвращает дескриптор объекта отображения или 0, если обращение было неудачным.

    Наконец, на третьем этапе создается окно просмотра, то есть собственно отображение данных в адресное пространство программы.

    function MapViewOfFile(hFileMappingObject: THandle;dwDesiresAccess: DWord; dwFileOffsetHigh, dwFileIffsetLow, dwNumberOfBytesToMap: DWord): Pointer;

    Здесь hFileMappingObject — дескриптор объекта отображения; dwDesiresAccess — определяет способ доступа к данным и может иметь одно из следующих значений: FILE_MAP_WRITE — разрешает чтение и запись (при этом в функции CreateFileMapping должен использоваться атрибут PAGE_READWRITE); FILE_MAP_READ — разрешает только чтение (в функции CreateFileMapping должен использоваться атрибут PAGE_READONLY или PAGE_READWRITE); FILE_MAP_ALL_ACCESS — то же, что и FILE_MAP_WRITE; FILE_MAP_COPY — данные доступны для записи и чтения, однако обновленные данные сохраняются в отдельной защищенной области памяти (в функции CreateFileMapping должен использоваться атрибут PAGE_WRITECOPY); dwFileOffsetHigh, dwFileIffsetLow — определяют соответственно старшие и младшие разряды смещения от начала файла, начиная с которого осуществляется отображение; dwNumberOfBytesToMap — определяет длину окна отображения (0 — длина равна длине файла). Функция возвращает указатель на первый байт отображенных данных или NIL , если обращение к функции оказалось безуспешным.

    После использования отображенных данных ресурсы окна отображения нужно освободить функцией:

    function UnMapViewOfFile(lpBaseAddress: Pointer): BOOL;

    единственный параметр обращения к которой должен содержать адрес первого отображенного байта, то есть адрес, возвращаемый функцией MapViewOfFile. Закрытие объекта отображения и самого файла осуществляется обращением к функции:

    function CloseHandle(hObject: THandle).

    В листинге 3 приводится текст модуля (File­­InMemory.dpr), который создает окно.

    Листинг 3

    Проект создает дисковый файл, состоящий из 100 тыс. случайных вещественных чисел (можно выбрать другую длину файла, если изменить значение редактора Длина массива). Файл с именем test.dat создается путем отображения файла в память (кнопка Память ) и традиционным способом (кнопка Файл ). В обоих случаях показывается время счета. Чем больше частота процессора и объем свободной оперативной памяти, тем больше будет разница во времени (листинг 3).

    О таймере

    Компонент Timer (таймер) служит для отсчета интервалов реального времени. Его свойство Interval определяет интервал временив миллисекундах, который должен пройти от включения таймера до наступления события OnTimer. Таймер включается при установке значения True в его свойство Enabled. Единожды включенный таймер все время будет возбуждать события OnTimer до тех пор, пока его свойство Enabled не примет значения False.

    Следует учесть, что в силу специфики реализации стандартного аппаратного таймера IBM-совместимого компьютера минимальный реально достижимый интервал отсчета времени не может быть меньше 55 мс (этот интервал называется тиком ), более того, любой интервал времени, отсчитываемый с помощью таймера, всегда кратен 55 мс. Чтобы убедиться в этом, проведите эксперимент, в котором подсчитывается среднее время между двумя срабатываниями таймера (Timer.dpr):

    1. Начните новый проект с пустой формой и положите на нее компонент TTimer.
    2. Установите в свойство Enabled таймера значение False.
    3. Напишите такой модуль главной формы (листинг 4):

    Листинг 4

    Необходимость нескольких (MaxCount) срабатываний для точного усреднения результата связана с тем, что системные часы обновляются каждые 55 мс. После запуска программы и ввода 1 как требуемого периода срабатывания в редакторе mmOutput вы увидите строку

    Задано 1 ms. Получено 55 ms.

    в которой указывается, какое реальное время разделяет два соседних события OnTimer. Если вы установите период таймера в диапазоне от 56 до 110 мс, в строке будет указано 110 ms и т.д. (в силу дискретности обновления системных часов результаты могут несколько отличаться в ту или иную сторону).

    В ряде практически важных областей применения (при разработке игр, в системах реального времени для управления внешними устройствам и т.п.) интервал 55 мс может оказаться слишком велик. Современный ПК имеет мультимедийный таймер, период срабатывания которого может быть от 1 мс и выше, однако этот таймер не имеет компонентного воплощения, поэтому для доступа к нему приходится использовать функции API.

    Общая схема его использования такова. Сначала готовится процедура обратного вызова (call back) с заголовком:

    procedure TimeProc(uID, uMsg: UINT; dwUser, dw1, dw2: DWORD); stdcall ;

    Здесь uID — идентификатор события таймера (см. об этом ниже); uMsg — не используется; dwUser — произвольное число, передаваемое процедуре в момент срабатывания таймера; dw1, dw2 — не используются.

    Запуск таймера реализуется функцией:

    function timeSetEvent(uDelay, uResolution: UINT; lpTimeProc: Pointer; dwUser: DWORD; fuEvent: UINT): UINT; stdcall ; external «winmm.dll»;

    Здесь uDelay — необходимый период срабатывания таймера (в мс); uResolution — разрешение таймера (значение 0 означает, что события срабатывания таймера будут возникать с максимально возможной частотой; в целях снижения нагрузки на систему вы можете увеличить это значение); lpTimeProc — адрес процедуры обратного вызова; dwUser — произвольное число, которое передается процедуре обратного вызова и которым программист может распоряжаться по своему усмотрению; fuEvent — параметр, управляющий периодичностью возникновения события таймера: TIME_ONESHOT (0) — событие возникает только один раз через uDelay миллисекунд; TIME_PERIODIC (1) — события возникают периодически каждые uDelay мс. При успешном обращении функция возвращает идентификатор события таймера и 0, если обращение было ошибочным.

    Таймер останавливается, и связанные с ним системные ресурсы освобождаются функцией:


    function timeKillEvent(uID: UINT): UINT; stdcall ; external «winmm.dll»;

    Здесь uID — идентификатор события таймера, полученный с помощью timeSetEvent.

    В следующем примере (Timer.dpr) иллюстрируется использование мультимедийного таймера (листинг 5).

    Листинг 5

    Многие разработчики сталкиваются с необходимостью организации печати из приложения текстовых документов или графики. Среда разработки Delphi предоставляет для решения этой задачи достаточно простой в использовании и эффективный инструментарий.

    Механизм печати содержится в специальном модуле printers. раs. Достаточно добавить его в секцию uses приложения и ваша программа готова к взаимодействию с принтером. Для организации печати в исходном коде применяется класс Tprinter, свойства и методы которого обеспечивают доступ к принтерам, установленным в системе.

    При помощи этого класса программист может распечатывать в своем приложении не только тексты, но и растровые изображения и графические элементы.

    Настроить принтер можно при помощи специального компонента в составе VCL — стандартного системного диалога настройки принтера

    В этой главе рассматриваются следующие вопросы:

    • свойства и методы класса Tprinter;
    • программирование печати текстов и списков строк;
    • программирование печати растровых изображений и произвольных графических элементов;
    • как напечатать изображение формы, без помощи класса Tprinter.

    Каждое приложение, в котором используется принтер, должно содержать в секции uses модуль printers. Если ссылка на данный модуль имеется, то при выполнении приложения автоматически создается экземпляр класса Tprinter, предоставляющий программисту все необходимые средства для организации вывода данных на один из подключенных к компьютеру принтеров. Рассмотрим свойства и методы класса Tprinter.

    Таблица 9.1. Свойства и методы класса Tрrinter

    property Aborted: Boolean;

    Определяет, было ли задание на печать удалено пользователем. Если задание удалено — возвращает значение True

    property Canvas: TCanvas ;

    Канва принтера (см. главу 8). Предоставляет пользователю возможность определить значения свойств Brush, Font и Pen для печати графики на принтере

    TPrinterCapability = (pcCopies, pcOrienta-tion, pcCollation); TPrinterCapabilities = set of TPrinterCapability;

    Содержит текущие установки драйвера принтера: PcCopies — количество копий; PcOrientation — ориентация листа;

    property Copies: Integer;

    Указывает требуемое количество копий документа

    property Fonts: TStrings ;

    Содержит список имен всех шрифтов, поддерживаемых текущим принтером

    property Handle: HDC;

    Контекст устройства. Применяется при вызове из программы функций Windows API

    TPrinterOrientation = (poPortrait, poLand-scape) ;

    Определяет ориентацию листа бумаги: PoPortrait — вертикальная;

    property Orientation: TPrinterOrientation;

    property PageHeight: Integer;

    Содержит высоту страницы в пикселах

    property PageNuinber: Integer;

    Содержит номер текущей страницы

    property PageWidth: Integer;

    Возвращает значение ширины страницы в пикселах

    property Printerlndex: Integer;

    Индекс имени текущего принтера в списке Printers

    property Printers: TStrings;

    Содержит список установленных в системе принтеров

    property Printing: Boolean;

    Имеет значение True до тех пор, пока продолжается процесс печати

    property Title: String;

    Строка, идентифицирующая печатаемый документ в окне состояния текущего принтера

    property Capabilities: TPrinterCapabilities;

    PcCollation — включен или нет параметр разбора по копиям

    Метод прерывает процесс печати, и принтер приступает к обработке следующего задания. При этом значение свойства Aborted устанавливается равным True

    Начинает выполнение нового задания печати

    Завершает печать документа, очищает буфер принтера и, если необходимо, прокручивает последнюю страницу. Этот метод не следует вызывать, если печать была прервана методом Abort

    Инициализирует печать с новой страницы. Значение свойства PageNumber при этом увеличивается на единицу

    Обращаем внимание читателя на то, что большинство свойств (Fonts, Handle, PageWidth, PageHeight, Aborted, Printing, Capabilities И Др.) доступны только для чтения.

    Для создания и обращения к экземпляру класса TPrinter используется объявленная В Модуле Printers функция

    function Printer: TPrinter;

    Она возвращает указатель на созданный экземпляр класса.

    Как видно из таблицы 9.1, класс TPrinter не только обеспечивает доступ к параметрам текущего принтера, но и создает индексированный список printers имен всех доступных принтеров системы. Любой принтер из списка можно сделать активным при помощи свойства printerindex.

    Управление печатью осуществляется описанными в таблице методами Abort, BeginDoc, EndDoc И NewPage. Очень важную роль играет свойство canvas, представляющее собой канву принтера (см. главу 8). С ее помощью принтер можно использовать для рисования или вывода текстов так же, как и формы или любые другие компоненты, имеющие канву.

    С точки зрения программиста простейший способ печати текстов из приложений Delphi не изменился со времен ранних версий Turbo Pascal. Для печати используются процедуры write и writein, которым в качестве устройства вывода назначается принтер.

    Решим простейшую задачу — напечатаем на принтере сакраментальную фразу “Hello, printer!” (что поделать — традиция). Для этого создадим консольное приложение (пункт меню File/New ) и добавим следующий исходный код (не забудьте о необходимости добавить в секцию uses модуль Printers):

    var FPrint: TextFile;

    Процедура Assignprn из модуля printers связывает текстовую файловую переменную с текущим принтером системы и создает буфер вывода в памяти. Оператор Rewrite открывает устройство вывода. Процедура Writein осуществляет печать строки и переводит позицию печати на новую строку (процедура write в отличие от Writein переход на новую строку не делает). И наконец, процедура CloseFile завершает печать и разрывает связь файловой переменной и принтера (рис. 9.1).

    Рис. 9.1. Главная форма проекта DemoPrint

    Подробнее об использовании файловых переменных и процедур ввода/вывода рассказывается в главе 6.

    В одном операторе write или writein можно вывести несколько значений разных типов — целые числа, переменные с плавающей точкой и т. д. Для этого значения или переменные разделяются запятыми.

    Кроме этого, в составе переменных вывода могут быть текстовые строки объектов TSrings И TStringList.

    В качестве примера рассмотрим небольшой проект DemoPrint. В нем при помощи диалога открытия файла выбирается нужный файл. В зависимости от состояния группы переключателей RadioGrp, вывод файла направляется на экран в компонент тмето или непосредственно на принтер.

    При щелчке на кнопке printBtn содержимое компонента тмето выводится на принтер (листинг 9.1.).

    Листинг 9.1. Секция implementation модуля главной формы проекта DemoPrint

    implementation uses printers;

    var FileTxt, PrintTxt: TextFile;

    while Not EOF(FileTxt) do

    begin Readin(FileTxt, TempStr);

    procedure TMainForm.OpenBtnClick(Sender: TObject);

    if Not OpenDIg.Execute then Exit;

    if RadioGrp.Itemlndex = 0

    var PrintTxt: TextFile;

    for i :=0 to Memol.Lines.Count -1 do Writeln(PrintTxt, Memol.Lines[i]);

    procedure TMainForrn.RadioGrpClick (Sender: TObject);


    begin PrintBtn.Enabled := RadioGrp.Itemlndex = 0;

    Процедура DirectPrint обеспечивает прямой вывод текстового файла на принтер. Для этого две файловые переменные связываются с выбранным файлом и принтером. Прочитанная из файла строка сразу же отправляется на принтер.

    Метод-обработчик PrintBtnClick обеспечивает вывод на печать строк из компонента ТМето. Для этого каждая строка из индексированного списка строк (свойство Lines) печатается процедурой writein. Файловая переменная Fprint настроена на текущий принтер.

    Метод-обработчик RadioGrpciick обеспечивает отключение кнопки печати файла при переключении устройства вывода на принтер.

    Для управления печатью можно использовать следующие управляющие символы:

    Write(FPrint, «После этой строки произойдет переход на новую строку», #10, #13);

    Writein (FPrint, «После этой строки включится прогон страницы»,^L);

    При печати текстового файла по умолчанию используется шрифт System размером 10. Для изменения параметров шрифта (в том числе и во время печати) используется свойство canvas объекта printer. Это может выглядеть так:

    with Printer.Canvas.Font do

    При печати графики используется свойство canvas типа TCanvas экземпляра класса Tprinter из модуля printers. Класс канвы обладает богатым набором возможностей по отображению разнообразных графических элементов и растровых изображений. Подробно свойства и методы канвы обсуждаются в главе 8, поэтому заинтересованный читатель может обратиться к ней, а здесь мы остановимся только на особенностях печати графики.

    Особенности реализации процесса передачи графики из канвы на принтер скрыты от разработчика. Для обеспечения печати необходимо выполнить следующую последовательность действий:

    1. Для начала печати используется метод BeginDoc.
    2. При помощи свойств и методов класса TCanvas, экземпляр которого для текущего принтера доступен в свойстве canvas, создается рисуемый сюжет. При вызове методов соответствующие графические элементы отправляются на печать.
    3. Для завершения печати вызывается метод EndDoc.

    Обратите внимание, что обращение к канве принтера выполняется только после начала печати. Иначе возникает ошибка времени выполнения.

    При переносе содержимого канвы на лист бумаги вид напечатанной копии сильно зависит от параметров принтера. Поэтому перед печатью желательно проверять размер изображения и при необходимости проводить его масштабирование. Оно выполняется не только при слишком больших картинках, но и при необходимости увеличить небольшое изображение до размеров листа.

    Размер листа бумаги для текущего принтера определяется свойствами PageHeight и PageWidth класса TPrinter.

    Кроме этого, качество представления графики (разрешение) для экрана и принтера могут существенно различаться. Текущее разрешение принтера можно узнать при помощи функции Windows API GetDeviceCaps, которая возвращает значения масштаба по горизонтали и вертикали, соответствующих числу логических пикселов на дюйм для используемого по умолчанию принтера.

    Примеры реализации программного кода для печати графики приведены ниже.

    Печать растровых изображений

    Для печати растрового изображения необходимо загрузить его в экземпляр класса TBitmap или его наследника. Проще всего использовать в приложении компонент Timage или созданный самостоятельно объект типа TBitmap. Затем изображение передается на канву принтера при помощи стандартных методов и класс TPrinter обеспечивает его печать.

    Например, печать изображения в центре страницы без изменения масштаба может быть реализована так:

    procedure TForml.ButtonlClick(Sender: TObject);

    with Printer, Imagel do

    if (Picture.Width > PageWidth) or(Picture.Height > PageHeight) then begin

    Илон Маск рекомендует:  Интернет и сеть

    ShowMessage(«Изображение больше страницы»);

    Canvas.Draw((PageWidth — Picture.Width) div 2,(PageHeight — Picture.Height) div 2, Picture.Bitmap);

    Если изображение помещается на страницу, то метод Canvas. Draw обеспечивает вывод изображения по центру страницы.

    Для непропорционального масштабирования изображения по размерам страницы можно сделать так:

    var ImageRect: TRect;

    with Printer, Imagel do

    В этом случае всю работу по масштабированию выполняет метод StretchDraw канвы, который изменяет размеры изображения в соответствии с размерами прямоугольника ImageRect.

    Для пропорционального масштабирования необходимо провести элементарные вычисления по расчету размеров сторон прямоугольника. Исчерпывающий пример есть в поставке Delphi: папка heip\examples\jpeg.

    Печать графических примитивов

    Печатать произвольные графические фигуры и текст как графику можно и без создания растровых изображений, а непосредственно с использованием возможностей свойства Canvas объекта printer.

    procedure TFormI.ButtonlClick(Sender: TObject);

    with Printer.Canvas do begin Pen.Color:= clBlack;

    R:= Rect(10, 10, 160, 160);

    Ellipse(R.Left, R.Top, R.Right, R.Bottom);

    TextOut (P.X, P.Y, «Ellipse»);

    При выполнении данного кода на принтере должен напечататься круг с подписью «Ellipse» под ним. Обратите внимание, что в этом случае текст под рисунком печатается при помощи графических средств.

    Свойство canvas класса TPrinter позволяет реализовывать еще одну интересную возможность: содержимое канвы формы или другого визуального компонента можно распечатать без особых хлопот.

    Предположим, что при визуализации формы на ее канве отображается некий геометрический рисунок.

    Рис. 9.2. Геометрический рисунок на канве формы

    Для его создания используются свойства и методы класса TCanvas. В приложении DemoPrintCanvas (рис. 9.2) для создания рисунка используется метод-обработчик OnPaint.

    Чтобы направить этот рисунок на печать, достаточно скопировать прямоугольник нужного размера из канвы формы в канву принтера. В листинге 9.2. это делается в методе-обработчике printBtnclick при помощи метода CopyRect.

    Листинг 9.2 Секция implementation модуля главной формы проекта DemoPrintCanvas

    procedure TMainForm.FormPaint(Sender: TObject);

    begin with Canvas do begin Pen.Color:= clBlack;

    Ellipse(10, 10, 160, 160);

    Ellipse(60, 60, 110, 110);

    Ellipse(17, 35, 153, 75);

    Ellipse; 16, 85, 154, 135);

    Text0ut(50, 180, «Нечто»);

    procedure TMainForm.PrintBtnClick(Sender: TObject);

    var ImageRect: TRect;

    begin ImageRect := Rect(10, 10, 160 , 200);

    with Printer do begin BeginDoc;

    Canvas.CopyRect(ImageRect, MainForm.Canvas, ImageRect);

    Печать формы и элементов управления

    В данном пункте мы освоим полезную и в то же время простую операцию,

    позволяющую напечатать форму в том виде, как она выглядит на экране.

    Для ее реализации следует вызвать метод print формы. При этом включать в секцию uses модуль printers не нужно.

    Метод класса TForm

    работает следующим образом. Он копирует клиентскую область текущего окна во внеэкранное растровое изображение, а затем печатает его с помощью функции Windows API stretchDiBits. Для управления режимом масштабируемой копии используется свойство

    type TPrintScale = (poNone, poProportional, poPrintToFit) ;

    property PrintScale: TPrintScale;

    Значения свойства имеют такой смысл:

    • PoNone — масштабирования нет. Размер напечатанного изображения зависит от разрешения принтера.Как правило, бумажная копия оказывается в этом случае в несколько раз меньше оригинала.
    • poProportional — форма печатается таким образом, что примерно сохраняется видимый на экране размер изображения.
    • poPrintToFit — масштабирование осуществляется до размеров страницы. То есть форма заполняет страницу в одном из направлений.

    Есть и другой путь печати как форм, так и любых других элементов управления — наследников класса TwinControl. У всех оконных элементов управления есть метод paintTo, позволяющий отрисовывать «себя» на любой канве. В нашем случае это канва принтера.

    Контроль ошибок печати

    Для повышения надежности приложений при работе с принтером применяется специальный класс исключительной ситуации EPrinter, происходящий непосредственно от базовой исключительной ситуации Exception. Поэтому класс EPrinter обладает стандартным набором свойств и методов (см. главу 4).

    Применяется он также стандартным образом, внутри блока try . except:

    with Printer do try

    Canvas.TextOut(100, 100, «SomeTexf);

    on E: EPrinter do ShowMessage(«Ошибка печати»);

    В данной главе рассмотрены вопросы, связанные с организацией вывода на печать текстов, списков строк, форм, растровых изображений и произвольных графических объектов. Определяющую роль в этих процессах играет модуль printers, описывающий класс TPrinter. Экземпляр класса доступен разработчику через функцию Printer.

    Печать текстов основана на хорошо известных процедурах ввода/вывода, перед использованием которых необходимо связать файловую переменную с текущим принтером при помощи метода Assignprn.

    Печать графики основывается на использовании возможностей класса TCanvas, доступного в объекте типа TPrinter через свойство Canvas.


    При изучении этой главы полезно вспомнить материал следующих глав:

    • глава 4 «Обработка исключительных ситуаций»;
    • глава 6 «Файлы и устройства ввода/вывода»;
    • глава 8 «Графика».

    В этой статье я постараюсь рассказать Вам о самых удобных и распространенных способах печати текстов и изображений из Ваших приложений. Печать используется в приложениях не так часто, вот и возникают различные вопросы по этому поводу. Иногда бывает необходимо «вывести на принтер» график получившейся функции или отчет о деятельности фирмы и т.д. Прочитав эту статью Вы освоите все самое необходимое для печати данных из Ваших приложений.

    Итак, начнем рассмотрение этих способов.

    Печать с помощью функций файлового ввода/вывода

    Здесь мы будем использовать простейшие функции ввода/вывода в файл, только свяжем выходной поток не с файлом, а с принтером. Рассмотрим пример печати текста, содержащегося в компоненте TEdit:

    Var P:TextFile;
    begin
    AssignPrn(P);
    Rewrite(P);
    Writeln(P, Edit1.text);
    CloseFile(P);
    End;

    Здесь мы объявляем переменную P типа TextFile. Процедура AssignPrn является разновидностью процедуры Assign. Она настраивает переменную P на порт принтера и позволяет работать с ним как с файлом. Rewrite открывает порт для работы, а WriteLn — выводит информацию на печать. Важно закрыть порт принтера командой CloseFile.

    Этот способ можно использовать для распечатки строк списка или каких-нибудь других данных, по мере их поступления в программу.

    Печать текстов в обогащенном формате методом Print

    Если Вы пытались попробовать распечатать тексты из Вашего приложения, то, наверно, Вам известно, что компонент TRichEdit имеет метод Print, позволяющий печатать текст, хранящийся в этом компоненте. Этот метод имеет только один параметр — строку, которая при просмотре в Windows очереди печатаемых заданий является именем задания. Приведу пример использования (хотя он очевиден:)

    RichEdit1.Print(«Print of our RichEdit1»);

    Следует заметить, что печать воспроизводит все особенности форматирования текста, так же происходит автоматический перенос строк и разбиение текста на страницы. При этом длина строк ни как не связана с размерами компонента RichEdit.

    Печать с помощью объекта Printer

    В Дельфи имеется класс печатающих объектов TPprinter, который обеспечивает печать текстов, изображений и других объектов, расположенных на его канве (Canvas).

    Модуль Дельфи Printers, содержит переменную Printer, которая является объектов типа TPrinter. Поэтому для использования этой переменной в Ваших программах, надо подключить модуль Printers в оператор Uses (к сожалению автоматически этого не делается)

    Рассмотрим подробнее некоторые свойства и методы объекта TPrinter:

    Свойство, метод Описание
    Canvas Канва — место в памяти, в котором формируется страница или документ перед печатью.
    TextOut Метод канвы, позволяющий посылать в нее текст
    BeginDoc Используется для начала задания печати
    EndDoc Используется для завершения задания печати. При этом печать начинается только после вызова этого метода!
    PageHeight Возвращает высоту страницы в пикселах
    NewPage Принудительно начинает новую страницу
    PageNumber Возвращает номер печатаемой страницы

    Приведу два примера печати с помощью объекта TPrinter текста и изображения.

    Печать текста можно осуществить так:

    Printer.BeginDoc;
    Printer.Canvas.TextOut(10,10,»Печатаем с помощью объекта Printer»);
    Printer.EndDoc;

    Если Вы хотите напечатать изображение, находящееся, например, в компоненте Image1, то код может быть таким: Printer.BeginDoc;
    with Image1.Picture.Bitmap do Printer.Canvas.CopyRect(Rect(0,0,Height,Width),Canvas,Rect(0,0,Height,Width));
    Printer.EndDoc;

    Казалось и бы и здесь все просто, но у объекта Printer есть существенный недостаток: он не производит автоматическое разбиение на строки и страницы, поэтому печатать длинные тексты предпочтительнее с помощью компонента RichEdit или Memo.

    Печать форм

    У форм в Delphi есть метод Print, который печатает всю клиентскую область формы. При этом полоса заголовка и полоса главного меню формы не печатаются.

    Свойство PrintScale определяет опции масштабирования изображения формы при печати:

    На этом мы заканчиваем обзор способов печати данных из Ваших приложений. Надеюсь, что еще одним вопросом у Вас стало меньше:))

    Печать сейчас широко используется в приложениях Delphi, когда нужно напечатать текст, изображение и т.д. Большинство приложений Windows поддерживают возможность печати. В Delphi есть несколько способов печати, в зависимости от качества, которого Вы хотите достичь.

    Печать формы

    В Delphi у формы Form имеется функция Print , которая может выводить на печать форму.

    Procedure TForm1.Button1Click(Sender: TObject); begin Form1.Print; end;

    Также Вы можете использовать свойство PrintScale , которое изменяет масштаб печатаемого объекта. Это свойство содержит три опции:

    • poNone — печать будет произведена с настройками принтера.
    • poProportional — печать страницы, которая будет иметь те же размеры, что и на экране.
    • poPrintToFit — размер изменяется в зависимости от размера страницы.

    При этом получается не самое высокое качество печати.

    Печать управления TRichEdit

    Функция Print имеется также у компонента TRichEdit .

    Procedure TForm1.Button2Click(Sender: TObject); begin RichEdit1.Print(«Имя документа»); end;

    Как видите, здесь функция Print получает один строковой параметр, который будет отображаться в очереди печати как имя документа.

    Печать текстовых файлов при помощи ShellExecute

    Также можно использовать функцию API ShellExecute для печати текстового документа.

    Uses < … >ShellApi < … >procedure TForm1.Button3Click(Sender: TObject); begin ShellExecute(Handle, «Print», «C:\Test.txt», nil, nil, SW_Hide); end;

    При этом открывается приложение, которое ассоциировано с файлом. В моем случае это Блокнот.

    Диалоговое окно печати

    В Delphi имеется два диалоговых окна для печати: диалоговое окно при помощи компонента TPrintDialog и при помощи диалогового окна установок принтера TPrinterSetupDialog .

    Диалоговое окно TPringDialog

    Компонент диалогового окна TPrintDialog Вы можете использовать непосредственно перед началом печати. Компонент TPrintDialog имеет свои свойства и метода, которые Вы сможете найти в справке по Delphi. Диалоговое окно вызывается конструкцией:

    Procedure TForm1.Button4Click(Sender: TObject); begin PrintDialog1.Execute; end;

    Диалоговое окно Настройка печати

    При вызове этого диалогового окна появляется возможность выбрать настройки печати, такие как размер бумаги, ориентацию и т.д. Можно также использовать это окно для настроек принтера. Вызывается это диалоговое окно функцией Execute .

    Procedure TForm1.Button5Click(Sender: TObject); begin PrinterSetupDialog1.Execute; end;

    TPrinter

    Объект TPrinter используется для печати документов, текста и т.д. Вот пример использования TPrinter для печати прямоугольника. Не забудьте добавить модуль Printers в раздел uses формы.

    Procedure TForm1.Button6Click(Sender: TObject); begin Printer.BeginDoc; Printer.Canvas.Rectangle(100, 100, 300, 300); Printer.EndDoc; end;

    Таким же образом, на холсте Canvas объекта Printer можно напечатать и текст.

    Procedure TForm1.Button7Click(Sender: TObject); begin Printer.BeginDoc; Printer.Canvas..EndDoc; end;

    А также вывести растровое изображение на печать, словно на холст.

    Procedure TForm1.Button8Click(Sender: TObject); var bmp: TBitmap; begin bmp:= TBitmap.Create; bmp.LoadFromFile(«C:\athena.bmp»); Printer.BeginDoc; Printer.Canvas.Draw(10, 10, bmp); Printer.EndDoc; bmp.Free; end;

    При печати растровое изображение будет небольшим, чтобы вывести нужный Вам размер на печать, используйте StretchDraw .

    Реализация Просмотра Печати

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

    Небольшое приложение с использованием предварительного просмотра печати Вы можете посмотреть

    Копирование содержимого формы в буфер обмена

    Справочник по компонентам Delphi. Часть 3
    Страница 17. Печать данных из приложения

    Печать данных из приложения

    Практически каждое приложение, работающее в Windows, имеет набор воз­можностей, позволяющих печатать те или иные данные. В состав Delphi вклю­чен специальный модуль — PRINTERS, в котором описан класс TPrinter, инкап­сулирующий интерфейс печати Windows.

    Свойства и методы этого класса позволяют разработчику реализовать доста­точно широкий набор возможностей для печати из приложения. Экземпляр объекта TPrinter с именем Printer создается автоматически при запуске приложения, если в его состав включен соответствующий модуль.

    Обычно перед началом печати какого-либо документа из приложения необ­ходимо проверить и при необходимости переустановить стандартные парамет­ры. Этот процесс может быть как автоматическим (проверка и переопределение по умолчанию из программы), так и интерактивным (при помощи стандартных диалоговых окон PrintDialog и PrintSetupDialog).

    Информацию обо всех инсталлированных в системе принтерах содержит список свойства:

    (Ro) property Printers: TStrings;

    Свойство доступно только при вьшолнении приложения. Информация о том, какой принтер из списка является текущим, содержится в свойстве:

    property Printerlndex: Integer;

    Оно возвращает порядковый номер принтера в списке. Значение -1 использу­ется для идентификации принтера, установленного по умолчанию.

    Метод procedure GetPrinter(ADevice, ADriver, APort: PChar; var ADeviceMode: THandle);

    возвращает параметры текущего принтера, используя для его идентификации значение свойства Printerlndex.

    Метод procedure SetPrinter(ADevice, ADriver, APort: PChar; ADeviceMode: THandle);

    проверяет, инсталлирован ли в системе принтер с заданными параметрами. В случае успеха этот принтер становится текущим, в случае неудачи инсталлируется новый принтер. Использование этих двух методов не рекомен­дуется справочным руководством, так как по мнению разработчиков вполне достаточно свойств Printers и Printerlndex. Авторы также рекомендуют приме­нять эти методы только подготовленньм разработчикам, если им необходимо работать с драйверами принтеров.


    Свойство (Ro) property Fonts: TStrings;

    содержит список шрифтов, поддерживаемых текущим принтером. Свойство доступно только при вьшолнении приложения.

    Расположение листа бумаги определяется свойством:

    property Orientation: TPrinterOrientation;

    TPrinterOrientation = (poPortrait, poLandscape) ;

    Свойство доступно только при выполнении приложения. Высоту и ширину листа бумаги содержат свойства:

    (Ro) property PageHeight: Integer; (R^ property PageWidth: Integer; Свойство property Title: string;

    содержит текстовую строку, которая используется для идентификации процесса печати (работы) в списке Диспетчера печати Windows.

    Дескриптор принтера, с которым связан объект TPrinter, возвращается в свой­стве:

    (Ro) property Handle: HDC;

    Поверхность печатаемой страницы доступна для вывода графических объектов (например, изображений) через свойство:

    (Ro) property Canvas: TCanvas;

    При использовании канвы необходимо проверить используемый принтер на предмет поддержки графики. Свойство доступно только при выполнении приложения.

    Для управления процессом печати объект содержит набор методов и свойств:

    Начинает печать документа.

    Завершает печать документа.

    (Ro) property Printing: Boolean; procedure Abort;

    Определяет состояние процесса. Возвращает True во время печати.

    Используется для прерывания печати.

    (Ro) property Aborted: Boolean;

    Устанавливается в True, если печать прервана.

    Отменяет печать текущей страницы и начинает распечатку следующей. При этом значение свойства PageNumber увеличивается на единицу.

    (Ro) property PageNumber: Integer;

    Содержит номер печатаемой страницы. Обращение к нему имеет смысл только в процессе печати документа.

    procedure BeginDoc;
    procedure EndDoc;
    procedure NewPage;

    В модуле PRINTERS описан метод procedure AssignPrn(var F: Text);

    который связывает текстовую файловую переменную с текущим принтером, что позволяет направлять на принтер текстовые данные, используя традиционные процедуры Write и Writeln. При печати используется шрифт, определенный в канве объекта TPrinter. Следующий пример распечатывает

    содержимое многострочного редактора PrintMemo при нажатии кнопки

    printBtn: procedure PrintForm.PrintBtnClick(Sender: TObject); var PrnTxt: System.Text; i: Integer; begin AssignPrn(PrnTxt) ; Rewrite(PrnTxt) ;

    for i := 0 to PrintMemo. Lines .Count -1 do Writeln (PrnTxt, PrintMemo.Lines [ i ]);

    Для печати графики необходимо передать требуемый графический объект (изображение, график, фигуру) в канву объекта Printer. В следующем примере при нажатии кнопки PrintBfcn печатается изображение из компо­нента Printlmage:

    procedure PrintForm.PrintBtnClick(Sender: TObject); begin with Printer do begin BeginDoc; Canvas.Draw(0, 0, Printlmage.Picture.Graphic); EndDoc ; end;

    При необходимости пропорции распечатываемого графического объекта можно скорректировать при помощи свойства формы-контейнера PrintScale.

    Секреты печати из программы на delphi

    Многие разработчики сталкиваются с необходимостью организации печати из приложения текстовых документов или графики. Среда разработки Delphi предоставляет для решения этой задачи достаточно простой в использовании и эффективный инструментарий.

    Механизм печати содержится в специальном модуле printers. раs. Достаточно добавить его в секцию uses приложения и ваша программа готова к взаимодействию с принтером. Для организации печати в исходном коде применяется класс Tprinter, свойства и методы которого обеспечивают доступ к принтерам, установленным в системе.

    При помощи этого класса программист может распечатывать в своем приложении не только тексты, но и растровые изображения и графические элементы.

    Настроить принтер можно при помощи специального компонента в составе VCL — стандартного системного диалога настройки принтера

    В этой главе рассматриваются следующие вопросы:

    • свойства и методы класса Tprinter;
    • программирование печати текстов и списков строк;
    • программирование печати растровых изображений и произвольных графических элементов;
    • как напечатать изображение формы, без помощи класса Tprinter.

    Каждое приложение, в котором используется принтер, должно содержать в секции uses модуль printers. Если ссылка на данный модуль имеется, то при выполнении приложения автоматически создается экземпляр класса Tprinter, предоставляющий программисту все необходимые средства для организации вывода данных на один из подключенных к компьютеру принтеров. Рассмотрим свойства и методы класса Tprinter.

    Таблица 9.1. Свойства и методы класса T р rinter

    property Aborted: Boolean;

    Определяет, было ли задание на печать удалено пользователем. Если задание удалено — возвращает значение True

    property Canvas: TCanvas ;

    Канва принтера (см. главу 8). Предоставляет пользователю возможность определить значения свойств Brush, Font и Pen для печати графики на принтере

    TPrinterCapability = (pcCopies, pcOrienta-tion, pcCollation); TPrinterCapabilities = set of TPrinterCapability;

    Содержит текущие установки драйвера принтера: PcCopies — количество копий; PcOrientation — ориентация листа;

    property Copies: Integer;

    Указывает требуемое количество копий документа

    property Fonts: TStrings ;

    Содержит список имен всех шрифтов, поддерживаемых текущим принтером

    property Handle: HDC;

    Контекст устройства. Применяется при вызове из программы функций Windows API

    TPrinterOrientation = (poPortrait, poLand-scape) ;

    Определяет ориентацию листа бумаги: PoPortrait — вертикальная;

    property Orientation: TPrinterOrientation;

    property PageHeight: Integer;

    Содержит высоту страницы в пикселах

    property PageNuinber: Integer;

    Содержит номер текущей страницы

    property PageWidth: Integer;

    Возвращает значение ширины страницы в пикселах

    property Printerlndex: Integer;

    Индекс имени текущего принтера в списке Printers

    property Printers: TStrings;

    Содержит список установленных в системе принтеров

    property Printing: Boolean;

    Имеет значение True до тех пор, пока продолжается процесс печати

    property Title: String;

    Строка, идентифицирующая печатаемый документ в окне состояния текущего принтера

    property Capabilities: TPrinterCapabilities;


    PcCollation — включен или нет параметр разбора по копиям

    Метод прерывает процесс печати, и принтер приступает к обработке следующего задания. При этом значение свойства Aborted устанавливается равным True

    Начинает выполнение нового задания печати

    Завершает печать документа, очищает буфер принтера и, если необходимо, прокручивает последнюю страницу. Этот метод не следует вызывать, если печать была прервана методом Abort

    Инициализирует печать с новой страницы. Значение свойства PageNumber при этом увеличивается на единицу

    Обращаем внимание читателя на то, что большинство свойств (Fonts, Handle, PageWidth, PageHeight, Aborted, Printing, Capabilities И Др.) доступны только для чтения.

    Для создания и обращения к экземпляру класса TPrinter используется объявленная В Модуле Printers функция

    function Printer: TPrinter;

    Она возвращает указатель на созданный экземпляр класса.

    Как видно из таблицы 9.1, класс TPrinter не только обеспечивает доступ к параметрам текущего принтера, но и создает индексированный список printers имен всех доступных принтеров системы. Любой принтер из списка можно сделать активным при помощи свойства printerindex.

    Управление печатью осуществляется описанными в таблице методами Abort, BeginDoc, EndDoc И NewPage. Очень важную роль играет свойство canvas, представляющее собой канву принтера (см. главу 8). С ее помощью принтер можно использовать для рисования или вывода текстов так же, как и формы или любые другие компоненты, имеющие канву.

    С точки зрения программиста простейший способ печати текстов из приложений Delphi не изменился со времен ранних версий Turbo Pascal. Для печати используются процедуры write и writein, которым в качестве устройства вывода назначается принтер.

    Решим простейшую задачу — напечатаем на принтере сакраментальную фразу «Hello, printer!» (что поделать — традиция). Для этого создадим консольное приложение (пункт меню File/New) и добавим следующий исходный код (не забудьте о необходимости добавить в секцию uses модуль Printers):

    var FPrint: TextFile;

    Процедура Assignprn из модуля printers связывает текстовую файловую переменную с текущим принтером системы и создает буфер вывода в памяти. Оператор Rewrite открывает устройство вывода. Процедура Writein осуществляет печать строки и переводит позицию печати на новую строку (процедура write в отличие от Writein переход на новую строку не делает). И наконец, процедура CloseFile завершает печать и разрывает связь файловой переменной и принтера (рис. 9.1).

    Рис. 9.1. Главная форма проекта DemoPrint

    Подробнее об использовании файловых переменных и процедур ввода/вывода рассказывается в главе 6.

    В одном операторе write или writein можно вывести несколько значений разных типов — целые числа, переменные с плавающей точкой и т. д. Для этого значения или переменные разделяются запятыми.

    Кроме этого, в составе переменных вывода могут быть текстовые строки объектов TSrings И TStringList.

    В качестве примера рассмотрим небольшой проект DemoPrint. В нем при помощи диалога открытия файла выбирается нужный файл. В зависимости от состояния группы переключателей RadioGrp, вывод файла направляется на экран в компонент тмето или непосредственно на принтер.

    При щелчке на кнопке printBtn содержимое компонента тмето выводится на принтер (листинг 9.1.).

    Листинг 9.1. Секция implementation модуля главной формы проекта DemoPrint

    implementation uses printers;

    var FileTxt, PrintTxt: TextFile;

    while Not EOF(FileTxt) do

    begin Readin(FileTxt, TempStr);

    procedure TMainForm.OpenBtnClick(Sender: TObject);

    if Not OpenDIg.Execute then Exit;

    if RadioGrp.Itemlndex = 0

    procedure TMainForm.PrintBtnClick(Sender: TObject);

    var PrintTxt: TextFile;

    for i :=0 to Memol.Lines.Count -1 do Writeln(PrintTxt, Memol.Lines[i]);

    procedure TMainForrn.RadioGrpClick (Sender: TObject);

    begin PrintBtn.Enabled := RadioGrp.Itemlndex = 0;

    Процедура DirectPrint обеспечивает прямой вывод текстового файла на принтер. Для этого две файловые переменные связываются с выбранным файлом и принтером. Прочитанная из файла строка сразу же отправляется на принтер.

    Метод-обработчик PrintBtnClick обеспечивает вывод на печать строк из компонента ТМето. Для этого каждая строка из индексированного списка строк (свойство Lines) печатается процедурой writein. Файловая переменная Fprint настроена на текущий принтер.

    Метод-обработчик RadioGrpciick обеспечивает отключение кнопки печати файла при переключении устройства вывода на принтер.

    Для управления печатью можно использовать следующие управляющие символы:

    Write(FPrint, ‘После этой строки произойдет переход на новую строку’, #10, #13);

    Writein (FPrint, ‘После этой строки включится прогон страницы’, ^L);

    При печати текстового файла по умолчанию используется шрифт System размером 10. Для изменения параметров шрифта (в том числе и во время печати) используется свойство canvas объекта printer. Это может выглядеть так:

    Илон Маск рекомендует:  Работа с текстом

    with Printer.Canvas.Font do

    При печати графики используется свойство canvas типа TCanvas экземпляра класса Tprinter из модуля printers. Класс канвы обладает богатым набором возможностей по отображению разнообразных графических элементов и растровых изображений. Подробно свойства и методы канвы обсуждаются в главе 8, поэтому заинтересованный читатель может обратиться к ней, а здесь мы остановимся только на особенностях печати графики.

    Особенности реализации процесса передачи графики из канвы на принтер скрыты от разработчика. Для обеспечения печати необходимо выполнить следующую последовательность действий:

    1. Для начала печати используется метод BeginDoc.
    2. При помощи свойств и методов класса TCanvas, экземпляр которого для текущего принтера доступен в свойстве canvas, создается рисуемый сюжет. При вызове методов соответствующие графические элементы отправляются на печать.
    3. Для завершения печати вызывается метод EndDoc.

    Обратите внимание, что обращение к канве принтера выполняется только после начала печати. Иначе возникает ошибка времени выполнения.

    При переносе содержимого канвы на лист бумаги вид напечатанной копии сильно зависит от параметров принтера. Поэтому перед печатью желательно проверять размер изображения и при необходимости проводить его масштабирование. Оно выполняется не только при слишком больших картинках, но и при необходимости увеличить небольшое изображение до размеров листа.

    Размер листа бумаги для текущего принтера определяется свойствами PageHeight и PageWidth класса TPrinter.

    Кроме этого, качество представления графики (разрешение) для экрана и принтера могут существенно различаться. Текущее разрешение принтера можно узнать при помощи функции Windows API GetDeviceCaps, которая возвращает значения масштаба по горизонтали и вертикали, соответствующих числу логических пикселов на дюйм для используемого по умолчанию принтера.

    Примеры реализации программного кода для печати графики приведены ниже.

    Печать растровых изображений

    Для печати растрового изображения необходимо загрузить его в экземпляр класса TBitmap или его наследника. Проще всего использовать в приложении компонент Timage или созданный самостоятельно объект типа TBitmap. Затем изображение передается на канву принтера при помощи стандартных методов и класс TPrinter обеспечивает его печать.

    Например, печать изображения в центре страницы без изменения масштаба может быть реализована так:

    procedure TForml.ButtonlClick(Sender: TObject);

    with Printer, Imagel do

    if (Picture.Width > PageWidth) or(Picture.Height > PageHeight) then begin

    ShowMessage(‘Изображение больше страницы’);

    Canvas.Draw((PageWidth — Picture.Width) div 2,(PageHeight — Picture.Height) div 2, Picture.Bitmap);

    Если изображение помещается на страницу, то метод Canvas. Draw обеспечивает вывод изображения по центру страницы.

    Для непропорционального масштабирования изображения по размерам страницы можно сделать так:

    procedure TFormI.ButtonlClick(Sender: TObject);

    var ImageRect: TRect;

    with Printer, Imagel do

    В этом случае всю работу по масштабированию выполняет метод StretchDraw канвы, который изменяет размеры изображения в соответствии с размерами прямоугольника ImageRect.

    Для пропорционального масштабирования необходимо провести элементарные вычисления по расчету размеров сторон прямоугольника. Исчерпывающий пример есть в поставке Delphi: папка heip\examples\jpeg.

    Печать графических примитивов

    Печатать произвольные графические фигуры и текст как графику можно и без создания растровых изображений, а непосредственно с использованием возможностей свойства Canvas объекта printer.

    procedure TFormI.ButtonlClick(Sender: TObject);

    with Printer.Canvas do begin Pen.Color := clBlack;

    R := Rect( 10, 10, 160, 160);

    Ellipse(R.Left, R.Top, R.Right, R.Bottom);

    TextOut (P.X, P.Y, ‘Ellipse’);

    При выполнении данного кода на принтере должен напечататься круг с подписью «Ellipse» под ним. Обратите внимание, что в этом случае текст под рисунком печатается при помощи графических средств.

    Свойство canvas класса TPrinter позволяет реализовывать еще одну интересную возможность: содержимое канвы формы или другого визуального компонента можно распечатать без особых хлопот.

    Предположим, что при визуализации формы на ее канве отображается некий геометрический рисунок.

    Рис. 9.2. Геометрический рисунок на канве формы

    Для его создания используются свойства и методы класса TCanvas. В приложении DemoPrintCanvas (рис. 9.2) для создания рисунка используется метод-обработчик OnPaint.

    Чтобы направить этот рисунок на печать, достаточно скопировать прямоугольник нужного размера из канвы формы в канву принтера. В листинге 9.2. это делается в методе-обработчике printBtnclick при помощи метода CopyRect.

    Листинг 9.2 Секция implementation модуля главной формы проекта DemoPrintCanvas

    procedure TMainForm.FormPaint(Sender: TObject);

    begin with Canvas do begin Pen.Color := clBlack;

    Ellipse( 10, 10, 160, 160 );

    Ellipse( 60, 60, 110, 110);


    Ellipse( 17, 35, 153, 75);

    Ellipse; 16, 85, 154, 135);

    Text0ut(50, 180, ‘Нечто’);

    procedure TMainForm.PrintBtnClick(Sender: TObject);

    var ImageRect: TRect;

    begin ImageRect := Rect(10, 10, 160 , 200);

    with Printer do begin BeginDoc;

    Canvas.CopyRect(ImageRect, MainForm.Canvas, ImageRect);

    Печать формы и элементов управления

    В данном пункте мы освоим полезную и в то же время простую операцию,

    позволяющую напечатать форму в том виде, как она выглядит на экране.

    Для ее реализации следует вызвать метод print формы. При этом включать в секцию uses модуль printers не нужно.

    Метод класса TForm

    работает следующим образом. Он копирует клиентскую область текущего окна во внеэкранное растровое изображение, а затем печатает его с помощью функции Windows API stretchDiBits. Для управления режимом масштабируемой копии используется свойство

    type TPrintScale = (poNone, poProportional, poPrintToFit) ;

    property PrintScale: TPrintScale;

    Значения свойства имеют такой смысл:

    • PoNone — масштабирования нет. Размер напечатанного изображения зависит от разрешения принтера. Как правило, бумажная копия оказывается в этом случае в несколько раз меньше оригинала.
    • poProportional — форма печатается таким образом, что примерно сохраняется видимый на экране размер изображения.
    • poPrintToFit — масштабирование осуществляется до размеров страницы. То есть форма заполняет страницу в одном из направлений.

    Есть и другой путь печати как форм, так и любых других элементов управления — наследников класса TwinControl. У всех оконных элементов управления есть метод paintTo, позволяющий отрисовывать «себя» на любой канве. В нашем случае это канва принтера.

    Контроль ошибок печати

    Для повышения надежности приложений при работе с принтером применяется специальный класс исключительной ситуации EPrinter, происходящий непосредственно от базовой исключительной ситуации Exception. Поэтому класс EPrinter обладает стандартным набором свойств и методов (см. главу 4).

    Применяется он также стандартным образом, внутри блока try . except:

    with Printer do try

    Canvas.TextOut(100, 100, ‘SomeTexf );

    on E: EPrinter do ShowMessage(‘Ошибка печати’);

    В данной главе рассмотрены вопросы, связанные с организацией вывода на печать текстов, списков строк, форм, растровых изображений и произвольных графических объектов. Определяющую роль в этих процессах играет модуль printers, описывающий класс TPrinter. Экземпляр класса доступен разработчику через функцию Printer.

    Печать текстов основана на хорошо известных процедурах ввода/вывода, перед использованием которых необходимо связать файловую переменную с текущим принтером при помощи метода Assignprn.

    Печать графики основывается на использовании возможностей класса TCanvas, доступного в объекте типа TPrinter через свойство Canvas.

    При изучении этой главы полезно вспомнить материал следующих глав:

    • глава 4 «Обработка исключительных ситуаций»;
    • глава 6 «Файлы и устройства ввода/вывода»;
    • глава 8 «Графика».

    Работа с принтером на Delphi

    Delphi имеет стандартный объект для доступа к принтеру — TPRINTER, находящийся в модуле PRINTERS. В этом модуле имеется переменная Printer:Tpinter, что избавляет от необходимости описывать свою.
    Он позволяет выводить данные на печать и управлять процессом печати. Правда, в некоторых версиях Delphi 1 он имеет «глюк» — не работают функции Draw и StrethDraw. Но эта проблема поправима — можно использовать функции API. Далее приведены основные поля и методы объекта Printers :

    PROPERTY
    Aborted:boolean — Показывает, что процесс печати прерван
    Canvas:Tcanvas — Стандартный Canvas, как у любого графического объекта. Он позволяет рисовать на листе бумаге графику, выводить текст . . Тут есть несколько особенностей, они описаны после описания объекта.
    Fonts:Tstrings — Возвращает список шрифтов, поддерживаемых принтером
    Handle:HDS — Получить Handle на принтер для использования функций API (см. Далее)
    Orientation:TprinterOrientation — Ориентация листа при печати : (poPortrait, poLandscape)
    PageHeight:integer — Высота листа в пикселах
    PageNumber:integer — Номер страницы, увеличивается на 1 при каждом NewPage
    PageWidth:integer — Ширина листа в пикселах
    PrinterIndex:integer — Номер используемого принтера по списку доступных принтеров Printers
    Printers:Tstrings — Список доступных принтеров
    Printing:boolean — Флаг, показывающий, что сейчас идет процесс печати
    Title:string — Имя документа или приложения. Под этим именем задание на печать регистрируется в диспетчере печати

    METODS
    AssignPrn(f:TextFile) — Связать текстовый файл с принтером.
    Далее вывод информации в этот файл приводит к ее печати.
    Удобно в простейших случаях.
    Abort — Сбросить печать
    BeginDoc — Начать печать
    NewPage — Начать новую страницу
    EndDoc — Завершить печать.

    Procedure TForm1.Button1Click(Sender: TObject);
    Begin
    With Printer do Begin
    BeginDoc; < Начало печати >
    Canvas.Font:=label1.font; < Задали шрифт >
    Canvas.TextOut(100,100,’Это тест принтера . ‘); < Печатаем текст >
    EndDoc; < Конец печати >
    end;
    end;

    1. После команды BeginDoc шрифт у Canvas принтера сбрасывается и
    его необходимо задавать заново

    2. Все координаты даны в пикселах, а для нормальной работы необходимы
    миллиметры (по двум очевидным причинам: очень трудно произвести разметку страницы в пикселах (особенно если необходима точность), и , главное, при изменении разрешающей способности принтера будет изменяться число точек
    на дюйм, и все координаты «поедут».

    3. У TPrinter информация о принтере, по видимому, определяются один раз — в момент запуска программы (или смены принтера). Поэтому изменение настроек
    принтера в процессе работы программы может привести к некорректной работе, например, неправильной печать шрифтов True Type.

    Для определения информации о принтере (плоттере, экране) необходимо знать Handle этого принтера, а его можно узнать объекта TPrinter -Printer.Handle.

    Далее вызывается функция API (unit WinProcs):
    GetDevice(Handle:HDC; Index:integer):integer;
    Index — код параметра, который необходимо вернуть.

    Для Index существует ряд констант :
    DriverVersion — вернуть версию драйвера
    Texnology — Технология вывода, их много, основные
    dt_Plotter — плоттер
    dt_RasPrinter — растровый принтер
    dt_Display — дисплей
    HorzSize — Горизонтальный размер листа (в мм)
    VertSize — Вертикальный размер листа (в мм)
    HorzRes — Горизонтальный размер листа (в пикселах)
    VertRes — Вертикальный размер листа (в пикселах)
    LogPixelX — Разрешение по оси Х в dpi (пиксел /дюйм)
    LogPixelY — Разрешение по оси Y в dpi (пиксел /дюйм)

    Кроме перечисленных еще около сотни, они позволяют узнать о принтере практически все.
    Параметры, возвращаемые по LogPixelX и LogPixelY очень важны — они
    позволяют произвести пересчет координат из миллиметров в пиксели
    для текущего разрешения принтера. Пример таких функций:

    Procedure TForm1.GetPrinterInfo; < Получить информацию о принтере >
    begin
    PixelsX:=GetDeviceCaps(printer.Handle,LogPixelsX);
    PixelsY:=GetDeviceCaps(printer.Handle,LogPixelsY);
    end;

    Function TForm1.PrinterCoordX(x:integer):integer; < переводит координаты из мм в пиксели >
    begin
    PrinterCoordX:=round(PixelsX/25.4*x);
    end;

    Function TForm1.PrinterCoordY(Y:integer):integer; < переводит координаты из мм в пиксели >
    begin
    PrinterCoordY:=round(PixelsY/25.4*Y);
    end;

    Printer.Canvas.TextOut(PrinterCoordX(30), PrinterCoordY(55),
    ‘Этот текст печатается с отступом 30 мм от левого края и ‘+
    ’55 мм от верха при любом разрешении принтера’);

    Данную методику можно с успехом применять для печати картинок — зная размер картинки можно пересчитать ее размеры в пикселах для текущего разрешения принтера, масштабировать, и затем уже распечатать. Иначе на матричном принтере (180 dpi) картинка будет огромной, а на качественном струйнике (720 dpi) — микроскопической.

    Секреты печати из программы на delphi

    Delphi: заметки программиста. Часть 2

    © Валерий Фаронов
    Статья была опубликована в КомпьютерПресс #5 2001(www.cpress.ru)

    Печать в Delphi

    Объект Printer автоматически создается в случае, если в программе указана ссылка на модуль Printers. Этот объект предоставляет программисту все необходимое для того, чтобы научить приложение выводить данные на один из подключенных к компьютеру принтеров.

    Вывод на принтер в Windows ничем не отличается от вывода на экран: в распоряжение программиста предоставляется свойство Canvas объекта Printer, содержащее набор чертежных инструментов, и методы, свойственные классу TCanvas. Размер листа бумаги в пикселах определяют свойства Height и Width, а набор принтерных шрифтов – свойство Fonts.

    Существует множество способов печати текста на принтере. Прежде всего следует назвать глобальную процедуру AssignPrn (она определена в модуле Printers), позволяющую использовать принтер как текстовый файл и печатать текстовые строки с помощью процедуры WriteLn. В листинге 1 (PrintText.dpr) приведен полный текст модуля, на форме которого расположены многострочный текстовый редактор Memo1 и четыре кнопки: для выбора текстового файла и ввода его содержимого в редактор, для выбора нужного шрифта отображения/печати документа, для инициации процесса печати и для завершения работы программы.

    Описанный способ печати — самый примитивный: с его помощью невозможно вывести линии, разделяющие колонки или строки, трудно форматировать текст, вставлять заголовки, номера страниц и т.д.

    Значительно более гибкие средства обеспечивает свойство Printer.Canvas. Покажем, как с его помощью можно напечатать текст, содержащийся в редакторе Memo1 (PrintText.dpr, листинг 2):

    Как можно увидеть, прямое обращение к чертежным инструментам свойства Canvas требует от программиста значительно больших усилий, но зато предоставляет ему полный контроль над печатным изображением.

    Во многих случаях для печати документа и внесения в него элементарных средств форматирования (печать общего заголовка, заголовка на каждой странице, номеров страниц и т.п.) проще использовать специальные компоненты, расположенные на странице QReport палитры компонентов Delphi. Эти компоненты разработаны для создания отчетов по базам данных, но могут с успехом использоваться и для печати обычных документов (PrintText.dpr).

    Наконец, очень хороших результатов можно достичь, используя специализированные средства просмотра/печати документов, как, например, текстовый процессор MS Word.

    Печать изображений может показаться очень сложным делом, однако свойство Printer.Canvas содержит метод:

    procedure StretchDraw(const Rect: TRect; Graphic: TGraphic );

    который легко справляется с этой задачей. При обращении к нему в качестве первого параметра указывается прямоугольная область, отводимая на поверхности листа для распечатки изображения, а в качестве второго — объект класса TGraphic, в котором хранится изображение, например:

    with Printer do
    begin
    BeginDoc;
    Canvas.StretchDraw(Canvas.ClipRect, Image1.Picture.Graphic);
    EndDoc;
    end;

    Отображение файла в память

    Для работы с файлом динамической подкачки страниц виртуальной памяти в Windows 32 используется механизм отображения файлов в адресное пространство приложения. Соответствующие функции API доступны любому приложению и могут применяться к любому файлу (кстати, таким способом загружаются в адресное пространство процесса исполняемые файлы и DLL). В результате отображения приложение может работать с файловыми данными как с размещенными в динамической памяти. В большинстве случаев такая возможность не только повышает скорость работы с данными, но и предоставляет программисту уникальные средства обработки сразу всех записей файла. Например, он может с помощью единственного оператора проверить, входит ли заданный образец поиска в какую-либо строку текстового файла.

    Отображение файла осуществляется в три приема. Вначале файл создается обращением к функции:

    function FileCreate (FileName: String): Integer;

    или открывается с помощью:

    function FileOpen (const FileName: String; Mode: LongWord): Integer;

    В обеих функциях FileName — имя файла, возможно, с маршрутом доступа. Параметр Mode определяет режим доступа к файлу и может принимать одно из следующих значений: fmOpenRead — только чтение; fmOpenWrite — только запись; fmOpenReadWrite — чтение и запись. С помощью операции or эти константы можно комбинировать с одной из следующих нескольких функций, регулирующих совместный доступ к файлу: fmShareExclusive — совместный доступ запрещен; fmShareDenyWrite — другим приложениям запрещается запись; fmShareDenyRead — другим приложениям запрещается чтение; fmSchareDenyNone — совместный доступ неограничен. Обе функции возвращают дескриптор созданного (открытого) файла или 0, если операция оказалась неудачной.

    На втором этапе создается объект отображения в память. Для этого используется функция:

    function CreateFileMapping (hFile: THandle; lpFileMappingAttributes: PSecurityAttributes; flProtect, dwMaximumSizeHigh, dwMaximumSizeLow: DWord; lpName: PChar): THandle;

    Здесь hFile — дескриптор файла; lpFileMappingAttributes — указатель на структуру, в которой определяется, может ли создаваемый объект порождать дочерние объекты (обычно не может — NIL); flProtect — определяет тип защиты, применяемый к окну отображения файла (см. об этом ниже); dwMaximumSizeHigh, dwMaximumSizeLow — соответственно старшие и младшие 32 разряда числа, содержащего размер файла (если вы будете отображать файлы длиной до 4 Гбайт, поместите в dwMaximumSizeHigh 0, если в dwMaximumSizeLow — длину файла; а если оба параметра равны 0, то размер окна отображения равен размеру файла); lpName — имя объекта отображения или NIL.

    Параметр flProtect задает тип защиты, применяемый к окну просмотра файла, и может иметь одно из следующих значений: PAGE_READONLY — файл можно только читать (файл должен быть создан или открыт в режиме fmOpenRead); PAGE_READWRITE — файл можно читать и записывать в него новые данные (файл открывается в режиме fmOpenReadWrite); PAGE_WRITECOPY — файл открыт для записи и чтения, однако обновленные данные сохраняются в отдельной защищенной области памяти (отображенные файлы могут разделяться приложениями, в этом режиме каждое приложение сохраняет изменения в отдельной области памяти или участке файла подкачки); файл открывается в режиме fmOpenReadWrite или fmOpenWrite; (этот тип защиты нельзя использовать в Windows 95/98). С помощью операции or к параметру flProtect можно присоединить такие атрибуты: SEC_COMMIT — выделяет для отображения физическую память или участок файла подкачки; SEC_IMAGE — информация об атрибутах отображения берется из образа файла; SEC_NOCASHE — отображаемые данные не кэшируются и записываются непосредственно на диск; SEC_RESERVE — резервируются страницы раздела без выделения физической памяти.

    Функция возвращает дескриптор объекта отображения или 0, если обращение было неудачным.

    Наконец, на третьем этапе создается окно просмотра, то есть собственно отображение данных в адресное пространство программы.

    function MapViewOfFile(hFileMappingObject: THandle;dwDesiresAccess: DWord; dwFileOffsetHigh, dwFileIffsetLow, dwNumberOfBytesToMap: DWord): Pointer;

    Здесь hFileMappingObject — дескриптор объекта отображения; dwDesiresAccess — определяет способ доступа к данным и может иметь одно из следующих значений: FILE_MAP_WRITE — разрешает чтение и запись (при этом в функции CreateFileMapping должен использоваться атрибут PAGE_READWRITE); FILE_MAP_READ — разрешает только чтение (в функции CreateFileMapping должен использоваться атрибут PAGE_READONLY или PAGE_READWRITE); FILE_MAP_ALL_ACCESS — то же, что и FILE_MAP_WRITE; FILE_MAP_COPY — данные доступны для записи и чтения, однако обновленные данные сохраняются в отдельной защищенной области памяти (в функции CreateFileMapping должен использоваться атрибут PAGE_WRITECOPY); dwFileOffsetHigh, dwFileIffsetLow — определяют соответственно старшие и младшие разряды смещения от начала файла, начиная с которого осуществляется отображение; dwNumberOfBytesToMap — определяет длину окна отображения (0 — длина равна длине файла). Функция возвращает указатель на первый байт отображенных данных или NIL, если обращение к функции оказалось безуспешным.

    После использования отображенных данных ресурсы окна отображения нужно освободить функцией:

    function UnMapViewOfFile(lpBaseAddress: Pointer): BOOL;

    единственный параметр обращения к которой должен содержать адрес первого отображенного байта, то есть адрес, возвращаемый функцией MapViewOfFile. Закрытие объекта отображения и самого файла осуществляется обращением к функции:

    function CloseHandle(hObject: THandle).

    В листинге 3 приводится текст модуля (File­­InMemory.dpr), который создает окно, показанное на рис. 1. Проект создает дисковый файл, состоящий из 100 тыс. случайных вещественных чисел (можно выбрать другую длину файла, если изменить значение редактора Длина массива). Файл с именем test.dat создается путем отображения файла в память (кнопка Память) и традиционным способом (кнопка Файл). В обоих случаях показывается время счета. Чем больше частота процессора и объем свободной оперативной памяти, тем больше будет разница во времени (листинг 3).

    Компонент Timer (таймер) служит для отсчета интервалов реального времени. Его свойство Interval определяет интервал временив миллисекундах , который должен пройти от включения таймера до наступления события OnTimer. Таймер включается при установке значения True в его свойство Enabled. Единожды включенный таймер все время будет возбуждать события OnTimer до тех пор, пока его свойство Enabled не примет значения False.

    Следует учесть, что в силу специфики реализации стандартного аппаратного таймера IBM-совместимого компьютера минимальный реально достижимый интервал отсчета времени не может быть меньше 55 мс (этот интервал называется тиком), более того, любой интервал времени, отсчитываемый с помощью таймера, всегда кратен 55 мс. Чтобы убедиться в этом, проведите эксперимент, в котором подсчитывается среднее время между двумя срабатываниями таймера (Timer.dpr):

    1. Начните новый проект с пустой формой и положите на нее компонент TTimer.
    2. Установите в свойство Enabled таймера значение False.
    3. Напишите такой модуль главной формы (листинг 4):

    Необходимость нескольких (MaxCount) срабатываний для точного усреднения результата связана с тем, что системные часы обновляются каждые 55 мс. После запуска программы и ввода 1 как требуемого периода срабатывания в редакторе mmOutput вы увидите строку

    Задано 1 ms. Получено 55 ms.

    в которой указывается, какое реальное время разделяет два соседних события OnTimer. Если вы установите период таймера в диапазоне от 56 до 110 мс, в строке будет указано 110 ms и т.д. (в силу дискретности обновления системных часов результаты могут несколько отличаться в ту или иную сторону).

    В ряде практически важных областей применения (при разработке игр, в системах реального времени для управления внешними устройствам и т.п.) интервал 55 мс может оказаться слишком велик. Современный ПК имеет мультимедийный таймер, период срабатывания которого может быть от 1 мс и выше, однако этот таймер не имеет компонентного воплощения, поэтому для доступа к нему приходится использовать функции API.

    Общая схема его использования такова. Сначала готовится процедура обратного вызова (call back) с заголовком:

    procedure TimeProc(uID, uMsg: UINT; dwUser, dw1, dw2: DWORD); stdcall;

    Здесь uID — идентификатор события таймера (см. об этом ниже); uMsg — не используется; dwUser — произвольное число, передаваемое процедуре в момент срабатывания таймера; dw1, dw2 — не используются.

    Запуск таймера реализуется функцией:

    function timeSetEvent(uDelay, uResolution: UINT; lpTimeProc: Pointer; dwUser: DWORD; fuEvent: UINT): UINT; stdcall; external ‘winmm.dll’;

    Здесь uDelay — необходимый период срабатывания таймера (в мс); uResolution — разрешение таймера (значение 0 означает, что события срабатывания таймера будут возникать с максимально возможной частотой; в целях снижения нагрузки на систему вы можете увеличить это значение); lpTimeProc — адрес процедуры обратного вызова; dwUser — произвольное число, которое передается процедуре обратного вызова и которым программист может распоряжаться по своему усмотрению; fuEvent — параметр, управляющий периодичностью возникновения события таймера: TIME_ONESHOT (0) — событие возникает только один раз через uDelay миллисекунд; TIME_PERIODIC (1) — события возникают периодически каждые uDelay мс. При успешном обращении функция возвращает идентификатор события таймера и 0, если обращение было ошибочным.

    Таймер останавливается, и связанные с ним системные ресурсы освобождаются функцией:

    function timeKillEvent(uID: UINT): UINT; stdcall; external ‘winmm.dll’;

    Здесь uID — идентификатор события таймера, полученный с помощью timeSetEvent.

  • Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL