Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции КПиЯП.docx
Скачиваний:
50
Добавлен:
20.09.2019
Размер:
3.8 Mб
Скачать

3.6.2. Графические компоненты

Операционная система Windows предоставляет разработчикам приложении мощные средства Интерфейса Графических Устройств GDI (Graphics Device Interface) для построения графических изображений независимо от типа используемого устройства вывода. К сожалению, GDI обременяет программистов множеством дополнительных действий (в частности, по управлению системными ресурсами), которые отвлекают разработчика от его основной задачи - создания графики.

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

Поддержка графики в C++Builder

C++Builder инкапсулирует функции Windows GDI на разных уровнях. Наиболее важным здесь является способ, посредством которого графические компоненты представляют свои изображения на экране монитора. При прямом вызове функции GDI необходимо передавать им дескриптор контекста устройства (device context handle), который задает выбранные вами орудия рисования - перья, кисти ц шрифты. После завершения работы с графическими изображениями, вы обязаны восстановить контекст устройства в исходное состояние и только потом освободиться от него.

Вместо того, чтобы вынуждать вас работать с графикой на таком уровне детализации, C++Builder предоставляет вам простой и завершенный интерфейс посредством свойства Canvas (Канва) графических компонент. Это свойство проинициализирует правильный контекст устройства и освободит его в нужное время, когда вы прекратите рисование. По аналогии с функциями Windows GDI канва имеет вложенные свойства, представляющие характеристики пера, кисти и шрифта.

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

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

Листинг 3.6.1 содержит два фрагмента кода, которые наглядно иллюстрируют, насколько C++Builder упрощает программирование графики. Первый фрагмент применяет стандартные функции GDI для того, чтобы нарисовать в окне OWL приложения для Windows желтый эллипс, обведенный синим контуром. Во втором фрагменте та же задача решается посредством канвы рисования.

void TMyWindow::Paint(TDC& PaintDC, bool erase, TRect& rect) {

HPEN PenHandle, OldPenHandle;

HBRUSH BrushHandle, OldBrushHandle;

PenHandle = CreatePen(PS_SOLID, 1, RGB(0, 0, 255));

OldPenHandle = SelectObject(PaintDC, PenHandle);

BrushHandle = CreateSolidBrush(RGB(255, 255, 0));

OldBrushHandle = SelectObject(PaintDC, BrushHandle);

Ellipse(10, 10, 50, 50);

SelectObject(OldBrushHandle) ;

DeleteObject(BrushHandle) ;

SelectObject(OldPenHandle);

DeleteObject(PenHandle) ;

}

