Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Inf_2.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
264.7 Кб
Скачать
  • Глава 8. Использование графики

    • Графические инструменты Delphi

      • Класс TFont

      • Класс ТРеn

      • Класс TBrush

      • Класс TCanvas

      • Класс TGraphic

      • Класс TPicture

      • Класс TMetafile

      • Класс TIcon

      • Класс TBitmap

      • Графический формат JPEG Класс TJPEGImage

    • Компонент TImage

    • Использование диалогов для загрузки и сохранения графических файлов

    • Класс TClipboard

    • Класс TScreen

    • Вывод графики с использованием отображаемых файлов

    • Класс TAnimate

    • Резюме

Глава 8

Использование графики

"Одно изображение стоит тысячи слов" — говорил древнекитайский император Сун; его слова верны и в наши времена. 80% информации мозг человека получает по зрительному каналу, и не удивительно, что программисты стараются придать внешнему виду своих программ максимум привлекательности.

Поэтому в Delphi с самого начала появились развитые средства для работы с графическими возможностями Windows. Этому набору объектов и посвящена данная глава.

Графические инструменты Delphi

Разработчики Delphi уделили большое внимание возможностям работы с деловой графикой: простота и удобство ее использования напрямую сказываются на простоте и удобстве созданных приложений. Вместо дебрей графического интерфейса Windows разработчик получил несколько инструментов, сколь понятных, столь же и мощных.

В стандартном графическом интерфейсе Windows (GDI) основой для рисования служит дескриптор контекста устройства hDC и связанные с ним шрифт, перо и кисть. В состав VCL входят объектно-ориентированные надстройки над последними, назначением которых является удобный доступ к свойствам инструментов и прозрачная для пользователя обработка всех их изменений.

Обязательным для любого объекта, связанного с графикой в Delphi, является событие:

property OnChange: TNotifyEvent;

Его обработчик вызывается всякий раз, когда меняются какие-то характеристики объекта, влияющие на его внешний вид.

Класс TFont

Класс инкапсулирует шрифт Windows. В Delphi допускаются только горизонтально расположенные шрифты. В конструкторе объекта по умолчанию принимается шрифт System цвета clWindowText и размером 10 пунктов.

Свойства класса приведены в табл. 8.1.

Таблица 8.1. Свойства класса TFont

Свойство

Описание

property Handle: Hfont;

Содержит дескриптор шрифта

property Name: TfontName; 

Содержит имя (начертание) шрифта, например, Arial

property Style: TfontStyles;

TFontStyle = (fsBold, fsltalic, fsUnderline,

fsStrikeOut) ;

TFontStyles = set of TFontStyle;

Содержит стиль (особенности начертания) шрифта: соответственно, жирный, курсив, подчеркнутый и перечеркнутый. 

 

 

property Color: Tcolor;

TColor = -(COLOR ENDCOLORS + 1) ..$2FFFFFF;

Определяет цвет шрифта

property Charset: TftontCharset TFontCharset = 0..255;

Содержит номер набора символов шрифта. По умолчанию равно 1 (default_charset). Для вывода символов кириллицы требуется RUSSIAN_CHARSET

property Pitch: TFontPitch ;

TFontPitch = (fpDefault,

fpVariable, fpFixed) ;

Определяет способ установки ширины символов шрифта. Значение fpFixed соответствует моноширинным шрифтам; fpVariable — шрифтам с переменной шириной символа. Установка fpDefault означает принятие того способа, ко торый определен начертанием

property Height: Integer;

Содержит значение высоты шрифта в пикселах

property PixelsPerInch: Integer;

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

property Size: Integer; 

 

 

 

Содержит размер шрифта в пунктах (как принято в Windows). Это свойство связано с Height соотношением:

Font.Size := -Font.Height*72;

Font.PixelsPerInch

Установка этих свойств вручную, как правило, не нужна. Если вы хотите изменить шрифт для какого-то компонента, воспользуйтесь компонентом TFontDialog. В нем можно и поменять свойства, и сразу увидеть получившийся результат на тестовой надписи; потом выбранный шрифт присваивается свойству Font нужного компонента:

if FontDialogl.Execute then Editl.Font := FontDialogl.Font;

Е сли вы хотите, не закрывая диалог, увидеть результат применения шрифта на вашем тексте, включите опцию fdApplyButton в свойстве Options объекта TFontDialog и напишите для него обработчик события OnApply. При этом в диалоговом окне появится кнопка Apply, по нажатию которой (событие OnApply) можно изменить параметры шрифта.

 Класс ТРеп

Этот класс инкапсулирует свойства пера GDI Windows. В конструкторе по умолчанию создается непрерывное (pssolid) черное перо шириной в один пиксел. Свойства класса приведены в табл. 8.2.

Таблица 8.2. Свойства класса Tpеп

Свойство

Описание

property Handle: HPen;

Содержит дескриптор пера

property Color: TColor ;

Определяет цвет пера

property Mode: TPenMode ;

TPenMode = (pmBlack, pmWhite,

pmNop, pmNot, pmCopy, pmNotCopy,

pmMergePenNot, pmMaskPenNot,

prnMergeNotPen, pmMaskNotPen,

pmMerge, pmNotMerge, pmMask,

pmNotMask, pmXor, pmNotXor) ;

Содержит идентификатор одной из растровых операций, которые определяют взаимодействие пера с поверхностью. Эти операции соответствуют стандартным, определенным в Windows

property Style: TPenStyle ;

TPenStyle = (psSolid, psDash,

psDot, psDashDot, psDashDotDot,

psClear, psInsideFrame) ;

Определяет стиль линии, рисуемой пером. Соответствующие стили также определены в Windows

 

property Width: Integer;

Содержит значение толщины пера в пикселах

К сожалению, пунктирные и штрихпунктирные линии (стили psDash, psDot, psDashDot, psDashDotDot) могут быть установлены только для линий единичной толщины. Более толстые линии должны быть сплошными — такое ограничение существует в Windows.

О перация pmNotXor подходит для рисования перемещающихся линий или фигур, например, при выделении мышью какой-либо области. Если вы два раза нарисуете одну и ту же фигуру таким пером, то после первого раза она появится, после второго — полностью сотрется.

 Класс TBrush

Этот класс инкапсулирует свойства кисти — инструмента для заливки областей. Когда создается экземпляр этого класса, первоначально создается белая сплошная (styie-bssolid) кисть. Свойства класса приведены в табл. 8.3.

Таблица 8.3. Свойства класса TBrush

Свойство

Описание

Property Handle: HBrush;

Содержит дескриптор кисти

Property Color: TColor ;

Определяет цвет кисти

Property Style: TBrushStyle ;

TbrushStyle = (bsSolid,

bsClear, bsHorizontal,

bsVertical, bsFDiagonal,

bsBDiagonal, bsCross,

bsDiagCross);

Определяет стиль кисти (фактура закраски) 

Property Bitmap: TBitmap; 

Содержит битовую карту, определенную пользователем для закраски поверхностей. Если это свойство определено, то свойства Color и Style недействительны

 Шрифт, перо и кисть не могут использоваться самостоятельно. Они являются составными частями специального класса, который и будет сейчас рассмотрен.

Класс TCanvas

Этот класс — сердцевина графической подсистемы Delphi. Он объединяет в себе и "холст" (контекст конкретного устройства GDI), и "рабочие инструменты" (перо, кисть, шрифт) и даже "подмастерьев" (набор функций по рисованию типовых геометрических фигур). Будем называть его канвой.

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

Читатели, знакомые с графикой Windows, узнают в TCanvas объектно-ориентированную надстройку над контекстом устройства Windows (device context, DC). Дескриптор устройства, над которым "построена" канва, может быть востребован для различных низкоуровневых операций. Он задается свойством:

property Handle: HDC;

Для рисования канва включает в себя шрифт, перо и кисть:

property Font: TFont;

property Pen: TPen; property Brush: TBrush;

Кроме того, можно рисовать и поточечно, получив доступ к каждому пикселу. Значение свойства:

property Pixels[X, Y: Integer]: TColor;

соответствует цвету точки с координатами X, Y.

Необходимость рисовать отдельную точку возникает нередко. Однако если нужно модифицировать все или хотя бы многие точки изображения, свойство pixels надо сразу отбросить — настолько оно неэффективно. Гораздо быстрее редактировать изображение при помощи свойства ScanLine объекта TBitmap; об этом рассказано ниже.

Канва содержит методы-надстройки над всеми основными функциями рисования GDI Windows и свойства, которые приведены ниже в табл. 8.4. При их рассмотрении имейте в виду, что все геометрические фигуры рисуются текущим пером. Те из них, которые можно закрашивать, закрашиваются с помощью текущей кисти. Кисть и перо при этом имеют текущий цвет.

Таблица 8.4. Методы и свойства класса rcanvas

Метод

Описание

procedure Arc (XI, Y1, Х2, Y2, Y3, Х4, Y4: integer);

 

 

 

