722
.pdfрасширение Video BIOS, предложенное VESA. Драйвер VESA или загружается, или содержится в ROM Video BIOS.
Контексты устройств (Device Contexts - DC)
Контекст устройства - структура, которая определяет набор графических объектов, связанных с ними атрибутов и графических режимов, которые обеспечивают вывод. Графические объекты включают перо для записи строки, кисть для закрашивания и заполнения, точечный рисунок для копирования или прокрутки частей экрана, палитру для определения набора доступных цветов, область для отсечения и других операций.
Перечислим атрибуты, связанные с каждыми из этих объектов.
Графический объект |
Атрибуты |
Точечный рисунок |
Размер, в байтах; протяженности (в пикселях); |
|
цветовой формат; схема сжатия; и т. д. |
Кисть |
Стиль, цвет, форма, и начало координат |
Палитра |
Цвета и размер (или число цветов) |
Шрифт |
Название Шрифта, ширина, высота, размер, |
|
набор символов, и т. д. |
Перо |
Стиль, ширина, и цвет |
Область |
Расположение и габариты |
Когда приложение создает контекст устройства, Windows автоматически сохраняет в нем набор заданных по умолчанию объектов (кроме точечного рисунка или пути). Приложение может определять атрибуты заданных по умолчанию объектов, вызывая функции GetCurrentObject и GetObject. Приложение может изменять эти значения по умолчанию, создавая новый объект и помещая его в контекст устройства, вызывая функцию SelectObject.
Графические режимы
Windows поддерживает пять графических режимов, которые позволяют приложению определить, как смешивать цвета, где размещать вывод, как выполнять масштабирование и т. д. Вот эти режимы:
Фоновый режим Определяет, как цвета фона смешиваются с существующими оконными
или экранными цветами для растровых и текстовых операций. Режим рисования
Определяет, как наносимые цвета смешиваются с существующими оконными или экранными цветами для пера, кисти, точечного рисунка, и текстовых операций.
Режим отображения Определяет, как графический образ отображается из логического представления на окно, экран, или бумагу принтера.
Режим заполнения Определяет, какова форма кисти, чтобы заполнить внутреннюю область сложных областей.
Режим растяжения Определяет, как растровые цвета смешаны с существующими оконными или экранными цветами при сжатии рисунка.
Приложение может определять заданные по умолчанию режимы,
вызывая соответственно функции GetBkMode, GetROP2, GetMapMode,
GetPolyFillMode, GetStretchBltMode. Для изменения режимов используют функции SetBkMode, SetROP2, SetMapMode, SetPolyFillMode, SetStretchBltMode.
Типы DC
Win32 API поддерживает четыре типа контекста устройств: дисплей, принтер, память и информация. Каждый тип обеспечивает работу с определенным объектом:
Дисплей |
Поддерживает операции рисования на дисплее. |
Принтер |
Поддерживает операции рисования на принтере или |
|
графопостроителе (плоттере). |
Память |
Поддерживает операции рисования на точечном рисунке. |
Информация |
Поддерживает поиск данных устройства. |
|
DC дисплея (Display DC - DDC) |
Windows предоставляет три типа контекста устройства для дисплеев: класс, общий и частный. Класс и частные контексты используются в приложениях САПР, издательских системах и т. п. Общие контексты используются в прикладных программах, которые выполняют нечастые операции рисования.
Приложение получает DDС, вызывая функцию BeginPaint или GetDC и идентифицируя окно, в котором предполагается вывод. Как правило, приложение получает контекст устройства только для рисования на клиентской области окна. Когда приложение заканчивает рисование, оно должно освободить контекст устройства, вызывая функцию EndPaint или ReleaseDC.
Класс DC
Класс DC поддерживается только для совместимости с предыдущими версиями Windows. При разработке 32-хразрядных приложений используют частный контекст устройства.
Общие DC
Общие DC - это DDC, стандартно управляемые оконными средствами Win32 API. Приложение получает дескриптор (handle), идентифицирующий один из доступных общих DC, вызывая GetDC, GetDCEx, или функцию BeginPaint. Перед возвращением этого дескриптора Windows инициализирует общий контекст устройства с заданными по умолчанию объектами, атрибутами и режимами.
Частные DC
Частные DC, в отличие от общих, сохраняют любые изменения заданных по умолчанию данных даже после вызовов из прикладной программы функций ReleaseDC или EndPaint. Частные контексты устройства не входят в кэш администратора оконного режима и поэтому не должны освобождаться после использования. Администратор автоматически удаляет частный контекст устройства после того, как связанное с ним последнее окно будет разрушено.
Приложение создает частный контекст устройства первым определением CS_OWNDC стиля класса окна при инициализации элемента стиля структуры WNDCLASS и вызова функции RegisterClass. После создания окна с CS_OWNDC стилем, приложение может вызывать GetDC, GetDCEx или BeginPaint для того, чтобы получить дескриптор, идентифицирующий частный DC.
Операции с DC
Приложению доступны следующие операции:
11
·Перечисление существующих графических объектов.
·Выбор новых графических объектов.
·Удаление существующих объектов.
·Сохранение текущих графических объектов, их атрибутов и графических режимов.
·Восстановление предварительно сохраненных графических объектов, атрибутов и режимов.
Закрашивание и рисование
Почти все прикладные программы используют экран, чтобы отобразить данные, которыми они манипулируют.
Прикладные программы используют окна как устройства вывода, а не непосредственно экран. Windows ставит DDC в соответствие окнам . Рисование в окне предотвращает сталкивание приложений и позволяет прикладным программам сосуществовать друг с другом.
Приложение рисует в окне в следующих случаях: при создании окна, при изменении размера окна, при наложении окон, при свертке или максимизировании окна, при отображении данных из открытого файла, при прокрутке, изменении или выборе части отображенных данных. Windows управляет действиями типа перемещения и установления размеров окна. Если оказывается воздействие на содержимое окна, Windows отмечает поврежденную часть окна как готовую к обновлению и при первой возможности посылает сообщение WM_PAINT. Некоторые действия управляются приложением, например, отображение открытых файлов и выбор отображенных данных.
Во всех случаях приложение может рисовать в окне, как только оно создано. Чтобы рисовать в окне, приложение должно сначала отыскать дескриптор DDC для окна. Обычно приложение выполняет большинство операций рисования в течение обработки сообщений WM_PAINT. В этом случае приложение отыскивает DDC, вызывая функцию BeginPaint. Сначала устанавливается область отсечения для DC, равная пересечению части окна, которое нуждается в обновлении и части, которая является видимой пользователю. Повторно выводятся только те части окна, которые изменились.
Windows может также посылать диспетчеру сообщения WM_NCPAINT и WM_ERASEBKGND. Эти сообщения направляют приложение, чтобы обновить неклиентскую область и фон окна. Неклиентская область - часть окна, которая находится вне клиентской области. Эта область включает области заголовка, меню окна (системное меню), и линейки прокрутки. Большинство прикладных программ полагается на заданную по умолчанию функцию окна DefWindowProc для вывода этой области. Фон окна - цвет или текстура, которым заполняется окно прежде, чем начинаются другие операции рисования. Фон закрывает любые объекты в окне.
Область обновления
Область обновления идентифицирует устаревшую часть окна, которая требует изменения. Windows использует область обновления, чтобы генерировать сообщения WM_PAINT для прикладных программ. Когда Windows решает, что окно нуждается в обновлении, она устанавливает габариты области обновления. Установка области обновления, однако, не заставляет приложение немедленно выводить. Вместо этого, приложение продолжает выбирать сообщения из очереди до ее исчерпания. Затем Windows проверяет область обновления и, если она не пуста, посылает WM_PAINT.
Синхронное и асинхронное рисование
Рисование, выполненное в течение обработки WM_PAINT асинхронно: то есть имеется задержка между моментом выдачи запроса на обновление и посылкой WM_PAINT. В течение задержки приложение обычно выбирает сообщения из очереди и выполняет другие задачи. Причина для задержки в том, что Windows вообще обрабатывает рисование в окне как операцию с низким приоритетом и пропускает вперед сообщения ввода пользователя и сообщения, которые могут воздействовать на позицию или размер окна.
Иногда необходимо вывести синхронно, то есть рисовать окно немедленно. Например, немедленно выводится главное окно приложения после его запуска. Windows выводит синхронно некоторые окна управления , типа кнопок, потому что они служат фокусом ввода пользователя. Синхронные функции UpdateWindow и RedrawWindow обеспечивают эту возможность. Они посылают сообщение WM_PAINT прямо окну, если область обновления не пуста.
Рисование без сообщения WM_PAINT
Иногда более эффективно выводить прямо в окно без ожидания WM_PAINT. Это может быть полезно, когда пользователь нуждается в немедленной обратной связи, как при перемещении или установлении размеров объекта. В таких случаях приложение обычно выводит в окно при обработке сообщений мыши или клавиатуры. Чтобы рисовать в окне без использования WM_PAINT, приложение вызывает функции GetDC или GetDCEx, чтобы отыскать DDC для окна.
Графическая подсистема Borland C++ Builder
Разработчики Borland C++ Builder уделили большое внимание возможностям работы с деловой графикой: простота и удобство ее использования напрямую сказывается на простоте и удобстве созданных приложений. Вместо дебрей графического интерфейса Windows разработчик получил несколько инструментов, сколь понятных, столь же и мощных.
Другой бич работы с графикой в Windows - проблема рационального использования ресурсов. Для больших программных комплексов она стала в последнее время нешуточной. Такие монстры, как Microsoft Office, потребляют во время работы львиную долю ресурсов. В Borland C++ Builder ресурсами GDI незримо для пользователя "заведуют" специальные менеджеры, ведущие списки всех размещенных кистей, перьев, шрифтов и т. п. и управляющие их использованием.
Обязательным для любого объекта, связанного с графикой в Borland C++ Builder является событие
__property Classes::TNotifyEvent OnChange = {read=FOnChange, write=FOnChange};
Его обработчик вызывается всякий раз, когда изменились какие-то характеристики объекта, влияющие на его внешний вид.
В стандартном GDI основой для рисования служит дескриптор контекста устройства hDC и связанные с ним шрифт, перо и кисть. В состав VCL входят объектно-ориентированные надстройки над последними, назначением которых является удобный доступ к свойствам инструментов и прозрачная для пользователя обработка всех их изменений. Сначала опишем три этих класса.
Класс TFont
Класс инкапсулирует шрифт Windows. В Borland C++ Builder допускаются только горизонтально расположенные шрифты. В конструк-
12
торе объекта по умолчанию принимается шрифт System цвета clWindowText размера 10 пунктов.
Свойства класса приведены в таблице:
-----------------------------------------------------------------
Handle |
Содержит дескриптор шрифта. |
|
|
|
|||||
Name |
Содержит |
имя |
(начертание) |
|
шрифта, |
||||
|
например, Arial |
|
|
|
|
|
|||
Style |
Содержит |
|
стиль |
(особенности |
|||||
|
начертания) шрифта: жирный, курсив, |
||||||||
|
подчеркнутый и перечеркнутый. |
|
|
||||||
Color |
Определяет цвет шрифта. |
|
|
|
|
||||
Pitch |
Определяет |
способ |
установки |
ширины |
|||||
|
символов шрифта. Значение fpFixed |
со |
|||||||
|
ответствует |
моноширинным |
шрифтам; |
||||||
|
fpVariable - шрифтам с переменной |
||||||||
|
шириной символа. Установка fpDefault |
||||||||
|
означает принятие того способа, |
||||||||
|
который определен начертанием. |
|
|
||||||
Height |
Содержит значение высоты шрифта в |
||||||||
|
пикселах. |
|
|
|
|
|
|
|
|
PixelsPerInch |
Определяет |
число |
точек |
|
на |
дюйм. |
|||
|
Первоначально |
равно числу |
точек |
на |
|||||
|
дюйм |
в контексте экрана. Программист |
|||||||
|
не |
должен изменять это свойство, |
т. |
||||||
|
к. |
оно |
используется |
системой |
для |
||||
|
приведения |
изображения на |
экране |
и |
|||||
|
принтере к одному виду |
|
|
|
|
||||
Size |
Содержит |
размер |
шрифта |
в |
|
пунктах |
|||
|
(принято в Windows). Это свойство |
||||||||
|
связано с Height соотношением. |
|
|
||||||
|
Font->Size = -Font->Height * 72 / |
|
|||||||
|
|
|
|
Font->PixelsPerInch; |
|
-----------------------------------------------------------------
Класс ТРеn
Инкапсулирует перо. В конструкторе по умолчанию создается непрерывное (psSolid) черное перо шириной в один пиксел. Свойства класса приведены в таблице:
-----------------------------------------------------------------
Handle |
Содержит дескриптор пера. |
|
|
||
Color |
Определяет цвет пера. |
|
|
||
Mode |
Содержит |
идентификатор одной |
из |
||
|
растровых |
|
операций, |
которые |
|
|
определяют взаимодействие пера |
с |
|||
|
поверхностью. |
Эти |
операции |
||
|
соответствуют |
стандартным, |
|||
|
определенным в Windows |
|
|
||
Style |
Определяет стиль линии, |
рисуемой |
|||
|
пером. |
Соответствующие |
стили |
|
также определены в Windows |
Width |
Содержит значение толщины пера в |
|
пикселах |
-----------------------------------------------------------------
Класс TBrush
Инкапсулирует кисть. Первоначально создается белая сплошная (bsSolid) кисть. Свойства класса приведены в таблице:
-----------------------------------------------------------------
Handle |
Содержит дескриптор кисти. |
|
||
Color |
Определяет цвет кисти. |
|
|
|
Style |
Содержит |
стиль кисти |
(фактуру |
|
|
закраски). |
|
|
|
Bitmap |
Содержит |
битовую |
карту, |
|
|
определенную пользователем |
для |
||
|
закраски поверхностей. Если это |
|||
|
свойство определено, то |
Color |
и |
|
|
Style недействительны |
|
|
-----------------------------------------------------------------
Шрифт, перо и кисть, как правило, используются не самостоятельно, а в составе специального класса, который и будет сейчас рассмотрен.
Класс TCanvas
Этот класс - сердцевина графической подсистемы Borland C++ Builder. Он объединяет в себе и "холст" (контекст конкретного устройства GDI), и рабочие инструменты" (перо, кисть, шрифт) и даже "подмастерьев" (набор функций по рисованию типовых геометрических фигур).
В дальнейшем для обозначения этого класса мы будем пользоваться термином 'канва". Канва не является компонентом, но она входит в качестве свойства во многие другие компоненты, которые должны уметь нарисовать себя и отобразить какую-либо информацию. Дескриптор контекста устройства, над которым "построена" канва, может быть востребован для различных низкоуровневых операций. Он задается свойством:
__property HDC Handle = {read =GetHandle, write=SetHandle, nodefault};
Для рисования канва включает в себя шрифт, перо и кисть:
__property TFont* Font = {read=FFont, write=SetFont}; __property TPen* Pen = {read=FPen, write =SetPen}; __property TBrush* Brush = {read=FBrush, write=SetBrush};
Кроме того, можно рисовать и поточечно, получив доступ к каждому пикселу. Значение свойства
__property TColor Pixels[int X][int Y] = {read=GetPixel, write=SetPixel};
соответствует цвету точки с координатами (X,Y).
Канва содержит методы-надстройки над всеми основными функциями рисования GDI Windows и свойства, которые приведены ниже в таблице. При их рассмотрении имейте в виду, что все геометрические фигуры рисуются текущим пером. Те из них, которые можно зак-
13
рашивать, закрашиваются с помощью текущей кисти. Кисть и перо при этом имеют текущий цвет.
------------------------------------------------------------------
void |
__fastcall Arc(int X1, |
int¦Метод |
рисует сегмент |
эллипса. |
||||||||||
Y1, int X2, int Y2, int X3, |
int¦Эллипс |
определяется описывающим |
||||||||||||
Y3, int X4, int Y4); |
|
¦прямоугольником |
(X1,Y1) |
- |
||||||||||
|
|
|
|
|
¦(X2,Y2); |
его |
|
размеры |
должны |
|||||
|
|
|
|
|
¦лежать в диапазоне от 2 до 32767 |
|||||||||
|
|
|
|
|
¦точек. Начальная точка |
сегмента |
||||||||
|
|
|
|
|
¦лежит на |
пересечении эллипса |
и |
|||||||
|
|
|
|
|
¦луча, проведенного из его центра |
|||||||||
|
|
|
|
|
¦через |
точку |
(X3,Y3). Конечная |
|||||||
|
|
|
|
|
¦точка |
сегмента |
|
лежит |
|
на |
||||
|
|
|
|
|
¦пересечении |
|
эллипса |
|
и |
луча, |
||||
|
|
|
|
|
¦проведенного из его центра через |
|||||||||
|
|
|
|
|
¦точку (X4,Y4). Сегмент |
рисуется |
||||||||
|
|
|
|
|
¦против часовой стрелки. |
|
|
|
||||||
void |
__fastcall |
Chord(int |
X1,¦Рисует |
хорду |
и |
|
заливает |
|||||||
int |
Y1, int X2, int Y2, int |
X3,¦отсекаемую |
ею |
часть |
|
эллипса. |
||||||||
int Y3, int X4, int Y4); |
|
¦Эллипс, |
начальная |
и |
конечная |
|||||||||
|
|
|
|
|
¦точки определяются, как в методе |
|||||||||
|
|
|
|
|
¦Arc. |
|
|
|
|
|
|
|
|
|
void |
__fastcall Ellipse(int |
X1,¦Рисует |
и |
закрашивает |
эллипс, |
|||||||||
int Y1, int X2, int Y2); |
|
¦вписанный в прямоугольник (X1 |
||||||||||||
|
|
|
|
|
¦,Y1) - (X2,Y2). |
|
|
|
|
|
||||
void |
__fastcall |
LineTo(int |
X,¦Проводит |
линию текущим пером из |
||||||||||
int Y); |
|
|
|
¦текущей точки в (X,Y). |
|
|
|
|||||||
void |
__fastcall |
MoveTo(int |
X,¦Перемещает |
текущее |
|
положение |
||||||||
int Y); |
|
|
|
¦пера |
(свойство PenPos) в |
точку |
||||||||
|
|
|
|
|
¦(X,Y). |
|
|
|
|
|
|
|
|
|
void __fastcall BrushCopy(const¦Производит |
|
|
|
специальное |
||||||||||
Windows::TRect &Dest, |
TBitmap*¦копирование. |
|
|
Прямоугольник |
||||||||||
Bitmap, |
const |
Windows::TRect¦Source |
из битовой карты |
Bitmap |
||||||||||
&Source, TColor Color); |
|
¦копируется в прямоугольник Dest |
||||||||||||
|
|
|
|
|
¦на |
канве; |
при этом |
цвет Color |
||||||
|
|
|
|
|
¦заменяется на цвет текущей кисти |
|||||||||
|
|
|
|
|
¦(Brush->Color). С |
помощью этого |
||||||||
|
|
|
|
|
¦метода |
|
можно |
|
нарисовать |
|||||
|
|
|
|
|
¦"прозрачную" картинку. Для этого |
|||||||||
|
|
|
|
|
¦нужно выбрать |
|
соответствующий |
|||||||
|
|
|
|
|
¦фону цвет кисти и затем заменить |
|||||||||
|
|
|
|
|
¦на |
него |
фоновый |
или |
наиболее |
|||||
|
|
|
|
|
¦часто встречающийся цвет битовой |
|||||||||
|
|
|
|
|
¦карты (см. TransparentColor). |
|
||||||||
void |
__fastcall |
CopyRect(const¦Производит |
|
|
|
копирование |
||||||||
Windows:: |
TRect &Dest, |
TCanvas*¦прямоугольника Source |
|
из |
канвы |
|||||||||
Canvas, |
const |
Windows::TRect¦Canvas |
в прямоугольник |
Dest |
в |
|||||||||
&Source); |
|
|
|
¦области самого объекта. |
|
|
|
|||||||
void |
__fastcall |
FillRect(const¦Производит |
|
|
|
|
заливку |
|||||||
Windows:: TRect &Rect); |
|
¦прямоугольника (текущей кистью). |
||||||||||||
void __fastcall FrameRect(const¦Производит, |
|
|
оконтуривание |
|||||||||||
Windows:: TRect &Rect); |
|
¦прямоугольника |
цветом |
текущей |
||||||||||
|
|
|
|
|
¦кисти (без заполнения). |
|
|
|
||||||
void |
__fastcall Draw(int X, |
int¦Осуществляет |
|
|
|
|
рисование |
|||||||
Y, TGraphic* Graphic); |
|
¦графического |
|
объекта |
|
Graphic |
||||||||
|
|
|
|
|
¦(точнее, |
вызов |
метода |
|
его |
|||||
|
|
|
|
|
¦рисования) в области |
с |
верхним |
|||||||
|
|
|
|
|
¦левым углом (X,Y). |
|
|
|
|
|||||
void __fastcall |
|
|
¦Осуществляет рисование |
объекта |
||||||||||
StretchDraw(const Windows::TRect ¦Graphic |
|
|
в |
|
|
заданном |
&Rect, TGraphic* Graphic); |
¦прямоугольнике |
Rect. |
|
Если |
|||||||||
|
|
|
|
|
|
¦размеры их не совпадают, Graphic |
|||||||
|
|
|
|
|
|
¦масштабируется. |
|
|
|
|
|||
void |
|
|
|
|
__fastcall¦Производит |
|
|
отрисовку |
|||||
DrawFocusRect(const |
|
¦прямоугольной рамки |
из |
точек |
|||||||||
Windows::TRect &Rect); |
¦(как |
на элементе, имеющем фокус |
|||||||||||
|
|
|
|
|
|
¦ввода). |
|
Поскольку |
метод |
||||
|
|
|
|
|
|
¦использует логическую |
операцию |
||||||
|
|
|
|
|
|
¦xor (исключающее ИЛИ), повторный |
|||||||
|
|
|
|
|
|
¦вызов для того же прямоугольника |
|||||||
|
|
|
|
|
|
¦приводит |
изображение |
|
к |
||||
|
|
|
|
|
|
¦начальному виду. |
|
|
|
|
|||
void __fastcall FloodFill(int |
X,¦Производит |
заливку |
области |
||||||||||
int |
Y, |
TColor Color, TFillStyle¦текущей |
|
кистью. |
|
Процесс |
|||||||
FillStyle); |
|
|
|
¦начинается |
с точки |
(X,Y). Если |
|||||||
|
|
|
|
|
|
¦режим FillStyle равен fsSurface, |
|||||||
|
|
|
|
|
|
¦то |
он продолжается до тех |
пор, |
|||||
|
|
|
|
|
|
¦пока |
есть |
соседние |
точки |
с |
|||
|
|
|
|
|
|
¦цветом Color. В режиме |
fsBorder |
||||||
|
|
|
|
|
|
¦закрашивание, |
|
наоборот, |
|||||
|
|
|
|
|
|
¦прекращается |
при |
|
выходе |
на |
|||
|
|
|
|
|
|
¦границу с цветом Color. |
|
|
|||||
void |
__fastcall Pie(int X1, |
int¦Рисует |
|
сектор |
|
эллипса, |
|||||||
Y1, |
int X2, int Y2, int X3, |
int¦описываемого |
прямоугольником |
||||||||||
Y3, int X4, int Y4); |
|
¦(X1,Y1) |
- |
(X2,Y2). |
Стороны |
||||||||
|
|
|
|
|
|
¦сектора |
лежат |
на |
лучах, |
||||
|
|
|
|
|
|
¦проходящих |
из центра |
эллипса |
|||||
|
|
|
|
|
|
¦через точки (X3,Y3) и (X4,Y4). |
|||||||
void __fastcall Polygon(const¦Строит |
многоугольник, используя |
||||||||||||
tagPOINT |
* |
Points, |
const |
int¦массив |
координат точек |
Points. |
|||||||
Points_Size); |
|
|
|
¦При |
|
этом |
последняя |
точка |
|||||
|
|
|
|
|
|
¦соединяется |
с |
|
первой |
и |
|||
|
|
|
|
|
|
¦внутренняя область закрашивается |
|||||||
void |
__fastcall |
Polyline(const¦Строит |
ломаную линию, используя |
||||||||||
tagPOINT |
* |
Points, |
const |
int¦массив координат точек Points. |
|||||||||
Points_Size); |
|
|
|
¦ |
|
|
|
|
|
|
|
||
void |
__fastcall |
|
Rectangle(int¦Рисует |
прямоугольник с верхним |
|||||||||
X1, int Y1, int X2, int Y2); |
¦левым |
углом в (X1, Y1) и нижним |
|||||||||||
|
|
|
|
|
|
¦правым в (X2, Y2). |
|
|
|
|
|||
void |
__fastcall |
|
RoundRect(int¦Рисует |
|
прямоугольник |
с |
|||||||
X1, int Y1, int X2, int Y2, |
int¦закругленными углами. Координаты |
||||||||||||
X3, int Y3); |
|
|
|
¦вершин - те же, что и в |
методе |
||||||||
|
|
|
|
|
|
¦Rectangle. Закругления |
рисуются |
||||||
|
|
|
|
|
|
¦как сегменты эллипса с размерами |
|||||||
|
|
|
|
|
|
¦осей по |
горизонтали и вертикали |
||||||
|
|
|
|
|
|
¦X3 и Y3. |
|
|
|
|
|
||
int |
__fastcall |
TextHeight(const¦Возвращает высоту строки |
Text в |
||||||||||
System:: AnsiString Text); |
¦пикселах. |
|
|
|
|
|
|||||||
int |
__fastcall |
TextWidth(const¦Возвращает ширину строки |
Text в |
||||||||||
System:: AnsiString Text); |
¦пикселах. |
|
|
|
|
|
|||||||
void |
__fastcall |
TextOut(int |
X,¦Производит вывод строки Text. |
||||||||||
int |
Y, |
const System::AnsiString¦Левый |
верхний угол помещается в |
||||||||||
Text); |
|
|
|
|
¦точку канвы (X.Y). |
|
|
|
|
||||
void |
__fastcall |
TextRect(const¦Производит |
вывод |
|
текста |
с |
|||||||
Windows:: |
TRect |
&Rect, int |
X,¦отсечением. Как и в |
TextOut, |
|||||||||
int |
Y, |
const System::AnsiString¦строка |
Text выводится с позиции |
||||||||||
Text); |
|
|
|
|
¦(X,Y); |
при |
этом |
часть текста, |
|||||
|
|
|
|
|
|
¦лежащая |
|
вне |
|
|
пределов |
||
|
|
|
|
|
|
¦прямоугольника Rect, |
отсекается |
||||||
|
|
|
|
|
|
¦и не будет видна. |
|
|
|
|
14
__property tagPOINT |
PenPos =¦Содержит |
текущую |
позицию пера |
{read |
=GetPenPos,¦канвы |
(изменяется |
посредством |
write=SetPenPos}; |
¦метода MoveTo). |
|
-----------------------------------------------------------------
Метод
void __fastcall Refresh(void);
сбрасывает текущие шрифт, перо и кисть, заменяя их на стандарт-
ные, заимствованные из Windows (BLACK_PEN, HOLLOW_BRUSH, SYS-
TEM_FONT). Предусмотрено два события дня пользовательской реакции на изменение канвы: OnChange и OnChanging . Эти события возникают при изменениях свойств и вызовах методов TCanvas, меняющих вид канвы (то есть при любом рисовании. В MoveTo, например, они не возникают). Отличие их в том, что OnChanging вызывается до начала изменений, a OnChange - после их завершения.
Идентификатор (код) растровой операции при копировании прямоугольных блоков содержится в свойстве CopyMode и определяет правило сочетания пикселов, копируемых на канву, с ее текущим содержимым. При этом можно создавать разные изобразительные эффекты. В Borland C++ Builder определены следующие константы кодов: cmBlackness, cmDstInvert. cmMergeCopy, cmMergePaint, cmNotSrcCopy, cmNotSrcErase, cmPatCopy, cmPatInvert, cmPatPaint, cmSrcAnd, cmSrcCopy, cmSrcErase, cmSrcInvert, cmSrcPaint, cmWhiteness. Все они стандартно определены в Windows, и подробное их описание можно найти в документации по GDI. Значением CopyMode по умолчанию является cmSrcCopy - копирование пикселов источника поверх существующих.
Помимо графических примитивов, таких как линии и фигуры, на канве можно разместить готовые изображения. Для их описания создан класс TGraphic. Этот абстрактный класс является родительским для трех видов изображений, общепринятых в графике Windows - значка (класс TIcon), метафайла (класс TMetafile) и растровой картинки (класс TBitmap).
Работая над приложением в Borland C++ Builder, вы никогда не будете создавать объекты класса TGraphic, но переменной этого типа вы можете присваивать указатель на любой из классов-потомков.
Метод
virtual void __fastcall Assign(Classes:: TPersistent* Source);
переопределяет одноименный метод предка, позволяя полиморфное присваивание графических объектов (см. ниже).
Загрузку и выгрузку графики в поток осуществляют методы
virtual void __fastcall LoadFromStream(Classes:: TStream* Stream); virtual void __fastcall SaveToStream(Classes::TStream* Stream);
а загрузку и выгрузку в файл:
virtual void __fastcall LoadFromFile(const System:: AnsiString Filename);
virtual void __fastcall SaveToFile(const System:: AnsiString Filename);
Эти методы создают соответствующий файловый поток и затем вызывают методы LoadFromStream / SaveToStream.
Два метода осуществляют взаимодействие с буфером обмена: virtual void __fastcall LoadFromClipboardFormat(Word AFormat,
int AData, HPALETTE APalette);
virtual void __fastcall SaveToClipboardFormat(Word &Format,
int &Data, HPALETTE &APalette);
Здесь AFormat - используемый графический формат; AData и APalette - данные и палитра (если она требуется). Потомок должен иметь свой формат и уметь обрабатывать данные, представленные в нем. Свойство Empty устанавливается в true, если графический объект пуст (в него не загружались данные).
Высота и ширина графического объекта: Height, Width. Для каждого дочернего типа значения этих свойств вычисляются своим способом. Наконец, логическое свойство Modified показывает, модифицировался ли данный графический объект. Это свойство устанавливается в true внутри обработчика события OnChange.
Класс TPicture
Класс-надстройка над TGraphic, точнее - над его потомками. Он содержит поле Graphic, которое может содержать TBitmap, TIcon
иTMetafile. Предназначение TPicture - управлять вызовами соответствующих методов, скрывая при этом хлопоты с определением типа
идетали их реализации.
Кроме того, на уровне TPicture определены возможности по регистрации и использованию других - определенных пользователем - классов графических объектов, порожденных от TGraphic. Доступ к графическому объекту осуществляется посредством свойства: Graphic. Если графический объект имеет один из трех предопределенных типов, то к нему можно обратиться и как к одному из свойств Bitmap, Icon или Metafile.
Если в поле Graphic хранился объект одного класса, а затребован - другого, то прежний объект уничтожается, а вместо него создается пустой объект нужного класса.
Все три разновидности графических объектов имеют свои системы кэширования. Это означает, что на один реально существующий в системе дескриптор могут одновременно ссылаться несколько объектов. Более простым является кэширование для TIcon и TMetafile, которые умеют только отображать себя и не предназначены для редактирования (создатели Borland C++ Builder считают, что дескриптор графического объекта дается программисту не для того, чтобы ковыряться в нем на уровне двоичных кодов). Гораздо сложнее устроен механизм кэширования для TBitmap, который имеет свою канву для рисования.
Внутреннее представление информации в графических объектах двоякое - она может храниться как поток типа TMemoryStream (в него загружается содержимое соответствующего файла), как область памяти с дескриптором (структура которой зависит от типа графического объекта) и одновременно в двух этих видах, содержимое которых автоматически синхронизируется. Поэтому будьте готовы к тому, что загрузка изображения потребует вдвое большего объема памяти - особенно это актуально для больших картинок.
Кого-то может удивить отсутствие объявленных методов рисова-
ния вроде Draw у TIcon, TMetafile и TBitmap. Такие методы есть,
но они недоступны. Все рисование должно осуществляться через вызовы методов Draw и StretchDraw канвы, содержащей графику, ибо канва несет тот контекст, в котором должна осуществляться операция. Рассмотрим предопределенные графические классы.
Класс TMetaflle
Инкапсулирует свойства стандартного метафайла Windows. В нем перекрываются методы Assign, LoadFromStream, SaveToStream, LoadFromClipboardFormat, SaveToClipboardFormat. В буфер обмена объект помещает свое содержимое в формате CF_METAFILEPICT. Помимо общих, класс имеет свойства:
15
-----------------------------------------------------------------
Handle |
Дескриптор метафайла. |
|
|
|
Inch |
Число точек |
на |
дюйм |
в |
|
координатной системе |
метафайла. |
||
|
Связано с установленным режимом |
|||
|
отображения. |
|
|
|
-----------------------------------------------------------------
Класс TIcon Инкапсулирует значок Windows.
Не пытайтесь изменить размеры значка - они постоянны (равны
GetSystemMetrics(SM_CXICON) и GetSystemMetrics(SM_CYICON)), и при попытке присвоить новые значения возникает исключительная ситуация EInvalidGraphicOperation. Значок нельзя также читать и писать в буфер обмена так как в Windows нет соответствующего формата. В этом классе перекрываются методы класса ТGraphiс: Assign, LoadFromStream и SaveToStream. Дополнительно также определены:
-----------------------------------------------------------------
Handle |
Дескриптор значка. |
|
|
ReleaseHandle |
Метод |
"отдает" |
дескриптор |
|
- возвращает его значение, |
||
|
обнуляя ссылку на него в объекте |
-----------------------------------------------------------------
Класс TBitmap
Класс соответствует битовой карте, зависимой от устройства
(Device - dependent bitmap, DDB). В нем перекрываются методы Assign LoadFromClipboardFormat, LoadFromStream, SaveToClipboardFormat, SaveToStream. Объект взаимодействует с буфером обмена в фор-
мате CF_BITMAP.
Канва битовой карты доступна через свойство Canvas. Обратите внимание на то, что другие потомки TGraphic канвы
не имеют. С ее помощью можно рисовать на поверхности изображения. Дескрипторы битовой карты и ее палитры доступны как свойства
Handle и Palette.
Два метода
HBITMAP __fastcall ReleaseHandle(void);
HPALETTE __fastcall ReleasePalette(void);
возвращают дескрипторы битовой карты и палитры и после этого обнуляют соответствующие поля, т. е. как бы "отдают" дескрипторы пользователю.
При любом внешнем обращении к дескриптору битовой карты и любой попытке рисовать на ее канве, разделение одной картинки несколькими объектами прерывается, и объект получает свою отдельную копию содержимого дескриптора. Для этого есть методы:
void __fastcall Dormant(void); - выгружает изображение в поток и уничтожает дескрипторы битовой карты и палитры,
void __fastcall FreeImage(void); - "освобождает" дескриптор бито-
вой карты для дальнейшего использования и внесения изменений. Это означает, что если на данный дескриптор есть ссылки, то он дублируется; поток очищается.
Битовая карта может быть монохромной и цветной, что определено логическим свойством Monochrome. Значение true соответствует монохромной битовой карте. При его изменении происходит преобразование содержимого к требуемому виду.
"Фоновый" цвет битовой карты:
__property TColor TransparentColor = {read=GetTransparentColor, write=SetTransparentColor, stored=TransparentColorStored, nodefault};
Это тот цвет, который можно отменить в операции BrushCopy, чтобы она выглядела прозрачной. Для монохромной карты этот цвет - белый.
Функции для работы с графикой
-------------------------------------------------------------------
extern |
|
PACKAGE¦Эту функцию |
удобно |
использовать |
|||||
System::AnsiString |
__fastcall¦вместе |
с |
диалогами |
открытия |
и |
||||
GraphicFilter(System:: |
|
¦закрытия |
файла. |
Для |
заданного |
||||
TMetaClass* GraphicClass); |
¦класса |
|
GraphicClass |
она |
вернет |
||||
|
|
¦строку, |
|
которую |
сразу |
можно |
|||
|
|
¦присвоить |
|
свойству |
|
Filter |
|||
|
|
¦диалога. |
Например, |
для |
TBitmap |
||||
|
|
¦она |
вернет |
строку |
|
'Bitmaps |
|||
|
|
¦(.ВМР)|*.ВМР' |
|
|
|
|
|
||
extern |
|
PACKAGE¦Возвращает |
строку, |
содержащую |
|||||
System::AnsiString |
__fastcall¦расширение, которое встречается |
у |
|||||||
GraphicExtension(System:: |
¦файлов |
|
в формате |
GraphicClass. |
|||||
TMetaClass* GraphicClass); |
¦Например, |
GraphicExtension(TIcon) |
|||||||
|
|
¦равно строке 'ICO'. |
|
|
|
|
|||
extern PACKAGE int |
__fastcall¦Преобразует |
значение типа |
TColor |
||||||
ColorToRGB(Tcolor Color); |
¦в формат RGB. |
|
|
|
|
|
extern PACKAGE bool __fastcall¦Функции взаимного преобразования
ColorToIdent(int |
Color,¦цвета |
в |
строку с его |
названием. |
||||
System::AnsiString &Ident); |
¦Например, |
ColorToIdent(clWhite, |
||||||
extern PACKAGE bool __fastcall¦AString) |
присвоит |
|
AString |
|||||
IdentToColor(const |
|
¦значение |
"clWhite". |
В |
случае |
|||
System::AnsiString |
Ident, |
int¦неуспеха возвращается false |
|
|||||
&Color); |
|
¦ |
|
|
|
|
|
|
extern PACKAGE |
|
¦Назначение |
|
аналогично |
двум |
|||
System::AnsiString __fastcall |
¦предыдущим |
|
функциям. |
|
При |
|||
ColorToString(TColor Color); |
¦отсутствии |
цвета Color |
в списке |
|||||
extern PACKAGE TColor __fastcall¦предопределенных |
|
цветов |
||||||
StringToColor(const |
|
¦возвращается |
строка |
|
с |
его |
||
System::AnsiString S); |
¦значением |
в |
шестнадцатеричном |
|||||
|
|
¦формате. |
При отсутствии |
цвета |
с |
|||
|
|
¦именем |
S |
(в |
том |
же |
списке) |
|
|
|
¦делается |
попытка преобразовать |
|||||
|
|
¦строку |
в число, в случае |
неудачи |
||||
|
|
¦возникает |
|
исключительная |
||||
|
|
¦ситуация. |
|
|
|
|
|
|
extern PACKAGE void __fastcall¦Производит |
вызов |
определенной |
||||||
GetColorValues(Classes::TGetStrP ¦пользователем процедуры |
Proc |
для |
||||||
roc &Proc); |
|
¦всех имеющихся в списке цветов. |
В |
|||||
|
|
¦качестве |
параметра |
в |
такую |
|||
|
|
¦процедуру |
передается |
строка |
с |
|||
|
|
¦именем цвета. |
|
|
|
|
--------------------------------------------------------------------
Для преобразования битовой карты из зависимого от устройства формата DDB в независимый (DIB) предназначены две функции:
--------------------------------------------------------------------
extern PACKAGE void |
__fastcall¦Возвращает |
размер |
заголовка |
GetDIBSizes(HBITMAP |
Bitmap, int¦изображения |
и размер |
самого |
&InfoHeaderSize, |
int¦изображения. |
|
Значение |
&ImageSize); |
¦InfoHeaderSize |
равно |
размеру |
|
¦структуры TBitmapInfoHeader плюс, |
16
|
¦при |
необходимости, |
размеру |
||
|
¦палитры (каждый элемент которой |
||||
|
¦TRGBQuad занимает 4 байта). |
В |
|||
|
¦ImageSize |
возвращается количество |
|||
|
¦байт, |
которое нужно |
отвести |
для |
|
|
¦получения изображения в формате |
||||
|
¦DIB. |
|
|
|
|
|
¦ |
|
|
|
|
extern PACKAGE bool __fastcall¦Преобразует |
DDB (определенную |
||||
GetDIB(HBITMAP Bitmap, HPALETTE¦через Bitmap и Palette) в DIB. |
|||||
Palette, |
void *BitmapInfo, void¦Заголовок |
помещается |
в |
||
*Bits); |
¦BitmapInfo, |
а сами |
данные |
- в |
|
|
¦Bits. |
|
|
|
|
-------------------------------------------------------------------
Визуальные компоненты для работы с графическими объектами
Компонент TPaintBox
Самой простой надстройкой над канвой служит компонент TPaintBox, предназначенный для рисования. Можно даже рассматривать его как канву, снабженную атрибутами компонента. Она представлена свойством Canvas.
Помимо канвы, компонент имеет свой цвет (фона) Color и шрифт Font. Изобразить на канве компонента что-либо можно, предусмотрев обработчик события OnPaint.
Компонент TShape
Этот компонент предназначен только для того, чтобы нарисовать и показать на своей поверхности простейшую геометрическую фигуру:
__property TShapeType |
Shape = {read = FShape, write=SetShape, |
||
|
|
|
default=0}; |
Рисуемая фигура - одна из предопределенных в множестве: |
|||
enum |
TShapeType |
{ |
stRectangle, stSquare, stRoundRect, |
stRoundSquare, stEllipse, stCircle };
Размеры фигуры соответствуют размерам компонента. Если задан квадрат или круг, а ширина и высота компонента не равны между собой, то сторона или диаметр фигуры будут равны длине меньшей стороны компонента.
Кисть и перо, которыми рисуется и закрашивается фигура, представлены свойствами Brush и Pen.
Компонент TImage
Этот компонент служит надстройкой над классом TPicture и замыкает всю иерархию графических объектов VCL. Он предназначен для показа на форме изображения: битовой карты (TBitmap), метафайла
(TMetafile), значка (TIcon).
Свойство
__property Graphics::TPicture* Picture = {read=FPicture, write=SetPicture};
служит контейнером для графического объекта одного из перечисленных классов.
В качестве канвы используется канва объекта Graphic - только если поле Graphic ссылается на объект класса Tbitmap.
Если это не так, то попытка обращения к свойству вызовет исключительную ситуацию EInvalidOperation, так как рисовать на метафайле или значке нельзя. Будьте внимательны с этим свойством.
Следующие три свойства определяют, как именно TPicture располагается в рабочей области компонента:
__property bool AutoSize = {read=FAutoSize, write=SetAutoSize, default=0}; - означает, что размеры компонента настраиваются по размерам содержащегося в нем графического объекта. Устанавливать его в True нужно перед загрузкой изображения из файла или буфepa обмена;
__property bool Stretch = {read=FStretch, write=SetStretch, default=0}; - если это свойство установлено в True, то изображение "натягивается" на рабочую область, при необходимости уменьшая или увеличивая свои размеры. Если оно установлено в False, то играет роль следующее свойство;
__property bool Center = {read=FCenter, write=SetCenter, default=0}; - если это свойство установлено в True, изображение центрируется в пределах рабочей области. В противном случае - располагается в ее верхнем левом углу.
Графическое представление результатов расчета с помощью визуального компонента VCL CHART FX
Создание простой диаграммы
Диаграмма создается таким же образом, как и любой из визуальных компонентов. Во время разработки компонент Chart FX выбирается со страницы ActiveX палитры компонентов, размещается на форме, после чего устанавливаются его начальные свойства. Для установки свойств компонента используется специализированный мастер свойств. Один компонент способен отображать несколько графиков, называемых сериями.
Изначально на диаграмме отображаются случайные данные. Поэтому как только Вы создали диаграмму, необходимо по крайней мере определить данные, которые должны быть отображены.
Чтобы определить данные, которые будут показаны, следует использовать свойство Value - массив с плавающей точкой:
Chart1->Value[nPoint] = dValue;
т.е. dValue является значением точки nPoint в серии, указанной свойством ThisSerie.
// Серия 0 , Точка 3 , Значение 10.5
Chart1->ThisSerie = 0;
Chart1->Value[3] = 10.5;
Однако перед использованием этого свойства Вы должны убедиться, что канал связи к библиотеке должным образом открыт. Это реализуется парой методов OpenDataEx и CloseData.
Таким образом, установка данных будет выглядеть следующим образом:
//Открыть канал ЗНАЧЕНИЙ, определяющий 2 серии и 7 точек
Chart1->OpenDataEx(COD_VALUES,2, 7);
//Код, чтобы установить данные
Chart1->ThisSerie = 0;
for (i = 0; i < 7; ++i)
17
Chart1->Value[i] = 9;
Chart1->ThisSerie = 1;
for (i = 0; i < 7; ++i) Chart1->Value[i] = 15;
// Закрыть канал ЗНАЧЕНИЙ
Chart1->CloseData(COD_VALUES);
Изменение данных существующей диаграммы
Как только диаграмма создана, Вы можете изменять любое из отображенных значений, используя свойства, описанные ранее: OpenDataEx, Value, CloseData.
Запрос OpenDataEx с новом числом серий и точек уничтожит существующие данные и будет готовить канал связи, чтобы получить новые данные.
//Открыть канал ЗНАЧЕНИЙ, определяющий 4 серии и 8 точек
Chart1->OpenDataEx(COD_VALUES, 4, 8);
//Код, чтобы установить данные
for (i = 0; i < 4; ++i)
{
Chart1->ThisSerie = i; for (j = 0; j < 8; ++j)
Chart1->Value[j] = 12;
}
// Закрыть канал ЗНАЧЕНИЙ
Chart1->CloseData(COD_VALUES);
Если Вы только хотите изменить значения без изменения числа точек или серий, можно использовать флажок COD_UNCHANGE:
Chart1->OpenDataEx(COD_VALUES,COD_UNCHANGE COD_UNCHANGE);
// Изменяют произвольную точку
Chart1->ThisSerie = 1;
Chart1->Value[4] = 10.5;
// Закрыть канал ЗНАЧЕНИЙ
Chart1->CloseData(COD_VALUES);
Изменение условных обозначений и заголовков
Чтобы изменять заголовки диаграммы, Вы можете устанавливать свойство Title с кодом заголовка в индексе, как показано ниже:
// Устанавливает или Изменяет заголовки диаграммы
Chart1->Title[CHART_LEFTTIT] = "Revenues"; Chart1->Title[CHART_BOTTOMTIT] = "Months";
Чтобы изменять легенды диаграммы, используется свойство Legend для описания легенды аргумента X и свойство SerLeg для легенды серии:
Chart1->Legend[0] = "Jan";
Chart1->Legend[1] = "Feb";
Chart1->Legend[2] = "Mar";
Chart1->Legend[3] = "Apr";
Chart1->SerLeg[0] = "Sales";
Chart1->SerLeg[1] = "Revenues";
Хотя библиотека Chart FX разрешает пользователю менять заголовки, это может быть ограничено двумя способами:
-Созданием диаграммы без CS_TITLES стиля.
-Использованием свойства Style.
Изменение визуальных атрибутов диаграммы
Chart FX обеспечивает 3 режима для отображения графики:
-2D режим
-3D "простой" режим
-3D с углами вращения
По умолчанию задается 2D-режим, однако Вы можете отменять это значение по умолчанию и устанавливать трехмерный "простой" режим при проектировании и времени выполнения, используя Свойства Type или Chart3D следующим образом:
// Чтобы установить трехмерный простой режим
Chart1->Chart3D = true;
Чтобы устанавливать полный трехмерный режим представления, диаграмма должна быть в трехмерном "простом" режиме и нуждается в следующих запросах:
/*
Чтобы установить 3D-режим с 30 точками по оси X и 60 точками по оси Y
*/
Chart1->View3D = true; Chart1->Angles3D = MAKELONG(30,60);
// Чтобы удалить 3D-режим
Chart1->View3D = false;
Установка цветовых схем, сетки и цветов фона
Цветовая схема описывает способ, который используется Chart FX для раскраски линий, точек, секторов круга, и т.д. Схема может быть Solid (твердые цвета), BW Patterns (черно-белые модели) и Patterns (цветные модели).
Сетка описывает горизонтальные и вертикальные линии диаграм-
мы.
Цвета фона - для вывода различных фонов в диаграмме.
// Установим цветовую схему
Chart1->Scheme = CHART_CSPATTERN;
// Установим сетку
Chart1->Grid = CHART_HORZGRID;
// Установим цвета фона
Chart1->RGBBk = RGB(0,255,0); Chart1->RGB2DBk = RGB(200,20,90);
18
Chart1->RGB3DBk = RGB(200,20,90);
Изменение шрифтов
Хотя Chart FX использует по умолчанию шрифт Arial 8 для отображения заголовков, условных обозначений и других текстов в диаграмме, программист может изменять любой из шрифтов, использованных библиотекой через свойства hFont и RGBFONT. Имеются два способа, которыми программист может определить шрифт:
Ограниченный Режим (свойство Font). В этом режиме программист с помощью поразрядного ИЛИ определяет флажки, который задают шрифт: гарнитура (CF_ARIAL, CF_TIMES, и т.д.), эффекты (CF_BOLD, CF_ITALIC, и т.д.) семейство (CF_FDONTCARE, CF_FSWISS, и т.д.) и
размер шрифта в точках.
Свободный Режим (свойство hFont). В этом режиме программист передает библиотеке дескриптор предварительно созданного шрифта (тип HFONT). В этом режиме на программиста возлагается ответственность за создание и уничтожение шрифта, используя функции
Windows (CreateFont и DeleteObject)
// Установка заголовка
Chart1->Title[CHART_BOTTOMTIT] = "Times Font";
// Изменение шрифта заголовка
Chart1->Font[CHART_BOTTOMFT] = CF_TIMES | CF_BOLD | 12;
// Изменение цветов для вывода шрифта
Chart1->RGBFont[CHART_BOTTOMFT] = RGB(255,0,0);
Создание инструментальных средств и других визуальных элементов
Chart FX предоставляет пользователю 4 инструментальных средства Windows, которые предлагают простой и интуитивный путь изменения некоторых из характеристик диаграммы:
Окно |
Флажок |
Используется для ... |
ToolBar |
CT_TOOL |
изменения трехмерного представления, |
|
|
типа графика, сетки и так далее. |
LegendBar |
CT_LEGEND |
управления легендами серий и оси |
|
|
аргумента X. |
PaletteBar |
CT_PALETTE |
управления цветами |
PatternBar |
CT_PATTERN |
управления заполнением |
С точки зрения программистов возможности, предоставляемые этими инструментальными средствами, полностью прозрачны и могут быть настроены двумя способами: во время разработки установкой соответствующих флагов в свойстве Type, во время выполнения использованием свойства Type_ соответственно.
Chart1->Type_ = BAR | CT_TOOL | CT_LEGEND;
РАСТРОВАЯ ГРАФИКА
Для работы с устройствами растровой графики нужны специальные методы генерации изображения, вычерчивания прямых и кривых линий, закраски многоугольников, создающей впечатление сплошных объектов.
АЛГОРИТМЫ ВЫЧЕРЧИВАНИЯ ОТРЕЗКОВ
Поскольку экран растрового дисплея с электронно-лучевой
трубкой (ЭЛТ) можно рассматривать как матрицу дискретных элементов (пикселов), каждый из которых может быть подсвечен, нельзя непосредственно провести отрезок из одной точки в другую. Процесс определения пикселов, наилучшим образом аппроксимирующих заданный отрезок, называется разложением в растр. В сочетании с процессом построчной визуализации изображения он известен как преобразование растровой развертки. Для горизонтальных, вертикальных и наклоненных под углом 45° отрезков выбор растровых элементов очевиден. При любой другой ориентации выбрать нужные пикселы труднее.
Прежде чем приступать к обсуждению конкретных алгоритмов рисования отрезков, полезно рассмотреть общие требования к таким алгоритмам и ответить на вопрос, каковы желаемые характеристики изображения. Очевидно, что отрезки должны выглядеть прямыми, начинаться и заканчиваться в заданных точках. Далее, яркость вдоль отрезка должна быть постоянной и не зависеть от длины и наклона. Наконец, рисовать нужно быстро. Как это часто бывает, не все из перечисленных критериев могут быть полностью удовлетворены. Сама природа растрового дисплея исключает генерацию абсолютно прямых линий (кроме ряда специальных случаев), равно как и точное совпадение начала и конца отрезка с заданными точками. Тем не менее при достаточно высоком разрешении дисплея можно получить приемлемую аппроксимацию.
Постоянная вдоль всего отрезка яркость достигается лишь при проведении горизонтальных, вертикальных и наклоненных под углом 45° прямых. Для всех других ориентаций разложение в растр приведет к неравномерной яркости. Даже для частных случаев яркость зависит от наклона: заметим например, что расстояние между соседними пикселами для отрезка под углом 45° больше, чем для вертикальных и горизонтальных прямых. Поэтому вертикальные и горизонтальные отрезки будут выглядеть ярче, чем наклонные. Обеспечение одинаковой яркости вдоль отрезков разных длин и ориентаций требует извлечения квадратного корня, а это замедлит вычисления. Обычным компромиссом является нахождение приближенной длины отрезка, сведение вычислений к минимуму, предпочтительное использование целой арифметики, а также реализация алгоритмов на аппаратном или микропрограммном уровне.
В большинстве алгоритмов вычерчивания отрезков для упрощения вычислений используется пошаговый метод. Приведем пример подобного алгоритма:
Простой пошаговый алгоритм позиция = начало шаг = приращение
1If позиция - конец < точность then 4 If позиция > конец then 2
позиция < конец then 3
2позиция = позиция - шаг gоto 1
3позиция = позиция + шаг goto 1
4finish
ЦИФРОВОЙ ДИФФЕРЕНЦИАЛЬНЫЙ АНАЛИЗАТОР
Один из методов разложения отрезка в растр состоит в решении дифференциального уравнения, описывающего этот процесс. Для прямой линии имеем
dy/dx = const
19
или
dy/dx = (Y2-Y1)/(X2-X1)
Решение представляется в виде
Yi+1 = Yi + dy
Yi+1 = Yi +(Y2-Y1)/(X2-X1) * dx
где X1, Y1 и X2, Y2концы разлагаемого отрезка и Yi - начальное значение для очередного шага вдоль отрезка. Фактически уравнение представляет собой рекуррентное соотношение для последовательных значений Y вдоль нужного отрезка. Этот метод, используемый для разложения в растр отрезков, называется цифровым дифференциальным анализатором (ЦДА). В простом ЦДА либо dx, либо dy (большее из приращений) выбирается в качестве единицы растра. Ниже приводится простой алгоритм, работающий во всех квадрантах:
/*
Предполагается, что концы отрезка (X1, Y1) и (X2, Y2) не совпадают.
Integer - функция преобразования вещественного числа в целое.
Примечание: во многих реализациях функция Integer означает округление целой части, т. е. Integer (-8.5) = -9, а не -8. В алгоритме используется именно такая функция.
Sign - функция, возвращающая -1, 0, 1 для отрицательного, нулевого и положительного аргумента соответственно
*/
// аппроксимируем длину отрезка
if abs(x2 - X1) >= abs(y2 - y1) then
Длина = abs(x2 - x1)
else
Длина = abs(y2 - y1) end if
// полагаем большее из приращений dx или dy равным единице растра
dх = (х2 - х1)/Длина dy = (y2 - y1)/Длина
/*
округляем величины, а не отбрасываем дробную часть. Использование знаковой функции делает алгоритм пригодным для всех квадрантов
*/
х = х1 + 0.5 * Sign(dx)
y = y1 + 0.5 * Sign(dy)
// начало основного цикла i = 1
while (i <= Длина)
Plot (Integer(x), Integer(y))
х = х + dх y = y + dy i = i + 1
end while finish
АЛГОРИТМ БРЕЗЕНХЕМА
Хотя алгоритм Брезенхема был первоначально разработан для цифровых графопостроителей, однако он в равной степени подходит и для использования растровыми устройствами с ЭЛТ. Алгоритм выбирает оптимальные растровые координаты для представления отрезка. В процессе работы одна из координат - либо x либо у (в зависимости от углового коэффициента) - изменяется на единицу. Изменение другой координаты (либо на нуль, либо на единицу) зависит от расстояния между действительным положением отрезка и ближайшими координатами сетки. Такое расстояние мы назовем ошибкой. Ошибка - это интервал, отсекаемый по оси Y рассматриваемым отрезком в каждом растровом элементе. Алгоритм построен так, что требуется проверять лишь знак этой ошибки.
/*
Алгоритм Брезенхема разложения в растр отрезка для первого октанта.
Предполагается, что концы отрезка (x1,y1) и (x2,y2) не совпадают.
Integer - функция преобразования в целое.
х, y, dх, dy - целые.
е - вещественное.
*/
//инициализация переменных х = х1
y = y1
dх = х2 - х1 dy = y2 - y1
//инициализация е с поправкой на половину пиксела е = dy/dх - .5
//начало основного цикла
for i = 1 to dх Plot (х, y) while (e >= 0)
y = y + 1
е = е - 1 end while
x = x + 1
е = е + dy/dх next i
finish
ЦЕЛОЧИСЛЕННЫЙ АЛГОРИТМ БРЕЗЕНХЕМА
Алгоритм Брезенхема в том виде, как он представлен выше, требует использования арифметики с плавающей точкой и деления (для вычисления углового коэффициента и оценки ошибки). Быстродействие алгоритма можно увеличить, если использовать только целочисленную арифметику и исключить деление. Так как важен лишь знак ошибки, то простое преобразование E = 2 * е * dy превратит предыдущий алгоритм в целочисленный и позволит эффективно реализовать его на аппаратном или микропрограммном уровне. Чтобы реализация алгоритма Брезенхема была полной, необходимо брать отрезки во всех октантах. Модификацию легко сделать, учитывая в алгоритме номер квадранта, в котором лежит отрезок и его угловой коэффициент. Когда абсолютная величина углового коэффициента больше
20