Компоненты Image и PaintBox представляют собой некоторую ограниченную поверхность с канвой, на которую можно заносить изображения, как это описано в разделе 4.2. При этом компонент PaintBox, собственно говоря, не дает ничего нового по сравнению с рисованием на канве формы. Рисование на PaintBox вместо формы не имеет никаких преимуществ, кроме, может быть, некоторого облегчения в расположении одного или нескольких рисунков в площади окна.
Компонент Image много богаче по своим возможностям и удобнее, чем PaintBox. Даже при использовании описанных в разделе 4.2 приемов рисования на канве компонент Image имеет существенное преимущество: в нем не приходится думать о перерисовке изображения, испорченного из-за перекрытия данного окна другими. Все, связанное с обработкой событий OnPaint, рассмотренных в разделе 4.2, в Image осуществляется автоматически. Кроме того с помощью Image проще, чем при непосредственном рисовании на канве формы, расположить в окне приложения несколько изображений и управлять ими. При этом отпадает необходимость сложных и нудных расчетов координат канвы формы, обеспечивающих требуемое взаимное расположение изображений, т.е. в полной мере проявляются преимущества визуального программирования. Так что, вероятно, во всех случаях лучше работать с канвой Image, чем с канвой формы.
Но помимо этих возможностей у компонента Image имеются свойства, позволяющие работать с различными типами графических файлов.
Delphi поддерживает три типа файлов — битовые матрицы, пиктограммы и метафайлы. Все три типа файлов хранят изображения; различие заключается лишь в способе их хранения внутри файлов и в средствах доступа к ним. Битовая матрица (файл с расширением .bmp) отображает цвет каждого пикселя в изображении. При этом информация хранится таким образом, что любой компьютер может отобразить изображение с разрешающей способностью и количеством цветов, соответствующими его конфигурации.
Пиктограммы (файлы с расширением .ico) — это маленькие битовые матрицы. Они повсеместно используются для обозначения значков приложений, в быстрых кнопках, в пунктах меню, в различных списках. Способ хранения изображений в пиктограммах схож с хранением информации в битовых матрицах, но имеются и различия. В частности, пиктограмму невозможно масштабировать, она сохраняет тот размер, в котором была создана.
Метафайлы (Metafiles) хранят не последовательность битов, из которых состоит изображение, а информацию о способе создания картинки. Они хранят последовательности команд рисования, которые и могут быть повторены при воссоздании изображения. Это делает такие файлы, как правило, более компактными, чем битовые матрицы.
Компонент Image позволяет отображать информацию, содержащуюся в графических файлах всех указанных типов. Для этого служит его свойство Picture — объект типа TPicture.
Рис. 4.3 Окно Picture Editor |
Чтобы познакомиться с этим свойством откройте новое приложение и перенесите на форму компонент Image. Растяните его или задайте его свойство Align равным alClient, чтобы он занял всю клиентскую область формы. Нажмите на кнопку с многоточием около свойства Picture в окне Инспектора Объектов или просто сделайте двойной щелчок на Image. Перед вами откроется окно Picture Editor
(рис. 4.3), позволяющее загрузить в свойство Picture какой-нибудь графический файл (кнопка Load
), а также сохранить открытый файл под новым именем или в новом каталоге. Щелкните на Load
, чтобы загрузить графический файл. Перед вами откроется окно открытия графического файла, представленное на рис. 4.4. По мере перемещения курсора в списке по графическим файлам в правом окне отображаются содержащиеся в них картинки, а над ними — цифры, характеризующие размер картинки. Вы можете выбрать требуемый вам графический файл любого типа. Напомним, что поставляемые с Delphi графические файлы вы можете найти в каталоге Images. В Delphi 5 и 4 он обычно расположен в каталоге ...\program files\Common Files\Borland Shared. В Delphi 3 он расположен в каталоге ...\program files\Borland\Delphi 3, а в Delphi 1 — в каталоге Delphi 16. После загрузки файла щелкните на OK
в окне Picture Editor
и в вашем компоненте Image отобразится выбранная вами картинка. Можете запустить ваше приложение и полюбоваться ею. Впрочем, вы и так видите картинку, даже не выполняя приложение.
Рис. 4.4 Окно диалога открытия графического файла | |
Когда вы в процессе проектирования загрузили изображение из файла в компонент Image, он не просто отображает его, но и сохраняет в приложении. Это дает вам возможность поставлять ваше приложение без отдельного графического файла. Впрочем, как мы увидим позднее, в Image можно загружать и внешние графические файлы в процессе выполнения приложения.
Вернемся к рассмотрению свойств компонента Image.
Если установить свойство AutoSize в true, то размер компонента Image будет автоматически подгоняться под размер помещенной в него картинки. Если же свойство AutoSize установлено в false, то изображение может не поместиться в компонент или, наоборот, площадь компонента может оказаться много больше площади изображения.
Другое свойство — Stretch позволяет подгонять не компонент под размер рисунка, а рисунок под размер компонента. Установите AutoSize в false, растяните или сожмите размер компонента Image и установите Stretch в true. Вы увидите, что рисунок займет всю площадь компонента, но поскольку вряд ли реально установить размеры Image точно пропорциональными размеру рисунка, то изображение исказится. Устанавливать Stretch в true может иметь смысл только для каких-то узоров, но не для картинок. Свойство Stretch не действует на изображения пиктограмм, которые не могут изменять своих размеров.
Свойство — Center, установленное в true, центрирует изображение на площади Image, если размер компонента больше размера рисунка.
Рассмотрим еще одно свойство — Transparent (прозрачность). Если Transparent равно true, то изображение в Image становится прозрачным. Это можно использовать для наложения изображений друг на друга. Поместите на форму второй компонент Image и загрузите в него другую картинку. Только постарайтесь взять какую-нибудь мало заполненную, контурную картинку. Можете, например, взять картинку из числа помещаемых обычно на кнопки, например, стрелку (файл ...\program files\common files\borland shared\images\buttons\arrow1l.bmp). Передвиньте ваши Image так, чтобы они перекрывали друг друга, и в верхнем компоненте установите Transparent равным true. Вы увидите, что верхняя картинка перестала заслонять нижнюю. Одно из возможных применений этого свойства — наложение на картинку надписей, выполненных в виде битовой матрицы. Эти надписи можно сделать с помощью встроенной в Delphi программы Image Editor
.
Учтите, что свойство Transparent действует только на битовые матрицы. При этом прозрачным (т.е. заменяемым на цвет расположенного под ним изображения) делается по умолчанию цвет левого нижнего пикселя битовой матрицы.
Мы рассмотрели загрузку изображения из файла в процессе проектирования. Но свойство Picture позволяет также легко организовать обмен с графическими файлами любых типов в процессе выполнения приложения. Чтоб пояснить технику такого обмена, надо сначала подробнее рассмотреть свойство Picture.
Это свойство является объектом, который имеет в свою очередь подсвойства, указывающие на хранящийся графический объект. Если в Picture хранится битовая матрица, на нее указывает свойство Picture.Bitmap. Если хранится пиктограмма, на нее указывает свойство Picture.Icon. На хранящийся метафайл указывает свойство Picture.Metafile. Наконец, на графический объект произвольного типа указывает свойство Picture.Graphic.
Объект Picture и его свойства Bitmap, Icon, Metafile и Graphic имеют методы файлового чтения и записи LoadFromFile и SaveToFile:
procedure LoadFromFile(const FileName: string); procedure SaveToFile(const FileName: string);
Для свойств Picture.Bitmap, Picture.Icon и Picture.Metafile формат файла должен соответствовать классу объекта: битовой матрице, пиктограмме, метафайлу. При чтении файла в свойство Picture.Graphiс файл должен иметь формат метафайла. А для самого объекта Picture методы чтения и записи автоматически подстраиваются под тип файла. Поясним это на примере.
Давайте построим приложение, аналогичное рассмотренному в разделе 4.2 примеру просмотра графических файлов. Для разнообразия можно организовать управление им не кнопкой Button, а меню. Поместите на форму компонент Image. Растяните его или задайте его свойство Align равным alClient, чтобы он занял всю клиентскую область формы. Перенесите на форму компонент диалога открытия графического файла OpenPictureDialog (см. раздел 8.2). Поместите также на форму компонент главного меню MainMenu (см. раздел 6.1) и задайте в нем один раздел — Файл. В обработчике этого раздела напишите оператор
if(OpenPictureDialog1.Execute) then Image1.Picture.LoadFromFile( OpenPictureDialog1.FileName);
Этот оператор вызовет диалог открытия графического файла (см. рис. 4.4) и загрузит в компонент Image1 изображение из выбранного пользователем файла (см. рис. 4.5). Причем файл может быть любого типа: битовая матрица, пиктограмма или метафайл.
Рис. 4.5 Изображение в компоненте Image битовой матрицы (а) и пиктограммы (6) | а) | б) |
В этом приложении метод LoadFromFile применен к Image1.Picture. Если будут открываться только файлы битовых матриц, то оператор загрузки файла можно заменить на
Image1.Picture.Bitmap.LoadFromFile( OpenPictureDialog1.FileName);
Для пиктограмм можно было бы использовать оператор
Image1.Picture.Icon.LoadFromFile( OpenPictureDialog1.FileName);а для метафайлов — оператор
Image1.Picture.Metafile.LoadFromFile( OpenPictureDialog1.FileName);или
Image1.Picture.Graphic.LoadFromFile( OpenPictureDialog1.FileName) ;
Но во всех этих случаях, если формат файла не совпадет с предполагаемым, возникнет ошибка. Аналогично работает и метод SaveToFile с тем отличием, что примененный к Picture или к Picture.Graphic он сохраняет в файле изображение любого формата. Например, если вы дополните свое приложение диалогом SavePictureDialog (см. раздел 8.2), введете в меню раздел Сохранить как
и в его обработчик поместите оператор
if SavePictureDialog1.Execute then Image1.Picture.SaveToFile(SavePictureDialog1.FileName);то пользователь получит возможность сохранить изображение любого формата в файле с новым именем. Только при этом, чтобы не возникало в дальнейшем путаницы, расширение сохраняемого файла все-таки должно соответствовать формату сохраняемого изображения.
Абсолютно идентично для изображений любого формата будет работать программа, если оператор сохранения вы замените на
Image1.Picture.Graphic.SaveToFile( SavePictrureDialog1.FileName);использующий свойство Picture.Graphic. А если вам известен формат хранимого в компоненте Image изображения, то вы можете применить метод SaveToFile к свойствам Picture.Bitmap, Picture.Icon и Picture.Metafile.
Для всех рассмотренных объектов Picture, Picture.Bitmap, Picture.Icon и Picture.Metafile определены методы присваивания значений объектов:
procedure Assign(Source: TPersistent);
Однако, для BitMap, Icon и Metafile присваивать можно только значения однородных объектов: соответственно битовых матриц, пиктограмм, метафайлов. При попытке присвоить значения разнородных объектов генерируется исключение ЕConvertError. Объект Picture — универсальный, ему можно присваивать значения объектов любых из остальных трех классов. А значение Picture можно присваивать только тому объекту, тип которого совпадает с типом объекта, хранящегося в нем.
Метод Assign можно использовать и для обмена изображениями с буфером Clipboard
. Например, оператор
Clipboard.Assign(Image1.Picture) ;занесет в буфер обмена изображение, хранящееся в Image1. Аналогично оператор
Image1.Picture.Assign(Clipboard) ;прочитает в Image1 изображение, находящееся в буфере обмена. Причем это может быть любое изображение и даже текст.
Надо только не забыть при работе с буфером обмена вставить в оператор uses вашего модуля ссылку на модуль Clipbrd. Автоматически Delphi эту ссылку не вставляет.
Возвращаясь к свойствам компонента Image, можно отметить один недостаток, присущий нашему тестовому приложению, приведенному на рис. 4.5. При загрузке разных изображений размер окна приложения может оказаться или слишком маленьким, и тогда вы увидите только часть изображения, или слишком большим, и тогда изображение будет некрасиво размещено в левом верхнем углу формы, оставляя много пустого пространства. Этот недостаток можно устранить, если воспользоваться свойствами Height (высота) и Width (ширина) компонента Image. При свойстве AutoSize установленном в true размеры Image автоматически устанавливаются равными размерам загруженного изображения. И этими размерами можно воспользоваться для соответствующего изменения размеров формы. Например, приведенный ранее код загрузки изображения из файла можно заменить на следующий:
if OpenPictureDialog1.Execute then begin Image1.Picture.LoadFromFile( OpenPictureDialog1.FileName); Form1.ClientHeight := Image1.Height+10; Image1.Top := Form1.ClientRect.Top + (Form1.ClientHeight — Image1.Height) div 2; Form1.ClientWidth := Image1.Width+10; Image1.Left := Form1.ClientRect.Left + (Form1.ClientWidth — Image1.Width) div 2; end;
В этом коде размеры клиентской области формы устанавливаются несколько больше размеров компонента Image1, которые в свою очередь адаптируются к размеру картинки благодаря свойству AutoSize. Внесите эти исправления в свое приложение, выполните его и увидите, что форма стала автоматически адаптироваться к размерам загруженного изображения.