Метод рисует сегмент эллипса. Эллипс определяется описывающим прямоугольником (Х1, Y1) — (Х2, Y2); его размеры должны лежать в диапазоне от 2 до 32767 точек. Начальная точка сегмента лежит на пересечении эллипса и луча, проведенного из его центра через точку (ХЗ, Y3). Конечная точка сегмента лежит на пересечении эллипса и луча, проведенного из его центра через точку (Х4, Y4). Сегмент рисуется против часовой стрелки

procedure Chord (XI, Y1, Х2, Y2, ХЗ, Y3, Х4, Y4 : Integer);

Рисует хорду и заливает отсекаемуюею часть эллипса. Эллипс, начальная и конечная точки хорды определяются как в методе Arc

procedure Ellipse (XI, Y1, Х2, Y2: Integer);

Рисует и закрашивает эллипс, вписанный в прямоугольник (Х1, Y1) - (Х2, Y2)

procedure LineTo(X, Y: Integer);

Проводит линию текущим пером из текущей точки в (X, Y)

procedure MoveTo(X, Y: Integer);

Перемещает текущее положение пера (свойство PenPos) в точку (X, Y)

procedure BrushCopy(constDest: TRect; Bitmap: TBitmap;

const Source: TRect; Color: TColor) ;

Производит специальное копирование. Прямоугольник Source из битовой карты Bitmap копируется в прямоугольник Dest на канве; при этом цвет Color заменяется на цвет текущей кисти(Brush.Color)

С помощью этого метода можно нарисовать "прозрачную" картинку. Для этого нужно выбрать соответствующий фону цвет кисти и затем заменить на него фоновый или наиболее часто встречающийся цвет битовой карты (см. Bitmap.TransparentColor)

procedure CopyRect(const Dest: TRect; Canvas: TCanvas;

const Source: TRect);

Производит копирование прямоугольника Source из канвы Canvas в прямоугольник Dest в области самого объекта

procedure FillRect(const Rect: TRect) ;

Производит заливку прямоугольника (текущей кистью)

procedure FrameRect(const Rect: TRect) ;

Производит оконтуривание Прямоугольника цветом текущей кисти (без заполнения).

procedure Draw(X, Y: Integer; Graphic: TGraphic);

Осуществляет рисование графического объекта Graphic (точнее, вызов метода его рисования) в области с верхним левым углом (X, Y)

procedure StretchDrawtconst Rect: TRect; Graphic: TGraphic) ;

Осуществляет рисование объекта Graphic в заданном прямоугольнике Rect. Если их размеры не совпадают, Graphic масштабируется

procedure DrawFocusRect(const Rect: TRect);

Производит отрисовку прямоугольной рамки из

точек (как на элементе, имеющем фокус ввода).

Поскольку метод использует логическую операцию XOR (исключающее ИЛИ), повторный вызов для того же прямоугольника приводит изображение к начальному виду

procedure FloodFill(X, Y: Integer; Color: TColor;

FillStyle: TFillStyle);

TFillStyle = (fsSurface, fsBorder) ;

Производит заливку области текущей кистью.

Процесс начинается с точки (X, Y). Если режим

FillStyle равен fsSurface, то он продолжа

ется до тех пор, пока есть соседние точки с цветом Color. В режиме fsBorder закрашивание,

наоборот, прекращается при выходе на границу

с цветом Color

procedure Pie(XI, Yl, X2, Y2, X3, Y3, X4, Y4: Integer); 

 

Рисует сектор эллипса, описываемого прямоугольником (Х1, Y1) — (X2, Y2). Стороны сектора лежат на лучах, проходящих из центра эллипса через точки (X3, Y3) и (X4, Y4)

procedure Polygon(const Points: array of TPoint);

Строит многоугольник, используя массив координат точек Points. При этом последняя точка соединяется с первой и внутренняя область закрашивается

procedure Polyline(const Points: array of TPoint);

Строит ломаную линию, используя массив координат точек Points

procedure PolyBezier(const Points: array of TPoint);

Строит кривую Безье (кубический сплайн), используя массив координат точек Points

procedure PolyBezierTo(const Points: array of TPoint); 

Строит кривую Безье (кубический сплайн), используя массив координат точек points. Текущая точка используется в качестве первой

procedure Rectangle(X1, Y1,X2, Y2: Integers);

Рисует прямоугольник с верхним левым углом в (Х1, Y1) и нижним правым в (X2, Y2)

Procedure RoundRect(XI, Yl,

X2, Y2, X3, Y3: Integers); 

Рисует прямоугольник с закругленными углами.

Координаты вершин — те же, что и в методе Rectangle. Закругления рисуются как сегменты эллипса с размерами осей по горизонтали и вертикали X3 и Y3

function TextHeight(const Text: string): Integer;

Задает высоту строки Text в пикселах 

function TextWidth(const Text: string): Integer;

Задает ширину строки Text в пикселах 

procedure TextOut(X, Y; Integer; const Text: string);

Производит вывод строки Text. Левый верхний угол помещается в точку канвы (X, Y)

procedure TextRect(Rect: TRect; X, Y: Integer; const Text: string) ;

 

Производит вывод текста с отсечением. Как и в

TextOut, строка Text выводится с позиции (X, Y); но при этом часть текста, лежащая вне пределов прямоугольника Rect, отсекается и не будет видна

Свойство

property ClipRect: TRect;

 

 

 

Определяет область отсечения канвы. То, что при рисовании попадает за пределы этого прямоугольника, не будет изображено. Свойство Доступно только для чтения — его значение переустанавливается системой в контексте устройства, с которым связана канва.

property PenPos: TPoint;

Содержит текущую позицию пера канвы (изменяется посредством метода MoveTo)

Метод

procedure Refresh;

сбрасывает текущие шрифт, перо и кисть, заменяя их на стандартные, заимствованные из установок Windows (black pen, hollow brush, system_font).

Предусмотрено два события для пользовательской реакции на изменение канвы:

property OnChange: TNotifyEvent;

property One-changing: TNotifyEvent;

Эти события возникают при изменениях свойств и вызовах методов TCanvas, меняющих вид канвы (то есть, при любом рисовании; в методе MoveTo, например, они не возникают). Отличие их в том, что событие onChanging вызывается до начала изменении, а событие OnChange — после их завершения.

Идентификатор (код) растровой операции при копировании прямоугольных блоков содержится в свойстве:

property CopyMode: TCopyMode;

TCopyMode = Longint;

и определяет правило сочетания пикселов, копируемых на канву, с ее текущим содержимым. При этом можно создавать разные изобразительные эффекты В Delphi определены следующие константы кодов: cmBlackness,

cmDstlnvert, cmMergeCopy, cmMergePaint, cmNotSrcCopy, cmNotSrcErase, cmPatCopy, cmPatInvort, cmPatPaint, cmSrcAnd, cmSrcCopy, cmSrcErase, crnSrcInvert, cmSrcPaint, cmWhiteness.

Все они стандартно определены в Windows, и подробное их описание можно найти в документации по GDI. Значением свойства CopyMode по умолчанию является cmSrcCopy — копирование пикселов источника поверх существующих.

Из возможностей, появившихся в классе TCanvas, следует отметить поддержку рисования кривых (полиномов) Безье. Эта возможность впервые появилась в API Windows NT. Для построения одной кривой нужны минимум четыре точки — начальная, конечная и две опорные. По ним будет построена кривая третьего порядка. Если задан массив точек, они используются для построения последовательных кривых, причем последняя точка одной кривой является первой для следующей кривой.

Хорошей иллюстрацией использования объекта TCanvas может послужить пример GraphEx, поставляемый вместе с Delphi (папка \Demos\Doc\GraphEx). Есть только одно "но" — он приводится в неизменном виде, начиная с версии Delphi 1.0. Поэтому сделаем часть работы за программистов Inprise. В нашем примере модернизированы панели инструментов — они выполнены на компонентах ттоо1ваг и TControlBar; добавлена поддержка файлов JPEG; и, наконец, добавлена возможность рисования кривых Безье. Обновленный внешний вид главной формы примера GraphEx показан на рис. 8.1.

Рис. 8.1. Так теперь выглядит главная форма примера GraphEx

Где же найти ту канву, на которой предстоит рисовать? Во-первых, ею снабжены все потомки классов TGraphicControl и TCustomControi, то есть почти все визуальные компоненты из Палитры компонентов; в том числе и форма. Во-вторых, канву имеет растровая картинка (класс TBitmap); вы можете писать и рисовать не на пустом месте, а на готовом изображении (об этом в разделе "Класс TBitmap" данной главы). Но иногда нужно рисовать и прямо на экране! В этом случае придется прибегнуть к использованию функций API. Функция Get dc возвращает контекст устройства заданного окна, если ей передается параметр О—то всего экрана:

ScreenCanvas := TCanvas.Create;

ScreenCanvas.Handle := GetDC(O);

// рисование на ScreenCanvas ReleaseDC(0, ScreenCanvas.Handle);

