Программирование >>  Вывод графики 

1 ... 7 8 9 [ 10 ] 11 12 13 ... 19


private Rectangle rectangleBounds = new Rectangle(new Point(0,0),

new Size(200,200)); private Rectangle ellipseBounds = new Rectangle(new Point(50,200),

new Size(200,150)); private readonly Pen bluePen = new Pen(Color.Blue, 3); private readonly Pen redPen = new Pen(Color.Red, 2); private readonly Brush solidAzureBrush = Brushes.Azure; private readonly Brush solidYellowBrush = new SolidBrush(Color.Yellow); private static readonly Brush brickBrush =

new HatchBrush(HatchStyle.DiagonalBrick, Color.DarkGoldenrod, Color.Cyan); private Pen brickWidePen = new Pen(brickBrush, 10);

Поле brickBrush объявлено статическим, чтобы можно было использовать его значение для инициализации поля brickWidePen. Язык C# не позволяет использовать одно поле экземпляра для инициализации другого поля экземпляра, поскольку не определено, какое из них инициализируется первым. Однако объявление одного из полей статическим решает проблему. А так как у нас создается только один экземпляр класса Form1, то неважно, является поле статическим или нет.

Переопределим OnPaint() следующим образом:

protected override void OnPaint( PaintEventArgs e )

base.OnPaint(e); Graphics dc = e.Graphics;

Point scrollOffset = AutoScrollPosition; dc.TranslateTransform(scrollOffset.X, scrollOffset.Y); if (e.ClipRectangle.Top+scrollOffset.X < 350 e.ClipRectangle.Left+scrollOffset.Y < 250)

dc.DrawRectangle(bluePen, rectangleBounds); dc.FillRectangle(solidYellowBrush, rectangleBounds); dc.DrawEllipse(redPen, ellipseBounds); dc.FillEllipse(solidAzureBrush, ellipseBounds); dc.DrawLine(brickWidePen, rectangleBounds.Location, ellipseBounds.Location+ellipseBounds.Size);

Как и раньше, установим AutoScrollMinSize равным (250,350). На рис. 33.13 показан результат.

Обратите внимание, что толстая диагональная линия нарисована поверх прямоугольника и эллипса, потому что она нарисована последней.

Вывод графических изображений

Одной из операций, которые вам, вероятно, придется делать с помощью GDI+, будет вывод готовых изображений, хранящихся в файлах. В действительности это намного проще, чем рисование соб-

Рис. 33.13. Результат выполнения

ственного пользовательского интерфейса, потому

примера ScrollMoreShapes что в данном случае все уже нарисовано заранее. По

сути все, что нужно сделать - это загрузить файл и дать команду GDI+ отобразить его. Изображение может представлять простой рисунок, состоящий из линий, пиктограмму или же сложную картинку наподобие фотографии. Изображением можно также манипулировать, растягивая и поворачивая его или же отображая какую-то его часть.




Начнем этот раздел с простого примера. Затем обсудим некоторые обстоятельства, о которых необходимо помнить при отображении картинок. Такой путь возможен, поскольку код, визуализирующий графические изображения, очень прост.

Класс, который нам понадобится - System.Drawing.Image - это один из базовых классов .NET. Экземпляр Image представляет изображение. Его чтение из файла требует написания всего одной строки кода:

Image myImage = Image.FromFile( FileName );

FromFile() , статический член класса Image, является обычным способом создания изображения. Файл может иметь любой из поддерживаемых графических форматов, включая .bmp, .jpg, .gif и .png.

Вывод изображения также очень прост, если у вас в руках уже есть подходящий экземпляр Graphics. Для этого достаточно вызова Graphics.DrawImageUnscaled() или Graphics.DrawImage() . Доступно сравнительно немного перегрузок этих методов, но они обеспечивают существенную гибкость за счет указания информации относительно местоположения и размера отображаемого образа. Но в данном примере мы используем DrawImage() следующим образом:

dc.DrawImage(myImage, points);

В этой строке кода предполагается, что dc - экземпляр Graphics, а myImage - отображаемый экземпляр Image. Аргумент points - массив структур Point, где points[0], points[1] и points[2] - координата: верхнего левого, верхнего правого и нижнего левого углов картинки.

Работа с графическими изображениями - возможно, та область, в которой разработчики, знакомые с GDI, обнаружат наибольшие различия между GDI и GDI+. В GDI вывод изображения требовал выполнения нескольких нетривиальных шагов. Если изображение представляло собой битовую карту, его загрузка б1ла относительно простой. Но если это б1л файл другого типа, то его загрузка требовала последовательности вызовов OLE-объектов. Вывод загруженного изображения на экран включал в себя получение его дескриптора, выбор его в контексте устройства, находящегося в памяти, и выполнение блочной передачи между контекстами. Хотя контексты устройств и дескрипторы остались за кулисами и по-прежнему необходимы в случае программного редактирования образа, простые задачи теперь исключительно удобно помещены в оболочки объектной модели GDI+.

Проиллюстрируем процесс вывода графического изображения на примере под названием DisplayImage. Пример будет просто отображать файл .jpg в главном окне приложения. Для простоты путевое имя файла .jpg жестко закодировано в тексте программы (поэтому перед запуском откорректируйте это имя в соответствии с местоположением файла в вашей системе). Отображаемый файл .jpg будет фотографией заката над Санкт-Петербургом.

Как и другие примеры, проект DisplayImage - стандартный проект приложения Windows на C#, сгенерированного Visual Studio 2008. Добавим в класс Form1 следующие поля:

readonly Image piccy;

private readonly Point [] piccyBounds;

В конструкторе Form1 загрузим файл с картинкой:

public Form1() {

InitializeComponent();

piccy = Image.FromFile(@ C:\ProCSharp\GdiPlus\Images\London.jpg ); AutoScrollMinSize = piccy.Size; piccyBounds = new Point[3];



piccyBounds[0] = new Point(0,0); piccyBounds[1] = new Point(piccy.Width,0); piccyBounds[2] = new Point(0,piccy.Height);

верхний левый верхний правхй нижний левхй

Обратите внимание, что размер изображения в пикселях получается из его свойства Size и используется для установки области документа. Также создается массив точек piccyBounds, определяющий позицию изображения на экране. Мы устанавливаем координаты точек в соответствии с действительным размером картинки, но при желании ее можно было бы увеличить, уменьшить, растянуть или даже втиснуть в непрямоугольный параллелограмм, всего лишь изменив значения структур Point в массиве piccyBounds.

Картинка отображается в переопределенном методе OnPaint():

protected override void OnPaint(PaintEventArgs e)

base.OnPaint(e); Graphics dc = e.Graphics; dc.ScaleTransform(1.0f, 1.0f);

dc.TranslateTransform(AutoScrollPosition.X, AutoScrollPosition.Y); dc.DrawImage(piccy, piccyBounds);

И, наконец, внесем изменение в сгенерированный IDE код метода Form1.

Dispose():

protected override void Dispose(bool disposing)

piccy.Dispose();

if( disposing && (component != null))

components.Dispose();

base.Dispose(disposing );

Уничтожить изображение сразу после того, как отпадает в нем необходимость, важно потому, что обычно графические изображения занимают большие объемы памяти. После того, как вызван Image.Dispose(), экземпляр Image более не ссылается ни на какое реальное изображение, а потому не может его отображать (если только не загружено новое изображение). На рис. 33.14 показан результат выполнения этого кода.


Рис. 33.14. Результат выполнения примера DisplayImage



1 ... 7 8 9 [ 10 ] 11 12 13 ... 19

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика