Опубликован: 13.07.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 16:

Рисование графических примитивов средствами GDI+

Упражнение 2. Использование некоторых возможностей печати документа

Поставим простейшую задачу распечатать клиентскую область формы на стандартно настроенный принтер. Чтобы не отвлекаться на создание пользовательского интерфейса для управления печатью (пункт меню, кнопка и т.д.) перегрузим метод OnClick() класса Control, который наследуется формой. Этот метод инициируется всякий раз при щелчке на форме любой кнопкой мыши.

Чтобы печатать на принтере по умолчанию, нужно создать объект типа System.Drawing.Printing.PrintDocument

PrintDocument prndoc = new PrintDocument();

Это класс содержит много методов, свойств и событий

На данном этапе нам понадобятся только одно свойство, один метод и одно событие, а именно

  • prndoc. DocumentName (public string DocumentName [ get, set ]) - строковое свойство, в которой устанавливается идентификатор задания в очереди печати. Обычно программа, работающая с документом, заносит в это свойство свое имя (текст заголовка окна программы).
  • PrintPage - событие, в обработчике которого будем использовать вызовы на вывод графической информации.
  • prndoc. Print() - метод начала печати. Этот метод возвращает управление не сразу - некоторое время отображается информационное окно с именем документа и кнопкой, позволяющей отменить задание печати.

В результате исполнения метода Print() также вызывается обработчик события PrintPage с передаваемыми ему параметрами. Значением первого параметра Object является ранее созданный объект prndoc класса PrintDocument. Второй параметр имеет тип PrintPageEventArgs, свойства которого предоставляют информацию о принтере, в том числе свойство Graphics. Это свойство является объектом и содержит информацию для страницы принтера, а не для клиентской области формы. Методы объекта Graphics выводят информацию на страницу принтера.

Если нужно напечатать несколько страниц, следует установить свойство HasMorePages переданного в обработчик объекта класса PrintPageEventArgs как true. Но в нашем примере будет печататься одна страница, поэтому оставим значение свойства HasMorePages по умолчанию (false) и обработчик события PrintPage сразу вернет управление.

Свойство ClientSize формы предоставляет размеры своей клиентской области в пикселах. Этого недостаточно для страницы принтера. Страница принтера определяется тремя разными областями:

  1. Полный размер страницы
  2. Область печати, заданная пользователем
  3. Предельная область печати, доступная принтеру или иному печатающему устройству

Полный размер страницы

Об этом содержатся сведения в свойстве PageBounds переданного в обработчик объекта класса PrintPageEventArgs. Его значением является структура Rectangle, чьи свойства X и Y равны нулю, а свойства Width и Height предаставляют размеры бумаги по умолчанию, выраженные в сотых долях дюйма. Например, для листа размером 8,5x11 дюймов значения свойств Width и Height объекта PageBounds равно 850x1100 единиц (сотых долей дюйма). Если в принтере задана альбомная, а не книжная ориентация страницы, то размеры будут равны 1100x850 единиц.

Область печати, заданная пользователем

Размер этой области близок к полному размеру страницы, за исключением полей, недоступных печатающей головке принтера. Ширина верхнего, правого, нижнего и левого полей может различаться. Значением свойства VisibleClipBounds объекта класса Graphics является структура RectangleF, предоставляющая размер установленной области печати страницы.

Свойства X и Y этой структуры устанавливаются в 0, а ее свойства Width и Height равны горизонтальному и вертикальному размерам установленной области печати страницы, выраженных в тех же единицах, что будут использованы и для рисования на странице принтера.

Предельная область печати

Эта область рассчитывается с учетом 1-дюймового отступа по периметру страницы и представляет собой границы, в пределах которых может печатать пользователь. Эта информация предоставляется свойством MarginBounds объекта PrintPageEventArgs в виде структуры Rectangle.

Пример кода программы

Цвета, видимые на экране, большей частью для принтера непригодны. Лучшим цветом для принтера является Color.Black, лучшее перо - Pens.Black, лучшая кисть - Brushes.Black. Это подходит для всех.

  • Вот программа, которая выводит в клиентскую область приглашение "Щелкни на форме для печати!" и начинает печатать на принтере после щелчка на клиентской области формы текст.
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Printing;
  
namespace Test
{
  public class HelloPrinter : Form
  {
    public HelloPrinter()
    {
      this.Text = "Простая программа печати";
      this.Width += 50;
      this.Height /= 2;
      this.BackColor = System.Drawing.SystemColors.Window;
      this.ForeColor = System.Drawing.SystemColors.WindowText;
      this.ResizeRedraw = true;
    }
  
    protected override void OnPaint(PaintEventArgs e)
    {
      Graphics graphics = e.Graphics;
      System.Drawing.StringFormat strfmt = new StringFormat();
      strfmt.Alignment = StringAlignment.Center;
      strfmt.LineAlignment = StringAlignment.Center;
      graphics.DrawString("Щелкни на форме для печати!", 
        Font, 
        new SolidBrush(ForeColor),
        RectangleF.FromLTRB(// Преобразовать из Left, Top, Right, Bottom
          this.ClientRectangle.Left,
          this.ClientRectangle.Top,
          this.ClientRectangle.Right,
          this.ClientRectangle.Bottom),
        strfmt);
  
      base.OnPaint (e);
    }
  
    protected override void OnClick(EventArgs e)
    {
      PrintDocument prndoc = new PrintDocument();
      prndoc.DocumentName = this.Text;
      // Делегат события печати
      // Создать вручную
      prndoc.PrintPage +=new PrintPageEventHandler(prndoc_PrintPage);
      prndoc.Print(); // Печать документа (инициирует событие PrintPage)
  
      base.OnClick (e);
    }
  
    private void prndoc_PrintPage(object sender, PrintPageEventArgs e)
    {
      Graphics printgr = e.Graphics;
      string message = "Привет студентам от Снеткова В.М.!";
      // Печатаем сообщение
      printgr.DrawString(message, 
        this.Font, Brushes.Black, 0, 0);
      // Измеряем текстовый блок с сообщением для начала линии
      SizeF szf = printgr.MeasureString(message, this.Font);
      // Проводим линию из нижнего правого угла текстового блока
      // до правого нижнего угла видимой области печати
      printgr.DrawLine(Pens.Black, szf.ToPointF(),
        printgr.VisibleClipBounds.Size.ToPointF());
    }
  }
}
Листинг 16.11. Простая программа печати (HelloPrinter.cs)

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

Иван Циферблат
Иван Циферблат
Россия, Таганрог, 36, 2000