Китай |
Рисование графических примитивов средствами GDI+
Упражнение 3.Разделение кода вывода на экран и печать
Усовершенствуем нашу последнюю программу так, чтобы сделать ее более универсальной, разделив код вывода на экран и печать. На данном этапе программа будет рисовать крестик, но в дальнейшем разработанный класс можно будет наследовать и переопределять в наследнике функции рисования.
- Вот как будет выглядеть усовершенствованный класс
using System; using System.Drawing; using System.Windows.Forms; using System.Drawing.Printing; namespace Test { public class PrintableForm : Form { public PrintableForm() { this.Text = "Форма, готовая наследоваться"; this.BackColor = System.Drawing.SystemColors.Window; this.ForeColor = System.Drawing.SystemColors.WindowText; this.ResizeRedraw = true; } protected override void OnPaint(PaintEventArgs e) { // Вывод на экран // Наша функция, см. ниже (зри в корень!) DoPage(e.Graphics, ForeColor, ClientSize.Width, ClientSize.Height); 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; // Измеряем область печати SizeF szf = printgr.VisibleClipBounds.Size; // Вывод на принтер DoPage(printgr, Color.Black, (int)szf.Width, (int)szf.Height); } // Создадим виртуальный метод с возможностью замещения в наследнике protected virtual void DoPage(Graphics graphics, Color color, int cx, int cy) { Pen pen = new Pen(color); // В этом варианте замещаемой функции рисуем крестик graphics.DrawLine(pen, 0, 0, cx - 1, cy - 1); graphics.DrawLine(pen, cx - 1, 0, 0, cy - 1); } } }Листинг 16.12. Форма, готовая наследоваться (PrintableForm.cs)
Здесь мы часть кода выделили в отдельную функцию DoPage(), которая выводит графическую информацию и на форму, и на принтер. Ей передают объект Graphics, цвет и размеры области вывода функции OnPaint() - вывод на форму, и prndoc_PrintPage() - вывод на принтер. Каждая вызывающая функция передает свои значения аргументов. Функция OnClick() инициирует срабатывание обработчика печати на принтер. Функцию DoPage() мы сделали защищенной (доступной только наследникам) и виртуальной (с возможностью замещения в наследниках), чтобы ее можно было заместить в наследующих классах для рисования других фигур.
Теперь в следующих программах этот класс можно использовать как базовый вместо класса Form, поскольку он является расширением Form, удобным для нас.
- Постройте форму и проверьте функциональность. Экранная часть должна выглядеть примерно так
Упражнение 4. Рисование ломаных линий
Если использовать функцию рисования прямой, например, для изображения прямоугольника по краю клиентской области формы, то потребуется четыре ее вызова
graphics.DrawLine(pen, 0, 0, cx - 1, 0); graphics.DrawLine(pen, cx - 1, 0, cx - 1, cy - 1); graphics.DrawLine(pen, cx - 1, cy - 1, 0, cy - 1); graphics.DrawLine(pen, 0, cy - 1, 0, 0);
Здесь конечная точка текущего вызова должна повторяться как начальная точка следующего.
Для экономии кода в класс Graphics включен метод DrawLines() рисования нескольких соединенных линий, в совокупности называемых ломаной. Приведем пример программы, очерчивающей границу клиентской области. В ней мы будем наследовать разработанное нами расширение PrintableForm вместо класса Form. Обратите внимание, что в новой форме мы не устанавливаем все ее свойства заново - они унаследованы из класса PrintableForm
using System; using System.Drawing; using System.Windows.Forms; namespace Test { public class BoxingTheClient : PrintableForm { public BoxingTheClient() { this.Text = "Очерчивание границы клиентской области"; this.Width += 80; } // Перегруженная функция базового класса PrintableForm protected override void DoPage(Graphics graphics, Color color, int cx, int cy) { Point[] apoint = { new Point(0, 0), new Point(cx - 1, 0), new Point(cx - 1, cy - 1), new Point(0, cy - 1), new Point(0, 0) }; graphics.DrawLines(new Pen(color, 10), apoint); } } }Листинг 16.13. Очерчивание границы клиентской области (BoxingTheClient.cs)
Результатом работы кода будет