Многостраничный
вывод
Процесс многостраничной
печати основан на небольшой хитрости: если процедура обработки события Pri ntPage
задает свойству HasMorePages объекта Pri ntPageEventArgs значение True, то объект
PrintDocument узнает о наличии дополнительных страниц для печати и автоматически
инициирует заново событие PagePri n't.
Проблемы,
возникающие при многостраничной печати, имеют мало общего с самой печатью. Они
присущи любому сложному выводу на графической поверхности: программа должна
помнить обо всем. Предположим, вы хотите написать небольшую программу
для вывода содержимого текстового поля или текстового файла. В псевдокоде все
выглядит просто.
- Прочитать строку из
поля или из файла.
- Не превышает ли длина
строки предельное допустимое значение? Если превышает, разбить на несколько
фрагментов.
- Помещаются ли эти фрагменты
на текущей странице?
- Если помещаются, напечатать
их функцией DrawString начиная с текущей позиции. Если не помещаются, напечатать
сколько удастся, начать новую страницу и вывести на ней остальные фрагменты.
- Повторить процесс
до тех пор, пока не будут обработаны все строки текстового поля или файла.
Однако проверка
возможности размещения новой строки на странице не имеет ничего общего с печатью;
в ней используются различные метрики, вычисляемые на основании ширины и высоты
текстовой строки. В свою очередь, эти параметры зависят от семейства и размера
используемого шрифта. К счастью, вы можете положиться на такие методы, как MeasureStri
ng; эти методы используют метрики, связанные с текущим контекстом устройства.
Объект PrintPageEventArgs
содержит два ReadOnly-свойства, при помощи которых можно получить информацию
о размерах страницы. Значения обоих свойств задаются в сотых долях дюйма.
В свойстве
PageSettings объекта PrintPageEventArgs хранится дополнительная информация.
В табл. 8.2 перечислены важнейшие свойства класса PageSetti ngs (большинство
принтеров позволяет читать эти свойства, но не все принтеры поддерживают запись).
Таблица
8.2. Свойства класса PageSettings
Свойство |
Описание |
||
Bounds | Возвращает размеры страницы с учетом возможной альбомной ориентации печати. Свойство доступно только для чтения | ||
Color | Признак печати страницы в цвете. Логическое свойство, доступное для чтения и записи | ||
Landscape | Ориентация страницы. Логическое свойство, доступное для чтения и записи | ||
Margins | Размеры полей (по умолчанию равны 1 дюйму). Свойство доступно для чтения и записи | ||
PaperSize | Размеры бумаги. Свойство доступно для чтения и записи | ||
PaperSource | Источник бумаги. Свойство доступно для чтения и записи | ||
PrinterResolution | Разрешение принтера. Некоторые принтеры поддерживают нестандартные разрешения, другие позволяют выбирать только между черновой и качественной печатью. Свойство доступно для чтения и записи | ||
PrinterSettings | Настройка принтера для данной страницы. Свойство доступно для чтения и записи | ||
Например,
многие принтеры не позволяют печатать ближе, чем в 0,5 дюйма от края бумаги.
В этом случае минимальные поля задаются следующей командой:
е.PageSettings.Margins
= New System.Drawing.Printing.Margins(50.50.50.50)
Следующий
фрагмент начинает печать с левого верхнего края области, ограниченной полями:
Dim g As Graphics
g = e.Graphics
g.DrawImage(PictureBoxl.Image,
e.MarginBounds.Left, e.MarginBounds.Top)
Элемент
PrintDialog и конфигурация печати
Пользователь
программы должен иметь возможность выбрать принтер и внести другие изменения
в конфигурацию печати. Такую возможность предоставляет элемент PrintDialog.
В программе соответствующий фрагмент может выглядеть примерно так:
Private Sub Buttonl_Click(ByVal sender As System.Object,_
ByVal e As System.EventArgs)Handles
Buttonl.Click
Dim PhntDialogl
As New PrintDialog()
' Следующая
строка необходима, потому что информация
' объекта PrinterSettings
нужна объекту PrintDialog перед выводом
PrintDialogl.Document
= PrintDocumentl
If PrintDialogl.ShowDialog()
= DialogResult.OK Then
PrintDocumentl.
PrintO
End If
End Sub
Выделенная
строка сообщает экземпляру PrintOialog, что связанный с ним документ должен
быть экземпляром PrintDocumentl (предполагается, что этот объект был создан
ранее). Эта строка необходима, поскольку элемент PrintDialog должен получить
некоторые параметры печати (в виде объекта Pri ntSetti ngs) перед выводом
окна. Чтобы передать ему эту информацию, проще всего назначить объект PrintDocument
свойству Document.
Самостоятельное
программирование печати
Во многих
случаях вполне достаточно элемента Pri ntDialog и автоматически сгенерированного
кода, но время от времени требуется реализовать нестандартные возможности печати.
Для этого необходимо написать процедуру со следующей сигнатурой:
Private Sub ProcedureToDoThePrinting(ByVal Sender As Object,_
ByVal e As System.Drawing.Printing.PrintPageEventArgs)
Затем процедура
при помощи делегата подключается к событию PrintPage класса PrintDocument. Например,
для вызова объекта aPrintDocument класса PrintDocument с приведенной выше процедурой
aPri ntDocument_PrintPage используется команда следующего вида:
AddHandler aPrintDocument.PrintPage,
AddressOf Me.aPrintDocument_PrintPage
В следующем
фрагменте показано, как выглядит возможная реализация печати в обработчике команды
меню Print:
Private Sub mnuPrint_Click(ByVal sender As System.Object,_
ByVal e As System.EventArgs)Handles
mnuPrint.Click
Dim aPrintDocument
As New PrintDocument()
AddHandler aPrintDocument.PrintPage.
AddressOf Me.aPrintDocument_PrintPage
aPrintDocument.Print()
End Sub
Рис.
8.25. Режим предварительного просмотра
Предварительный
просмотр
Печать простейших
документов в VB .NET требует несколько больших усилий, чем в VB6, зато режим
предварительного просмотра реализуется гораздо проще. Для этого от вас потребуется
лишь назначить объект PrintDocument свойству Document экземпляра PrintPrevl
ewDialog. Так, следующий фрагмент почти полностью совпадает с кодом, приведенным
выше, однако он реализует предварительный просмотр вместо вывода на принтер.
Результаты его выполнения показаны на рис. 8.25:
Private Sub
btnPreview_Click(ByVal sender As System.Object.
ByVal e As System.EventArgs)
Handles btnPreview.Click
Dim PrintPreviewDialogl
As New PrlntPreviewDialog()
PrintPreviewDlalogl.Document
= PrintDocumentl
If PrintPreviewDialogl.ShowDialog() = DialogResult.OK Then
PrintDocumentl.Print()
End If
End Sub