ScreenCanvas.Free;

Пример необходимости рисования на экране — экранные заставки (Screen savers). Такое приложение под названием MovLines поставляется с этой книгой.

Когда и где следует рисовать? Этот вопрос далеко не риторический, как может показаться с первого взгляда.

Помимо графических примитивов, таких как линии и фигуры, на канве можно разместить готовые изображения. Для их описания создан класс TGraphic.

Класс TGraphic

Канва, перо, кисть и шрифт нужны, чтобы нарисовать свою картинку. Чтобы загрузить готовую, нужны объекты, "понимающие" графические форматы Windows.

Абстрактный класс TGraphic является родительским для четырех видов изображений, общепринятых в графике Windows — значка (компонент Ticon), метафайла (компонент TMetafile) и растровой картинки (компонент TBitmap). Четвертым потомком TGraphic является TJpEGimage — сжатая растровая картинка в формате JPEG.

Работая над приложением в Delphi, вы никогда не будете создавать объекты класса TGraphic;, но переменной этого типа вы можете присваивать указатель на любой из перечисленных классов-потомков.

Метод:

procedure Assign(Source: TPersistent);

переопределяет одноименный метод предка, допуская полиморфное присваивание графических объектов.

Загрузку и выгрузку графики в поток осуществляют методы:

procedure LoadFromStream(Stream: TStream);

procedure SaveTo3tream(Stream: TStream);

а загрузку и выгрузку в файл — методы:

procedure LoadFromFile(const Filename: string);

procedure SaveToFile(const Filename: string);

Эти методы создают соответствующий файловый поток и затем вызывают

Методы LoadFromStream/SaveToStream.

Два метода осуществляют взаимодействие с буфером обмена Windows:

procedure LoadFromClipboardFormat(AFormat: Word; AData: THandle; APal-ette: HPALETTE);

procedure SaveToClipboardFormat(var AFormat: Word; var AData: THandle;

var APalette: HPALETTE);

Здесь AFormat — используемый графический формат; AData и APalette — данные и палитра (если она требуется). Потомок должен иметь свой формат представления в буфере обмена и уметь обрабатывать данные, представленные в нем.

Загрузка больших графических файлов может продолжаться очень долго. Чтобы скрасить пользователю ожидание, программист может обработать событие OnProgress:

type TProgressStage = (psStarting, psRunning, psEnding);

TProgressEvent = procedure (Sender: TObject; Stage: TProgressStage; PercentDone: Byte; RedrawNow: Boolean;

Const R: TRect; const Msg: string) of object-property OnProgress: TProgressEvent;

Оно вызывается графическими объектами во время длительных операций. Параметр stage означает стадию процесса (начало/протекание/завершение), a percentDone - процент сделанной работы. Сразу оговоримся, что не все из тех объектов, которые будут нами описаны, вызывают обработчик события OnProgress.

Значение свойства:

property Empty: Boolean;

устанавливается равным True, если графический объект пуст (в него не загружены данные).

Высота и ширина графического объекта задаются свойствами:

property Height: Integer-property Width: Integer;

Для каждого дочернего типа эти параметры вычисляются своим способом. Наконец, свойство:

property Modified: Boolean;

показывает, модифицировался ли данный графический объект. Значение этого свойства устанавливается равным True внутри обработчика события

OnChange.

Многие графические объекты при отрисовке должны быть прозрачными. Некоторые из них прозрачны всегда (значок, метафайл), некоторые — в зависимости от значения свойства

property Transparent: Boolean;

Класс TPicture

Этот класс-надстройка над TGraphic, точнее — над его потомками. Он содержит поле Graphic, которое может содержать объекты классов TBitmap, Ticon, TMetafile и TJpEGimage. Предназначение TPicture — управлять вызовами соответствующих методов, скрывая при этом хлопоты с определением типа графического объекта и детали его реализации.

Кроме того, на уровне TPicture определены возможности регистрации и использования других — определенных пользователем — классов графических объектов, порожденных от TGraphic. Доступ к графическому объекту осуществляется посредством свойства:

property Graphic: TGraphic;

Если графический объект имеет один из трех предопределенных типов, то к нему можно обратиться и как к одному из свойств:

property Bitmap: TBitmap;

property Icon: TIcon;

property Metafile: TMetafile;

Обращаясь к этим функциям, нужно быть осторожным. Если в поле Graphic хранился объект одного класса, а затребован объект другого класса, то прежний объект уничтожается, а вместо него создается пустой объект требуемого класса. Например:

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]