void_fastcall TFormI::FormPaint(TObject *Sender) {

Canvas->Pen->Color = clBlue; // выбрать цвет контура

Canvas->Brush->Color = clYellow; // выбрать цвет заливки

Canvas->Ellipse(10, 20, 50, 50); // нарисовать эллипс }

Листинг 3.6.1. Использование функций Windows GDI и свойства канвы на примере рисования эллипса.

Использование канвы

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

Уровень

Действие

Методы

Свойства

Высокий

Определяет текущую позицию пера

MoveTo

PenPos

Рисует прямую до заданной точки

LineTo

PenPos

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

Rectangle

Рисует эллипс заданного размера

Ellipse

Выводит текстовую строку

TextOut

Задает высоту, отведенную для вывода текстовой строки

TextHeight

Задает ширину, отведенную для вывода текстовой строки

TextWidth

Вывод текста внутри прямоугольника

TextRect

Заливка указанного прямоугольника цветом и текстурой текущей кисти

FillRect.

Заливка области канвы (произвольной формы) заданным цветом

FloodFill

Средний

Используется для установки цвета, стиля, ширины и режима пера

Pen

Используется для установки цвета и текстуры при заливке графических фигур и фона канвы.

Brush

Используется для установки шрифта заданного цвета, размера и стиля

Font

Используется для чтение и записи цвета заданного пикселя канвы

Pixels

Копирует прямоугольную область канвы в режиме CopyMode

CopyRect

CopyMode

Копирует прямоугольную область канвы с заменой цвета

BrushCopy

Рисует битовый образ, пиктограмму, метафайл в заданном месте канвы

Draw

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

StretchDraw

Низкий

Используется как параметр при вызове функций Windows GDI

Handle

Работа с рисунками

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

При работе с рисунками в среде C++Builder следует принимать во внимание три важных аспекта.

В среде C++Builder существует три рода объектов, которые имеют отношение к графике:

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

Графика представляет растровое изображение некоторого файла или ресурса (битового образа, пиктограммы или метафайла). C++Builder определяет производные от базового класса TGraphic объектные классы TBitmap, Ticon и TMetafile. Конечно, вы можете объявить свои собственные классы графических объектов. TGraphic предоставляет минимальный стандартный интерфейс для использования в вашем приложении всех видов графики.

Рисунок представляет собой контейнер для графики, т.е. он может содержать любые классы графических объектов. Таким образом, контейнерный класс TPicture может содержать битовый образ, пиктограмму, метафайл или некоторый другой графический тип, определенный пользователем, а приложение может стандартизовано обращаться ко всем объектам контейнера посредством объекта "рисунок". Действительно, большинство компонент управления изображениями имеют свойство Picture объектного типа TPicture, которое дает возможность представления изображений различных видов графики.

Отметим, что объект "рисунок" всегда содержит некоторую графику, которой в свою очередь может потребоваться иметь канву (единственный стандартный графический класс с канвой - это TBitmap). Обычно, имея дело с рисунком, вы работаете только с той частью графического объекта, которая открыта для доступа через контейнер TPicture. Если вам надо указать доступ к конкретному графическому объекту, задайте его в свойстве Graphic данного рисунка.

Графические файлы

В любой момент работы вашего приложения C++Builder поддерживает загрузку и сохранение рисунков и графиков в файлах изображений стандартного формата. Имена сохраняемого и исходного файла изображений могут совпадать или различаться.

Для загрузки изображения в рисунок из файла воспользуйтесь методом рисунка LoadFromFile. Чтобы сохранить изображение в файле, вызовите метод рисунка SaveToFile. Единственным параметром этих методов является имя файла. Метод LoadFromFile использует расширение файла для распознавания вида графического объекта, который он создаст и загрузит. Метод SaveToFile сохраняет файл с расширением, соответствующим виду сохраняемого графического объекта.

Листинг 3.6.2 содержит инструкцию, которую вы должны записать в тексте кодового модуля для загрузки битового образа в компонентный объект рисунка.

void_fastcall TFormI::FormCreate(TObject *Sender) {

Imagel->Picture->LoadFromFile("c:\\windows\\clouds.bmp");

}

Листинг 3.6.2. Загрузка битового образа из файла clouds, bmp.

Рисунок распознает стандартное расширение файлов битовых образов .bmp и создает свою графику как объект класса TBitmap, а затем вызывает метод LoadFromFile загрузки изображения из файла с указанным именем.

Обслуживание палитр

Большинство элементов пользовательского интерфейса не нуждаются в какой бы то ни было палитре. Однако компонентам, содержащим графические изображения, может потребоваться взаимодействие с Windows и его экранным драйвером для того, чтобы обеспечить надлежащее отображение данных компонент. В документации по операционной системе Windows этот процесс называется реализацией палитр (palette realizing).

Реализация палитр призвана обеспечить, чтобы самое верхнее (видимое на экране как ближайшее к вам) активное окно использовало полную цветовую палитру, в то время как фоновые окна максимально использовали оставшиеся цвета своих палитр. Это означает, что фоновые окна должны изменять свои цвета на ближайшие подобные из доступных в "реальной" палитре. По мере того, как окна меняются местами, перекрывая друг друга, Windows постоянно осуществляет реализацию оконных палитр.

Замечание. C++Builder не содержит самостоятельных средств для создания и обслуживания иных палитр, нежели палитры битовых образов. Однако, если вы получили дескриптор некоторой палитры, графические компоненты смогут работать с ним.

При работе с устройством типа дисплея или принтера, компоненты C++Builder автоматически поддерживают механизм реализации палитр. Таким образом, если ваша компонента имеет палитру, вы можете воспользоваться двумя методами GetPalette и PaletteChanged, наследованными от базового компонентного класса TControl, чтобы управлять тем, как Windows обращается с этой палитрой:

• Связь палитры с компонентой. Если требуется использовать некоторую палитру для графической компоненты, ваше приложение должно узнать об этом. Чтобы ассоциировать палитру с вашей компонентой, перегрузите ее объектный метод GetPalette так, чтобы он возвращал дескриптор (handle) этой палитры. При этом вы, во-первых, сообщаете приложению, что определенной палитре вашей компоненты необходимо быть реализованной; а во-вторых, определяете, какая конкретно палитра используется при реализации.

• Реакция на изменение палитры. Когда ваша компонента ассоциируется с некоторой палитрой посредством перегрузки метода GetPalette, C++Builder автоматически берет на себя реакцию на сообщения Windows от палитр с помощью метода PaletteChanged. При нормальной работе вам никогда не придется переопределять поведение этого метода, установленное по умолчанию. Основная задача метода PaletteChanged состоит в том, чтобы определить вид реализации палитры (для фоновых или активных окон). C++Builder продвигается на шаг вперед, по сравнению с реализацией палитр в Windows: с помощью оконных дескрипторов реализуются не только палитры "стопки" перекрывающихся окон, но и палитры наложенных друг на друга компонент активного окна. Вы можете переопределить такое, принятое по умолчанию, поведение палитр, если захотите, чтобы некоторая компонента приобрела полную цветовую палитру и выглядела на экране как ближайшая к вам.

Внеэкранные битовые образы

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

C++Builder позволяет создавать объекты класса TBitmap в вашем приложении для представления изображении файлов и других ресурсов, которые также способны работать как внеэкранные изображения.

Копирование битовых образов.

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

Требуемый результат

Метод

Полное копирование графики

Draw

Копирование с масштабированием

StretchDraw

Копирование прямоугольного участка канвы

CopyRect

Копирование с растровыми операциями

BrushCopy

Создание и обслуживание

При создании сложных графических изображений следует избегать их непосредственного рисования на канве формы или компоненты, представленной в экранном окне вашего приложения. Вместо этого вы сможете сконструировать некий объект битового образа и рисовать на его канве, а затем скопировать изображение на канву экрана. При рисовании на канве внеэкранного битового образа наиболее часто используется метод Paint графических компонент.

Пример рисования сложного изображения на внеэкранном битовом образе дает Индикатор (Gauge), представленный на вкладке Samples Палитры компонент. Исходные файлы Gauges.cpp и Gauges.h программного модуля компоненты TGauge можно найти в каталоге: \.. .\CBuilder\Examples\Controls\Source.

Реакция на изменения

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