Лабораторная работа №6
Графические возможности Visual C#. Построение графика функции.
Цель работы: Изучить основные возможности среды разработки для создания графических объектов. Познакомиться с базовым набором графических примитивов.
1. Теоретические сведения
1.1. ОСОБЕННОСТИ GDI+
Для рисования объектов в Windows Forms приложениях язык С# содержит очень богатый набор методов. Пространство имен Drawing содержит множество объектов, которые облегчают программисту работу с графикой. Специально для .NET платформы разработчики Microsoft разработали GDI+ библиотеку, значительно повысив возможности GDI
(Graphic Device Interface). GDI+ включает возможности рисования простейших объектов (линии, эллипсы...), рисование различных объектов 2D графики, отображение файлов различных графических форматов (bmp, jpeg, gif, wmf, ico, tiff...) и многое другое.
Перед началом рисования линий и фигур, вывода текста или отображения изображений с помощью библиотеки GDI+, необходимо создать графический объект. Графический объект представляет собой пространство для рисования и является объектом, используемым для создания изображения.
Для работы с графикой необходимо выполнить два действия:
Создать графический объект.
применить графический объект для рисования линий, фигур, вывода текста или отображения картинки.
Графический объект может быть создан различными способами:
Созданием ссылки на графический объект как часть аргументов PaintEventArgs события Paint для формы или объекта управления. Чаще всего этот метод используется, если необходимо запрограммировать рисование для нового объекта управления.
Вызовом метода CreateGraphics объекта управления или формы для размещения графического объекта на поверхности объекта управления или формы. Метод используется, если необходимо рисовать на форме или объекте управления, которые уже существуют.
Созданием графического объекта из любого объекта, являющегося изображением. Этот подход используется, когда необходимо изменить уже существующее изхображение.
1.2. Графический инструментарий
1.2.1 Пространства имен и классы
Весь графический инструментарий расположен в пространствах имен, перечисленных в табл. 2.1,
Таблица 2.1. Пространства имен для отрисовки изображений
Пространство |
Описание |
|
System.Drawing |
Предоставляет простые классы, такие как Pen (карандаш), Brush (кисть), Bitmap (изображение) и т. п. |
|
System.Drawing. Drawing2D |
Предоставляет дополнительные классы, такие как Adjustable-ArrowCap (реализует наконечники для линий), Liner-GradientBrush (реализует градиентную заливку), Matrix (реализует аффинные преобразования изображений) и др. |
|
System.Drawing. Imaging |
Предоставляет дополнительные классы для работы с изображениями, такие как ColorMap (поверхность для отображения рисунков с корректируемыми цветами), ColorMatrix (матрица 5x5 для коррекции цветов), Metafile (класс для работы с метафайлами) и др. |
|
System.Drawing. Printing |
Содержит классы для работы с принтером, такие как Margins (управляет полями), PageSettings (задает параметры для одной страницы), PreviewPageInfo (содержит информацию для предварительного просмотра изображений) и др. |
|
System.Drawing. Text |
Содержит классы для работы с текстом, такие как FontCollection (базовый класс для создания коллекции шрифтов), installedFontCollection (коллекция установленных в системе шрифтов) и др. |
1.2.2 Класс Graphics
В CTS для отрисовки компонентов предлагаются классы Pen, Brush, Font, Region, Bitmap, Palette и Graphics. Каждый из них может работать только в рамках заданного контекста графического устройства. Графическими устройствами являются дисплей, принтер, плоттер и т. п. Контекст графического устройства (далее — просто контекст устройства) представляет собой набор параметров, характеризующих это устройство и использующихся для вывода изображений, текста, линий и других графических объектов.
Класс Graphics определяет набор свойств и методов для отрисовки различных изображений на поверхности контекста устройства. Он передается как параметр вызова обработчикам события Paint, и в этом случае его не нужно создавать или уничтожать. Для самостоятельного создания объекта Graphics могут использоваться его методы FromXXX (см. далее). В табл. 2.2 и 2.3 представлены наиболее важные свойства и методы класса.
Таблица 2.2. Свойства класса Graphics
Свойство |
Описание |
public Region Clipfget; set;} |
Определяет область отрисовки |
public RectangleF ClipBounds{get;}; |
Возвращает вещественные координаты области отрисовки |
public enum CompositingMode = (SourseCopy, SoureseOver); public CompositingMode CompositingMode{get; set;}; |
Определяет, будут ли пикселы изображения заменять (SourseCope) собой пикселы фона или взаимодействовать с ними |
public enum CompositingQuality = (AssumeLiner, Default, HighQuality, Highspeed, Invalid); public CompositingQuality CompositingQuality{get; set;} |
Определяет качество отрисовки: AssumeLiner — допускается линеаризация значений; Default — умалчиваемое качество; HighQuality — высокое качество, низкая скорость; Highspeed — низкое качество, высокая скорость; invalid — неправильное значение качества |
public float DPiX{get;} |
Горизонтальная разрешающая способность контекста |
public float DPiY{get;} |
Вертикальная разрешающая способность контекста |
public enum InterpolationMode = (Bicubic, Bilinear, Default, High, HighQualityBicubic, HighQualityBilinear, Invalid, Low) ; public InterpolationMode InterpolationMode{get; set;} |
Определяет режим интерполяции (изменение цвета между двумя точками изображения): Bicubic — бикубическая интерполяция; Bilinear — билинейная интерполяция; Default — умалчиваемая интерполяция; High — интерполяция высокого качества; HighQualityBicubic — бикубическая интерполяция высокого качества; HighQualityBilinear — билинейная интерполяция высокого качества; Invalid — неправильное значение; Low — интерполяция низкого качества |
public bool IsClipEmpty{get;} |
Содержит true, если область отрисовки пуста |
public bool IsVisibleClipEmpty{get;} |
Содержит true, если видимая часть области отрисовки пуста |
public Matrix Transform{get; set; } |
Содержит матрицу преобразования координат отрисовки |
Таблица 2.3. Методы класса Graphics
Метод |
Описание |
public GraphicsContainer BeginContainer(); |
Начинает работу с графическим контейнером (информацию о перегруженных методах см. в справочной службе) |
public void Clear(Color Col); |
Очищает поверхность отрисовки и заливает ее указанным цветом |
public void Dispose(); |
Освобождает все ресурсы, связанные с объектом Graphics |
public void DrawArc(Pen P, Rectangle R, Single Start, Single Finish); |
Вычерчивает пером Р дугу эллипса, вписанного в прямоугольник R, в секторе, ограниченном углами Start и Finish (информацию о перегруженных методах см. в справочной службе) |
public void DrawBezier(Pen P, Point Tl, Point T2, Point T3, Point T4); |
Вычерчивает кривую Безье, проходящую по указанным точкам (информацию о перегруженных методах см. в справочной службе) |
public void DrawClosedCurve (Pen P. Point[] Points); |
Вычерчивает замкнутую кривую, проходящую по заданным точкам (информацию о перегруженных методах см. в справочной службе) |
public void DrawCurve(Pen P, Point[] Points); |
Вычерчивает кривую, проходящую по заданным точкам (информацию о перегруженных методах см. в справочной службе) |
public void DrawEllipse(Pen P, Rectangle Rect); |
Вычерчивает эллипс, вписанный в прямоугольник Rect (информацию о перегруженных методах см. в справочной службе) |
public void DrawIcon(Icon Ic, Rectangle Rect); |
Вычерчивает значок 1с в области Rect (информацию о перегруженных методах см. в справочной службе) |
public void DrawImage(Image Im, Rectangle Rect); |
Вычерчивает изображение im в области Rect (информацию о перегруженных методах см. в справочной службе) |
public void DrawLine(Pen P, Point Tl, Point T2); |
Вычерчивает линию между указанными точками (информацию о перегруженных методах см. в справочной службе) |
public void DrawLines(P: Pen; Points: array of Point); |
Вычерчивает линии, соединяющие указанные точки (информацию о перегруженных методах см. в справочной службе) |
public void DrawPath(Pen P, GraphicsPath Path); |
Вычерчивает пером р объект Path |
public void DrawPie(Pen P, Rectangle Rect, int StartAngle, int FinishAngle); |
Вычерчивает сектор эллипса, вписанного в прямоугольник Rect, ограниченный радиальными лучами StartAngle, FinishAngle (информацию о перегруженных методах см. в справочной службе) |
public void DrawPolygon(Pen P, Point[] Points); |
Вычерчивает полигон — замкнутую ломанную линию, соединяющую заданные точки (информацию о перегруженных методах см. в справочной службе) |
public void DrawRectangle(Pen P, Rectanle Rect); |
Вычерчивает прямоугольник (информацию о перегруженных методах см. в справочной службе) |
public void DrawString(string S, Font F, Brush B, Single Start); |
Выводит строку S текста: F — шрифт; в — кисть; start — начальная точка (информацию о перегруженных методах см. в справочной службе) |
public void EndContainer ( GraphicsContainer Container); |
Заканчивает работу с графическим контейнером |
public void ExcludeClip( Rectangle Rect); |
Исключает из области отрисовки прямоугольник Rect (информацию о перегруженных методах см. в справочной службе) |
public void FillClosedCurve ( Brush B, Point[] Points); |
Закрашивает кистью В внутреннюю область замкнутой кривой, проходящей через точки Points (информацию о перегруженных методах см. в справочной службе) |
public void FillEllipse(Brush B, Rectangle Rect); |
Закрашивает кистью в внутреннюю область эллипса (информацию о перегруженных методах см. в справочной службе) |
public void FillPath(Brush В, GraphicsPath Path); |
Закрашивает внутреннюю область объекта Path |
public void FillPie(B: Brush; Rect: Rectangle; StartAngle, FinishAngle: Single); |
Закрашивает внутреннюю область сектора эллипса (информацию о перегруженных методах см. в справочной службе) |
public void FillPolygon(Brush В Point [] Points); |
, Закрашивает внутреннюю область полигона (информацию о перегруженных методах см. в справочной службе) |
public void FillRectangle (Brush B, Rectangle Rect); |
Закрашивает внутреннюю область прямоугольника (информацию о перегруженных методах см. в справочной службе) |
public void FillRectangles (Brush B, Rectangle[]] Rects); |
Закрашивает внутренние области нескольких прямоугольников (информацию о перегруженных методах см. в справочной службе) |
public void FillRegion(Brush B, Region Reg); |
Закрашивает область Reg (информацию о перегруженных методах см. в справочной службе) |
public Graphics FromHdc(IntPtr DC) ; |
Создает объект Graphics по заданному контексту устройства DC |
public Graphics FromHWND(IntPtr HWND); |
Создает объект Graphics по заданному дескриптору окна hwnd |
public Graphics FromImage (Image Img) ; |
Создает объект Graphics но заданному объекту Img |
public IntPtr GetHDCO; |
Возвращает контекст устройства объекта |
public bool isClipEmpty(); |
Возвращает true, если объект пуст |
public bool IsVisible(Point T) ; |
Возвращает true, если точка T принадлежит видимой области объекта (информацию о перегруженных методах см. в справочной службе) |
public Region[] MeasureCharacterRanges (string S, Font F. Rectangle Layout, StringFormat[] SF) ; |
Метод возвращает объект Region, который содержит заданную подстроку строки s |
public SizeF MeasureString (string S, Font F); |
Метод возвращает размеры строки S (информацию о перегруженных методах см. в справочной службе) |
public void ReleaseHdc(IntPtr Hdc) ; |
Освобождает контекст устройства, полученный методом GetHDC |
public void ResetClip(); |
Восстанавливает бесконечные границы области отрисовки |
public void Restore(GraphicsObject GS); |
Восстанавливает состояние объекта, сохраненное в объекте GS методом Save |
public GraphicsState Save(); |
Сохраняет текущее состояние объекта |
public void SetClip(Graphics G); |
Устанавливает размеры области отрисовки текущего объекта равными указанным в свойстве Clip объекта G (информацию о перегруженных методах см. в справочной службе) |
public void TransformPoints (CoordinatSpace CS1, CoordinatSpace CS2,Point [] Points); |
Преобразует массив точек Points из одной координатной системы в другую (информацию о перегруженных методах см. в справочной службе) |
public void TranslateClip (int X, int Y) ; |
Изменяет размеры области отрисовки (информацию о перегруженных методах см. в справочной службе) |
public void TranslateTransform (Single X, Single Y); |
Изменяет начало координат области отрисовки (информацию о перегруженных методах см. в справочной службе) |
Класс Graphics является базовым классом для отрисовки изображений.
1.2.3 Отрисовка линий
Для отрисовки линий CTS предоставляет два класса — Реn и Brush, а также метод DrawLine класса Graphics.
Класс Реn позволяет выбирать толщину линий, добавлять к ним наконечники, а также нужным образом соединять линии. Класс Brush обеспечивает раскраску линии, в том числе заполнение ее градиентным цветом, узором или текстурой. Метод DrawLine осуществляет собственно отрисовку линии, используя нужные перо Реn и кисть Brush.
Методами BeginContainer () и EndContainer () создается и уничтожается графический контейнер — специальный объект класса GraphicsContainer (пространство имен System.Drawing.Drawing2D), в котором сохраняются текущие параметры объекта Graphics.
При вызове BeginContainer () параметры помещаются в стек. Любые изменения параметров до вызова EndContainer () уничтожаются и восстанавливаются сохраненные в стеке. Контейнеры могут быть вложенными, но каждый вызов EndContainer () уничтожает самый последний контейнер (количество вызовов EndContainer () может быть меньше вызовов BeginContainer () ).
В следующем примере создается контейнер, затем начало координат смещается на 100 пикселов влево и вниз, вычерчивается черной утолщенной линией прямоугольник и контейнер уничтожается. После этого вычерчивается синий прямоугольник того же размера (рис. 2.1).
В листинге 2.1 представлен обработчик события Form. Paint описанного примера.
Рис. 2.1. Демонстрация работы с контейнером
Листинг 2.1. Демонстрация работы с контейнером
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace ContainerDemo {
public partial class Forml : Form {
public Forml() {
InitializeComponent(); }
private void Forml_Paint(object sender, PaintEventArgs e)
{
// Создаем контейнер:
GraphicsContainer GS = e.Graphics.BeginContainer();
// Смещаем начало координат:
e.Graphics.TranslateTransform(100, 100);
// Вычерчиваем черный прямоугольник:
Pen P = new Pen(Color.Black, 2);
e.Graphics.DrawRectangle(P, 0, 0, 200, 200);
e.Graphics.EndContainer(GS); // Удаляем контейнер
// Заливаем синий прямоугольник:
SolidBrush В = new SolidBrush(Color.Blue);
e.Graphics.FillRectangle(В, 0, 0, 200, 200);
}
}
}
Аналогично работают методы Save () и Restore ().
В методах DrawArc () и DrawPie () используются ограничивающие углы Start и Finish. Начало отсчета углов соответствует радиальной горизонтальной линии, направленной вправо. Положительные углы отсчитываются по часовой стрелки, отрицательные — против.
Методы SetClip () , IntersectClip () и ResetClip () управляют размерами и положением области отрисовки.
Класс Graphics обеспечивает возможность использования графических объектов класса GraphicsPath (пространство имен System.Drawing.Drawing2D). Эти объекты имеют методы, позволяющие наполнять их графическими примитивами, линиями и кривыми. Метод DrawPath () вычерчивает все содержимое объекта GraphicsPath разом. Рисунок 2.4 получен с помощью показанного в листинге 2.3 обработчика события Paint .
Рис. 2.4. Демонстрация метода DrawPath
Листинг 2.3. Демонстрация метода DrawPath
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace GraphicPath {
public partial class Forml : Form
{
public Forml() {
InitializeComponent() ; }
private void Forml_Paint(object sender, PaintEventArgs e) {
// Создаем объект GraphicsPath:
GraphicsPath GP = new GraphicsPath();
// Наполняем его эллипсами:
GP.AddEllipse(60, 0, 60, 40);
GP.AddEllipse(60, 40, 60, 80);
GP.AddEllipse(31, 60, 30, 30);
GP.AddEllipse(119, 60, 30, 30);
GP.AddEllipse(55, 120, 30, 20);
GP.AddEllipse(95, 120, 30, 20);
e.Graphics.TranslateTransform(60, 60);
// Отрисовываем все содержимое объекта GpahicsPath:
Pen P = new Pen(Color.Black, 3);
e.Graphics.DrawPath(P, GP) ;
} } }
Методы DrawBezier() и DrawCurve() рисуют кривые линии. Кривая Безье определяется начальной и конечной, а также несколькими промежуточными точками (в методе DrawBezier() две промежуточные точки). В методе DrawCurve () используется сплайн-интерполяция между произвольным количеством точек. На рис. 2.5 показаны примеры кривых, создаваемых этими методами.
Листинг 2.4. Демонстрация вычерчивания кривых линий
private void Forml_Paint(object sender, PaintEventArgs e) {
// Точки излома для метода Curve:
Point [] Curve = new Point [7];
Curve[0] = new Point (50, 50);
Curve[1] = new Point(100, 25);
Curve[2] = new Point(200, 50);
Curve[3] = new Point (100, 150);
Curve[4] = new Point(300, 100);
Curve[5] = new Point (350, 200);
Curve[6] = new Point(250, 150);
// Рисуем кривую:
Pen P = new Pen(Color.Black, 2);
e.Graphics.DrawCurve(P, Curve);
// Рисуем ломаную линию по координатам кривой:
Реп р = new Pen(Color.Blue, 1);
е.Graphics.DrawLines(p, Curve);
// Точки излома для метода Bezier:
Point[] Bezier = new Point[4];
Bezier[0] = new Point(500, 50);
Bezier [1] = new Point(350, 100);
Bezier[2] = new Point(650, 150);
Bezier[3] = new Point(500, 200);
// Рисуем кривую Безье:
e.Graphics.DrawBezier(P,
Bezier[0], Bezier[l], Bezier [2], Bezier[3]);
// Рисуем ломаную линию по координатам кривой Безье:
е.Graphics.DrawLines(p, Bezier); }
Рис. 2.5. Демонстрация методов DrawLines, DrawCurve и DrawBezier
Этот рисунок создан обработчиком из листинга 2.4 .
Метод MeasureCharacterRanges () возвращает объекты типа Region, положение и размеры которых соответствуют положению и размерам некоторых подстрок в заданной строке. Параметр обращения SF класса StringFormat имеет метод SetMeasurableCharacterRanges (), с его помощью задаются порядковый номер символа (нумерация начинается с нуля) и количество символов, положение которых нужно определить.
ПРИМЕЧАНИЕ Описываемые методы правильно работают только со строками, созданными шрифтами типа Courier, в которых ширина знакоместа не изменяется (такие шрифты называются моноширинными).
В листинге 2.5 представлен обработчик события Paint формы, создающий окно, показанное на рис. 2.6.
Рис. 2.6. Демонстрация метода MeasureCharacterRanges
Листинг 2.5. Демонстрация метода MeasureCharacterRanges
private void Forml_Paint(object sender, PaintEventArgs e) {
// Создаем моноширинный шрифт:
Font F = new Font("Courier New", 22, FontStyle.Bold);
// Выводим строку:
string S = "First and Second ranges";
SolidBrush В = new SolidBrush(Color.Black);
e.Graphics.Drawstring(S, F, B, 50.OF, 50.OF);
// Определяем прямоугольник строки:
float w = e.Graphics.MeasureString(S, F).Width; // Ширина
float h = e.Graphics.MeasureString (S, F).Height; // Высота
// Прямоугольник строки:
RectangleF Layout = new RectangleF(50.Of, 50.Of, w, h);
// Готовим измерение:
StringFormat SF = new StringFormat();
SF.FormatFlags = StringFormatFlags.DirectionRightToLeft;
CharacterRange[] CR = new CharacterRange[2];
CR[0] = new CharacterRange(0, 5); // Параметры 1-й подстроки
CR[1] = new CharacterRange(10, 6); // Параметры 2-й подстроки
// Измеряем:
SF.SetMeasurableCharacterRanges(CR);
// Обрабатываем результат:
Region[] Reg = new Region[2]; // Области для подстрок
Reg = e.Graphics.MeasureCharacterRanges(S, F, Layout, SF) ;
RectangleF MR = Reg[0].GetBounds(e.Graphics); // 1-я подстрока
Pen P = new Pen(Color.Red);
е.Graphics.DrawRectangle (P, Rectangle.Round(MR)); // Очерчиваем
MR = Reg[1].GetBounds(e.Graphics); // 2-я подстрока
e.Graphics.DrawRectangle(P, Rectangle.Round(MR)); // Очерчиваем
}
Вызовом Rectangle .Round (MR) прямоугольник с вещественными координатами преобразуется в прямоугольник с целочисленными координатами.
ПРИМЕЧАНИЕ Вещественные константы в С# принадлежат типу double. Для приведения их к типу float можно ставить символ F или f за последней цифрой константы.
Свойство Transform содержит объект класса Matrix (пространство имен System . Drawing. Drawing2D). Этот объект определяет матрицу 3x3 для так называемых аффинных преобразований координат. При аффинных преобразованиях поворот и масштабирование изображений осуществляются путем нужного изменения системы координат. Для этого в состав класса включены методы Translate () (смещение начала координат), Scale () (масштабирование) и RotateAt () (поворот на заданный угол).
Рис. 2.7. Смещение начала координат
В листинге 2.6 демонстрируется метод Translate: сначала создается квадрат со стороной 100 пикселов и выводится синим цветом в левом верхнем углу экрана; затем начало координат смещается на 100 пикселов вниз и вправо, после чего квадрат вычерчивается вновь красным цветом. В результате в окне формы оказываются два квадрата: синий в левом верхнем углу и смещенный на 100 пикселов вправо и вниз красный (рис. 2.7).
Листинг 2.6. Демонстрация метода Transform
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace TransformDemo {
public partial class Forml : Form {
public Forml() {
InitializeComponent() ;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
// Создаем квадрат:
Rectangle R = new Rectangle (0, 0, 100, 100);
// Выводим его:
Pen P = new Pen(Color.Blue, 2);
e.Graphics.DrawRectangle(P, R);
// Создаем матрицу:
Matrix M = new Matrix();
// Смещаем начало координат:
M.Translate (100, 100);
// Вставляем в контекст устройства:
е.Graphics.Transform = М;
// Вновь выводим квадрат:
P.Color = Color.Red;
е.Graphics.DrawRectangle(P, R);
} } }
Для демонстрации метода Scale () поместите на форму два компонента Track-Bar (для этого в окне Toolbox раскройте узел All Windows Forms) и назовите их tbHor и tbVer. В свойство Orientation компонента tbVer поместите значение Vertical и разместите компоненты на форме примерно так, как показано на рис. 2.8 .
Рис. 2.8. Масштабирование изображения
В свойства Maximum, Minimum, TickFrequency и Value компонентов поместите значения 100, 1, 10, 10 соответственно. Создайте для их события Value-
Change и для события Paint формы обработчики (для события tbVer_Value-Change назначьте обработчик события tbHor_ValueChange), показанные в листинге 2.7.
Листинг 2.7. Масштабирование изображений
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace ScaleDemo {
public partial class Forml : Form
{
public Forml() {
InitializeComponent (); }
private void tbHor_ValueChanged(object sender, EventArgs e)
// При изменении значения свойства Value отрисовываем форму заново
{
Refresh (); }
private void Forml_Paint(object sender, PaintEventArgs e)
{
// Создаем матрицу:
Matrix M = new Matrix();
// Масштабируем с учетом положения ползунков TrackBar:
М.Scale(tbHor.Value / 10, tbVer.Value /10);
// Вставляем матрицу в контекст устройства:
е.Graphics.Transform = М;
// Вычерчиваем прямоугольник:
Реп Р = new Pen (Color.Blue, 2);
е.Graphics.DrawRectangle(P, 70, 70, 200, 200) ; } } }
При масштабировании в матрицу помещаются два коэффициента (dX и dY), на которые будут умножаться значения, соответственно, горизонтальной и вертикальной осей. Если коэффициент меньше 1, изображение сжимается, если больше — растягивается. Так как значения свойства Value компонента TrackBar не могут быть меньше единицы, эти значения при формировании матрицы делятся на 10.
Метод RotateAt () класса Matrix создает матрицу, поворачивающую оси координат на заданный угол относительно указанной точки. На рис. 2.9 показана форма с надписями, повернутыми на разные углы относительно горизонтального направления.
Рис. 2.9. Поворот изображения
Эту форму создала программа, представленная в листинге 2.8.
Листинг 2.8. Поворот изображений
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace RotateDemo {
public partial class Forml : Form
{
public Forml()
{
InitializeComponent();
}
private void Forml_Paint(object sender, PaintEventArgs e)
{
// Строка для вывода:
string S = " Visual C# v.2.0";
// Создаем графический путь:
GraphicsPath GP = new GraphicsPath();
// Создаем семейство шрифтов:
FontFamily FF = new FontFamily("Courier");
// Точка вывода - середина формы:
Point Р = new Point(Width / 2, Height 12);
// Помещаем строку в ГП:
StringFormat SF = new StringFormat(StringFormat.GenericDefault);
GP.AddString(S, FF, (int)FontStyle.Bold, 20, P, SF) ;
// Создаем матрицу поворота:
Matrix M = new Matrix();
// Цикл вывода:
Pen p = new Pen(Color.Black, 1);
for (int k = 1; k < 9; k++)
{
// Выводим надпись с текущим поворотом осей:
е.Graphics.DrawPath(p, GP);
// Поворачиваем оси для следующего прохода:
M.RotateAt(45, Р);
}}
При добавлении в графический путь строки помимо собственно строки нужно задать семейство шрифтов, стиль шрифта, его размер, точку старта строки и формат строки. Для задания начертания (полужирный, курсив и т. п.) можно применить перечисление FontStyle. Однако для совместимости элемент перечисления необходимо явно привести к типу int. Объект класса StringFormat содержит всю необходимую информацию о формате надписи: центрирование по осям, расстояние между символами и строками и т. п.
Обратите внимание: при отрисовке графического пути заданным пером р очерчиваются все находящиеся в нем объекты. Надпись очерчивается по периметру букв, поэтому буквы получились «пустыми».