ОБЪЕКТНООРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ Авторы курса лекций: Зверева Ольга Михайловна, ст. преподаватель каф АСУ Спиричева Наталия Рахматулловна, ст. преподаватель каф АСУ Екатеринбург 2007 Модуль 2 Объектно-ориентированное программирование в среде Borland C++ Builder Лекция 12. Общие характеристики и особенности применения системы объектно-ориентированного программирования Borland C++ Builder Лекция 13. Знакомство со средой C++ Builder Лекция 14. Программные технологии VCL. Использование компонентов Лекция 15. Класс TForm Лекция 16. Обработка исключительных ситуаций в C++ Builder Лекция 17. Графические возможности среды C++ Builder. Класс TGrahp Лекция 18.Создание пакетных приложений. Компонент программиста. Лекция 19. Использование наборов данных. Лекция 20. Работа в интегрированном отладчике 3 Формируемые компетенции После изучения теоретического материала Модуля 1 необходимо знать и иметь представление о: отличительных особенностях среды Borland C++ Builder; принципах визуального и объектно-ориентированного программирование в среде C++ Builder; иерархии классов среды C++ Builder; уметь: создавать приложения C++ Builder; создавать собственную иерархию классов; уметь расширять среду собственными компонентами владеть: навыками применения библиотеки VCL 4 Лекция 17. Графические возможности среды C++ Builder. Класс TGrahp Цели изучения Изучение основных характеристик класса TGraph Знакомство с основными графическими примитивами:холст, перо, кисть. Знакомство с цветовыми и шрифтовыми возможностями графики Знакомство с примерами создания графических приложений 6 Содержание Поддержка графики в C++Builder. Класс TGraph Использование канвы Работа с рисунками Внеэкранные битовые образы 7 Введение Операционная система Windows предоставляет разработчикам приложении мощные средства Интерфейса Графических Устройств GDI (Graphics Device Interface) для построения графических изображений независимо от типа используемого устройства вывода. К сожалению, GDI обременяет программистов множеством дополнительных действий (в частности, по управлению системными ресурсами), которые отвлекают разработчика от его основной задачи - создания графики. C++Builder берет на себя всю вспомогательную работу GDI, освобождая разработчиков от непродуктивного программирования с поиском утерянных дескрипторов изображений и не освобожденных ресурсов памяти. Это вовсе не означает, что прямое обращение приложений к отдельным функциям Windows GDI запрещается - вы всегда сможете при необходимости вызывать их. Однако, инкапсуляция графических функций Windows визуальными компонентами представляет собой более перспективную методику создания графики в вашем приложении. 8 Поддержка графики в C++Builder C++Builder инкапсулирует функции Windows GDI на разных уровнях. Наиболее важным здесь является способ, посредством которого графические компоненты представляют свои изображения на экране монитора. При прямом вызове функции GDI необходимо передавать им дескриптор контекста устройства (device context handle), который задает выбранные вами орудия рисования - перья, кисти ц шрифты. После завершения работы с графическими изображениями, вы обязаны восстановить контекст устройства в исходное состояние и только потом освободиться от него. Вместо того, чтобы вынуждать вас работать с графикой на таком уровне детализации, C++Builder предоставляет вам простой и завершенный интерфейс посредством свойства Canvas (Канва) графических компонент. Это свойство проинициализирует правильный контекст устройства и освободит его в нужное время, когда вы прекратите рисование. По аналогии с функциями Windows GDI канва имеет вложенные свойства, представляющие характеристики пера, кисти и шрифта. 9 Поддержка графики в C++Builder Единственное, что должен сделать пользователь, работая с графическими компонентами, - это определить характеристики используемых орудий рисования. Вам не потребуется следить за системными ресурсами при создании, выборе и освобождении орудий. Канва сама позаботится об этом. Одно из достоинств, которые проявляет C++Builder при работе с графикой это использование кэшированной памяти для графических ресурсов системы. Если ваша программа повторно создает, использует и освобождает, скажем, перо некоторого конкретного вида, вам приходится повторять эти шаги каждый раз, когда вы используете такое перо. Поскольку C++Builder использует кэш-память для хранения графических ресурсов, увеличивается вероятность, что часто употребляемое орудие рисования будет повторно выбираться из кэш-памяти, а не воссоздаваться каждый раз заново. Очевидно, что вследствие этого заметно возрастет эффективность повторяющихся операций вашего графического приложения. 10 Использование функций Windows GDI u свойства канвы на примере рисования эллипса 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); // нарисовать эллипс } Листинг 1. Использование функций Windows GDI u свойства канвы на примере рисования эллипса 11 Использование канвы Объектный класс канвы инкапсулирует графические функции Windows на различных уровнях, начиная с функций высокого уровня для рисования отдельных линий, фигур и текста. Далее идут свойства и методы среднего уровня для манипуляций с канвой для рисования. Наконец, на нижнем уровне обеспечивается доступ к самим функциям Windows GDI. В следующей таблице обобщаются характеристики основных методов и свойств канвы 12 Использование канвы Уровень Высокий Действия Методы Свойства Определяет текущую позицию пера MoveTo PenPos Рисует прямую до заданной точки LineTo PenPos Рисует прямоугольник заданного размера Rectangle Рисует эллипс заданного размера Ellipse Выводит текстовую строку TextOut Задает высоту, отведенную для вывода текстовой строки TextHeight Задает ширину, отведенную для вывода текстовой строки TextWidth 13 Использование канвы Уровень Средний Действия Методы Вывод текста внутри прямоугольника TextRect Заливка указанного прямоугольника цветом и текстурой текущей кисти FillRect. Заливка области канвы (произвольной формы) заданным цветом FloodFill Свойства Используется для установки цвета, стиля, ширины и режима пера Pen Используется для установки цвета и текстуры при заливке графических фигур и фона канвы. Brush Используется для установки шрифта заданного цвета, размера и стиля Font Используется для чтение и записи цвета заданного пикселя канвы Pixels Копирует прямоугольную область канвы в режиме CopyMode CopyRect Копирует прямоугольную область канвы с заменой цвета BrushCopy Рисует битовый образ, пиктограмму, метафайл в заданном месте канвы Draw Рисует битовый образ, пиктограмму или метафайл так, чтобы целиком заполнить заданный прямоугольник StretchDraw CopyMode 14 Использование канвы Уровень Действия Низкий Используется как параметр при вызове функций Windows GDI Методы Свойства Handle 15 Работа с рисунками Основное содержание графических работ, которые выполняются в среде C++Builder, состоит непосредственно в рисовании на канве вашей формы или других размещенных на ней компонент. C++Builder также обслуживает поддержку внешних изображений - битовых образов, метафайлов и пиктограмм, включая автоматическое управление палитрами. При работе с рисунками в среде C++Builder следует принимать во внимание три важных аспекта. 16 Рисунок, графика или канва В среде C++Builder существует три рода объектов, которые имеют отношение к графике: Канва предоставляет битовую карту поверхности для рисования на форме,графической компоненте, принтере или на другом битовом образе. Канва не является самостоятельным объектом, она всегда является свойством какого-то другого графического объекта. Графика представляет растровое изображение некоторого файла или ресурса (битового образа, пиктограммы или метафайла). C++Builder определяет производные от базового класса TGraphic объектные классы TBitmap, Ticon и TMetafile. Конечно, вы можете объявить свои собственные классы графических объектов. TGraphic предоставляет минимальный стандартный интерфейс для использования в вашем приложении всех видов графики. 17 Рисунок, графика или канва Рисунок представляет собой контейнер для графики, т.е. он может содержать любые классы графических объектов. Таким образом, контейнерный класс TPicture может содержать битовый образ, пиктограмму, метафайл или некоторый другой графический тип, определенный пользователем, а приложение может стандартизовано обращаться ко всем объектам контейнера посредством объекта "рисунок". Действительно, большинство компонент управления изображениями имеют свойство Picture объектного типа TPicture, которое дает возможность представления изображений различных видов графики. Отметим, что объект "рисунок" всегда содержит некоторую графику, которой в свою очередь может потребоваться иметь канву (единственный стандартный графический класс с канвой - это TBitmap). Обычно, имея дело с рисунком, вы работаете только с той частью графического объекта, которая открыта для доступа через контейнер TPicture. Если вам надо указать доступ к конкретному графическому объекту, задайте его в свойстве Graphic данного рисунка 18 Графические файлы В любой момент работы вашего приложения C++Builder поддерживает загрузку и сохранение рисунков и графиков в файлах изображений стандартного формата. Имена сохраняемого и исходного файла изображений могут совпадать или различаться. Для загрузки изображения в рисунок из файла воспользуйтесь методом рисунка LoadFromFile. Чтобы сохранить изображение в файле, вызовите метод рисунка SaveToFile. Единственным параметром этих методов является имя файла. Метод LoadFromFile использует расширение файла для распознавания вида графического объекта, который он создаст и загрузит. Метод SaveToFile сохраняет файл с расширением, соответствующим виду сохраняемого графического объекта. void_fastcall TFormI::FormCreate(TObject *Sender) { Image1->Picture->LoadFromFile("c:\\windows\\clouds.bmp"); } Листинг 2. Загрузка битового образа из файла clouds, bmp. 19 Графические файлы Рисунок распознает стандартное расширение файлов битовых образов .bmp и создает свою графику как объект класса TBitmap, а затем вызывает метод LoadFromFile загрузки изображения из файла с указанным именем. 20 Обслуживание палитр Большинство элементов пользовательского интерфейса не нуждаются в какой бы то ни было палитре. Однако компонентам, содержащим графические изображения, может потребоваться взаимодействие с Windows и его экранным драйвером для того, чтобы обеспечить надлежащее отображение данных компонент. В документации по операционной системе Windows этот процесс называется реализацией палитр (palette realizing). Реализация палитр призвана обеспечить, чтобы самое верхнее (видимое на экране как ближайшее к вам) активное окно использовало полную цветовую палитру, в то время как фоновые окна максимально использовали оставшиеся цвета своих палитр. Это означает, что фоновые окна должны изменять свои цвета на ближайшие подобные из доступных в "реальной" палитре. По мере того, как окна меняются местами, перекрывая друг друга, Windows постоянно осуществляет реализацию оконных палитр. Замечание. C++Builder не содержит самостоятельных средств для создания и обслуживания иных палитр, нежели палитры битовых образов. Однако, если вы получили дескриптор некоторой палитры, графические компоненты смогут работать с ним. При работе с устройством типа дисплея или принтера, компоненты C++Builder автоматически поддерживают механизм реализации палитр. Таким образом, если ваша компонента имеет палитру, вы можете воспользоваться двумя методами GetPalette и PaletteChanged, наследованными от базового компонентного класса TControl, чтобы управлять тем, как Windows обращается с этой палитрой: 21 Обслуживание палитр • Связь палитры с компонентой. Если требуется использовать некоторую палитру для графической компоненты, ваше приложение должно узнать об этом. Чтобы ассоциировать палитру с вашей компонентой, перегрузите ее объектный метод GetPalette так, чтобы он возвращал дескриптор (handle) этой палитры. При этом вы, во-первых, сообщаете приложению, что определенной палитре вашей компоненты необходимо быть реализованной; а во-вторых, определяете, какая конкретно палитра используется при реализации. • Реакция на изменение палитры. Когда ваша компонента ассоциируется с некоторой палитрой посредством перегрузки метода GetPalette, C++Builder автоматически берет на себя реакцию на сообщения Windows от палитр с помощью метода PaletteChanged. При нормальной работе вам никогда не придется переопределять поведение этого метода, установленное по умолчанию. Основная задача метода PaletteChanged состоит в том, чтобы определить вид реализации палитры (для фоновых или активных окон). C++Builder продвигается на шаг вперед, по сравнению с реализацией палитр в Windows: с помощью оконных дескрипторов реализуются не только палитры "стопки" перекрывающихся окон, но и палитры наложенных друг на друга компонент активного окна. Вы можете переопределить такое, принятое по умолчанию, поведение палитр, если захотите, чтобы некоторая компонента приобрела полную цветовую палитру и выглядела на экране как ближайшая к вам. 22 Внеэкранные битовые образы Общепринятая методика программирования сложных графических приложении для Windows заключается в создании внеэкранного битового образа, рисовании или заполнении его конкретным изображением и, наконец, копировании всего изображения из битового образа на указанное место экранного окна. Благодаря этому уменьшается заметное глазу мерцание экрана монитора, вызванное повторным рисованием непосредственно в экранном окне. C++Builder позволяет создавать объекты класса TBitmap в вашем приложении для представления изображении файлов и других ресурсов, которые также способны работать как внеэкранные изображения. 23 Копирование битовых образов C++Builder предусматривает четыре способа копирования изображении с одной канвы на другую. Выбирайте нужный метод копирования из следующей таблицы, в зависимости от результата, который необходимо получить. Требуемый результат Метод Полное копирование графики Draw Копирование с масштабированием StretchDraw Копирование прямоугольного участка канвы CopyRect Копирование с растровыми операциями BrushCopy 24 Создание и обслуживание При создании сложных графических изображений следует избегать их непосредственного рисования на канве формы или компоненты, представленной в экранном окне вашего приложения. Вместо этого вы сможете сконструировать некий объект битового образа и рисовать на его канве, а затем скопировать изображение на канву экрана. При рисовании на канве внеэкранного битового образа наиболее часто используется метод Paint графических компонент. Пример рисования сложного изображения на внеэкранном битовом образе дает Индикатор (Gauge), представленный на вкладке Samples Палитры компонент. Исходные файлы Gauges.cpp и Gauges.h программного модуля компоненты TGauge можно найти в каталоге: \.. .\CBuilder\Examples\Controls\Source. 25 Создание и обслуживание Рис. 1 показывает, что текст программы, реализующей перемещение стрелки индикатора по сигналам таймера, состоит всего из двух строк обработчика события OnTimer компоненты TTimer из вкладки System. Первая инструкция функции обработки события Timer1Timer устанавливает значение 1000 (принятое по умолчанию) для односекундного интервала времени объекта Timer1, а вторая инкрементирует значение свойства Progress объекта Gauge1. Если вы соберете и запустите это приложение, то сможете убедиться, что при движении стрелки индикатора с любой скоростью, мерцание экрана монитора действительно отсутствует. 26 Создание и обслуживание Рис. 1. Индикатор в виде шкалы со стрелкой (см. свойство Kind) 27 Реакция на изменения Все графические объекты - включая канвы для рисования - и объекты, которыми они владеют (перья, кисти и шрифты), содержат встроенные события, отвечающие за изменения, произошедшие с объектом. С помощью этих событий вы можете заставить ваши компоненты и, следовательно, использующее их приложение перерисовывать свои изображения в ответ на произошедшие изменения. Реакция на изменения объектов графической компоненты особенно важна в том случае, если эти объекты объявлены в исходном файле модуля компоненты как published. Тогда единственный способ обеспечить, чтобы вид компоненты на стадии проектирования приложения соответствовал свойствам, установленным Инспектором объектов, заключается в подключении обработчика события, который будет реагировать на изменения компонентного объекта. Для графических компонент вы должны предусмотреть реакцию на событие OnChange. Графическая компонента рисования геометрических фигур TShape Библиотеки Визуальных Компонент объявляет свои свойства, представляющие перо и кисть, в секции published. Конструктор компонентного объекта присваивает метод StyleChanged событию OnChange, заставляя компоненту перерисовывать изображенные на ней фигуры при любом изменении пера или кисти. 28 Информационное обеспечение лекции Литература по теме: Боровский А. C++ и Borland C++ Builder. Изд-во Питер, 2005 Тагин М.А., Архангельский А. Программирование в C++ Builder и 2006. Изд-во БИНОМ, 2007 Пахомов Б.И. Самоучитель. C/C++ и Borland C++ Builder 2006. Издво БХВ-Петербург, 2006 Пахомов Б.И. C/C++ и Borland C++ Builder для начинающих Изд-во БХВ-Петербург, 2005 В. Ермолаев, Т. Сорока. C++ Builder: Книга рецептов. Изд-во КУДИЦ-Образ, 2006 Электронный адрес: nr.spiricheva@rtf.ustu.ru 29 Объектно-ориентированное программирование Курс лекций является частью учебно-методического комплекса «Объектно-ориетированное программирование», авторский коллектив: Зверева Ольга Михайловна, старший преподаватель кафедры «Автоматизированные системы управления» Спиричева Наталия Рахматулловна, старший преподаватель кафедры «Автоматизированные системы управления» Учебно-методический комплекс подготовлен на кафедре АСУ РИ-РТФ ГОУ ВПО УГТУ-УПИ Никакая часть данной презентации не может быть воспроизведена в какой бы то ни было форме без письменного разрешения авторов 30