Опубликован: 11.09.2006 | Доступ: свободный | Студентов: 7608 / 459 | Оценка: 4.26 / 3.45 | Длительность: 30:46:00
ISBN: 978-5-9556-0080-2
Лекция 6:

Работа с печатью и изображениями

Печать содержимого PictureBox

Теперь займемся печатью изображений, помещенных в PictureBox. Добавляем на форму элементы PrintDocument, PageSetupDialog, PrintPreviewDialog и PrintDialog. На этот раз мы не будем настраивать визуально свойства этих элементов. Создаем обработчиков пунктов меню, в которых просто вызываем диалоговые окна:

private void mnuPageSetup_Click(object sender, System.EventArgs e)
  {
    PageSetupDialog diag = new PageSetupDialog();
    diag.Document = printDocument1;
    diag.ShowDialog();
  }
  private void mnuPreview_Click(object sender, System.EventArgs e)
  {
    PrintPreviewDialog diag = new PrintPreviewDialog();
    diag.Document = printDocument1;
    diag.ShowDialog();
  }
  private void mnuPrint_Click(object sender, System.EventArgs e)
  {
    PrintDialog diag = new PrintDialog();
    diag.Document = printDocument1;
    if (diag.ShowDialog() == DialogResult.OK)
    {
      printDocument1.Print();
    }
    
  }
Листинг 6.9.

Обратите внимание на свойство диалоговых окон Document — мы программно устанавливаем значение printDocument1. Переключаемся в режим дизайна, выделяем объект printDocument1 и в окне Properties дважды щелкаем в поле события PrintPage:

private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
    {
}

Дальнейший код будет относиться к этому обработчику. Проверяем наличие изображения в pictureBox1:

if (pictureBox1.Image == null)
  {
    e.Cancel = true;
    return;
  }

Определяем печатную область страницы:

float leftMargin = e.MarginBounds.Left;
float rightMargin = e.MarginBounds.Right;
float topMargin = e.MarginBounds.Top;
float bottomMargin= e.MarginBounds.Bottom;
float printableWidth = e.MarginBounds.Width;
float printableHeight = e.MarginBounds.Height;

Cоздаем экземпляр graph класса Graphics:

Graphics graph = e.Graphics;

В документе, формируемом для печати, не содержится текста — ведь мы имеем дело с изображением. Но интересно будет выводить на печать строку, указывающую, к примеру, размер изображения. Для этого создадим экземпляр font класса Font:

Font font= new Font("Comic Sans MS", 16); 
//Определяем высоту шрифта
float fontHeight = font.GetHeight(graph);
//Определяем размер пробелов 
float spaceWidth = graph.MeasureString(" ", font).Width;

Определяем область, в которую будет вписываться изображение; размер наибольшей стороны изображения составляет 90% от кратчайшей стороны листа:

float imageLength;
float Xposition = leftMargin;
float Yposition = topMargin + fontHeight;
if (printableWidth < printableHeight)
  {
    imageLength = printableWidth * 90/100;
    Yposition += imageLength;
  }
  else
  {
    imageLength = printableHeight * 90/100;
    Xposition += imageLength + spaceWidth;
  }

Выводим изображение в области rectImage:

Rectangle rectImage= new Rectangle((int)leftMargin + 1, 
(int)topMargin + 1, (int)imageLength,(int)imageLength);
graph.DrawImage(pictureBox1.Image,(int)leftMargin + 1,  
(int)topMargin + 1, (int)imageLength,(int)imageLength);

Определяем область rectText и выводим в нее строку с указанием размера файла (используется метод PrintTextString ):

RectangleF rectText = new RectangleF(Xposition, Yposition, rightMargin -
- Xposition,  bottomMargin - Yposition);
PrintText (graph, font,"Размер изображения: ", Convert.ToString
(pictureBox1.Image.Size), ref rectText);

}

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

protected void PrintText( Graphics graph,   Font font,  string name,  string text,  ref RectangleF rectText)
  {
    // Определяем размеры печатной области для текста:
    float leftMargin = rectText.Left;
    float rightMargin = rectText.Right;
    float topMargin = rectText.Top;
    float bottomMargin = rectText.Bottom;
    //Определяем высоту текста и координаты, где он будет выводиться:
    float fontHeight = font.GetHeight(graph);
    float Xposition = rectText.Left;
    float Yposition = topMargin + fontHeight;
    //Определяем ширину текста и размер пробелов
    float spaceWidth = graph.MeasureString(" ",   font).Width;
    float nameWidth  = graph.MeasureString(name, font).Width;
    graph.DrawString(name, font,
    Brushes.Black, new PointF(Xposition, Yposition));
    leftMargin += nameWidth + spaceWidth;
    Xposition = leftMargin;
    // Формируем несколько строк для текста  в случае,
    // если он не будет умещаться на одной строке
    string[] words
      = text.Split(" \r\t\n\0".ToCharArray());
    foreach (string word in words)
    {
      float wordWidth = graph.MeasureString(
        word, font).Width;
      if (wordWidth == 0.0)
        continue;
      if (Xposition + wordWidth > rightMargin)
      {
        // Начало с новой строки
        Xposition = leftMargin;
        Yposition += fontHeight;
        if (Yposition > bottomMargin)
        {            
          break;
        }
      }
      graph.DrawString(word, font,Brushes.Black,  new PointF(Xposition, Yposition));
      Xposition += wordWidth;
    }
    // Исключаем область, на которую был выведен текст, из области печати 
    //для избежания наложения текста и рисунка
    rectText.Y = Yposition;
    rectText.Height = bottomMargin - Yposition;
  }
Листинг 6.10.

Запускаем приложение. При выборе книжной ориентации страницы рисунок вписывается с сохранением своих пропорций (рис. 6.14), затем выводится на печать (рис. 6.15).

Предварительный просмотр приложения Picture Viewer

Рис. 6.14. Предварительный просмотр приложения Picture Viewer
Вывод рисунка  в окно виртуального принтера программы pdfFactoryPro

Рис. 6.15. Вывод рисунка в окно виртуального принтера программы pdfFactoryPro

В конце лекции приводится полный листинг приложения Picture Viewer, а исходный проект имеется на диске, прилагаемом к книге (Code\Glava6\ Picture Viewer).

Елена Дьяконова
Елена Дьяконова

При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: 

Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll

Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан.

Затем:

Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll

Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз.

Александр Сороколет
Александр Сороколет

Свойство WindowState формы blank Maximized. Не открывается почемуто на всё окно, а вот если последующую форму бланк открыть уже на макс открывается :-/