МОСКОВСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
ЭКОНОМИКИ, СТАТИСТИКИ И ИНФОРМАТИКИ
![]() |
Кафедра Информатики
Программирование в среде Borland С++ Builder.
Создание графических объектов и манипуляция ими.
Методические указания к лабораторным работам
по курсу " Основы алгоритмизации и языки программирования "
для студентов 1-го курса специальности ДИС
Лабораторная работа № 3
Тверь 2000
Цель лабораторной работы заключается в более детальном изучении возможностей контекста графического устройства и интегрированной среды для разработки программных приложений "Borland C++ Builder" при формировании и манипуляциях изображениями объектов в виде геометрических фигур.
Основными задачами, решаемыми в процессе выполнения лабораторной работы, являются:
· Изучение основных возможностей объектов класса TImage и способов изменения положения и формы графических объектов в окне приложения.
· Разработка класса для представления геометрических фигур многоугольников.
· Приобретение практических навыков по созданию простейшего приложения, позволяющего создавать и редактировать графические изображения, состоящие из группы различных раскрашенных многоугольников.
Методическое указание обсуждено на заседании кафедры Информатики (протокол №___от 2000 года) и рекомендовано к печати.
Составитель:
Содержание
1. Содержание отчета по лабораторной работе.
2. Класс Timage.
2.1. Свойства.
2.2. Методы.
3. Возможные способы изменения положения и формы графических объектов в окне приложения.
3.1. Изменения положения.
3.2. Изменения формы.
4. Основные принципы разработки интерфейса класса.
4.1. Структура класса.
4.1.1. Состав классы.
4.1.2. Уровни доступа к членам класса.
4.1.3. Конструкторы.
4.1.4. Деструкторы.
4.1.5. Члены - данные.
4.1.6. Функции - члены.
4.1.7. Скрытый указатель с именем this.
4.2. Проектирование классов.
4.2.1. Этапы проектировния.
4.2.2. Общие рекомендации при проектированию классов.
4.2.3. Определение операций.
4.2.4. Определение зависимостей.
5. Создание меню.
5.1. Создание главного меню.
5.1.1. Добавление главного меню к форме.
5.1.2. Вставка из шаблона.
5.1.3. Удаление пунктов меню.
5.1.4. Вставка пунктов меню.
5.2. Создание подменю.
6. Задание на лабораторную работу.
Литература
1. Содержание отчета по лабораторной работе.
Отчет по лабораторной работе должен содержать:
· Титульный лист.
· Задание на лабораторную работу, детализированное описанием предполагаемой реализации.
· Обоснование и описание интерфейса класса для представления многоугольников. Обоснование и описание принципов реализации основных функций (методов) класса.
· Описание реализации разработанного приложения (представляющего собой графический редактор группы геометрических фигур) включающее:
· описание реализуемых режимов;
· описание основных особенностей функционирования разработанной системы;
· инструкцию пользователя (краткое описание: как пользоваться данным приложением).
· Исходные тексты программ всех модулей приложения (кроме модуля приложения, в котором находится функция WinMain). Исходные тексты программ должны содержать все необходимые поясняющие комментарии, позволяющие лучше понять их реализацию.
· Внешний вид главного окна созданного приложения, включающий демонстрационный вариант созданной группы многоугольников.
2. Класс Timage.
Эта компонента создаёт и на форме контейнер для отображения графических данных: битового образа, пиктограммы или метафайла.
Компонента класса TImage используется для визуализации на форме изображений различных графических объектов. Для указания конкретной графической картинки, иконки, метафайла или других графических объектов, необходимо воспользоваться свойством Timage::Picture. При выборе этого свойства в окне Инспектора Объектов и нажатие на справа-расположенную клавишу с многоточием, открывается окно редактора файлов изображений.
Компонента TImage предоставляет некоторые из своих свойств для определения того, как требуется выводить на экран изображение графического объекта в пределах границ объекта TImage. Например, чтобы контейнер изменил свои размеры так, чтобы вместить изображение целиком, необходимо установить значение свойства AutoSize в true. Для того, чтобы исходное изображение меньшего размера растянуть на весь контейнер, необходимо установить свойство Stretch в значение true. Для динамической загрузки и сохранения файлов изображений, необходимо воспользоваться методами объектного свойства Picture: LoadFromFile и SaveToFile. Например:
Image->Picture-> LoadFromFile("Имя файла");
Image->Picture-> SaveToFile ("Имя файла");
На Рис.1 представлены общий вид основного окно (б) оперативной подсказки по компоненте TImage и дополнительные, с описанием его свойств (а) и методов (в).
а) Свойства компоненты. б) Общее описание компоненты. в) Методы компоненты.
Рис.1. Основное (б) и дополнительные (а, в) окна оперативной подсказки по компоненте TImage.
Рассмотрим некоторые основные свойства и методы компоненты.
2.1. Свойства.
q Canvas. Предоставляет поверхность для графического образа.
q Picture. Указывает на конкретный графический образ.
q Stretch. Указывает - нужно ли растягивать графический образ на всю область контейнера.
q AutoSize. Признак автоматической установки размеров контейнера, равным размеру графического образа.
q Height. Высота компоненты в пикселях.
q Width. Ширина компоненты в пикселях.
q Cursor. Указывает на форму курсора при прохождении его над компонентой.
q Hint. Текстовая строка, появляющаяся на экране при попадании в компоненту курсором.
q Left. Горизонтальная координата верхнего-левого угла компоненты.
q Top. Вертикальная координата верхнего-левого угла компоненты.
q Visible. Определяет видимость компоненты на экране.
2.2. Методы.
q Hide(). Делает компоненту невидимой.
q Invalidate(). Сообщает Windows о необходимости перерисовать компоненту.
q Show().Делает компоненту видимой.
q ClientToScreen(). Преобразует координаты внутренней точки области компоненты (относительно её верхнего-левого угла), в её абсолютные координаты на экране экране.
Прототип функции имеет следующий вид:
Windows::TPoint __fastcall ClientToScreen(const Windows::TPoint &Point);
q ScreenToClient().Преобразует координаты точки на экране, во внутренние координаты компоненты (относительно её верхнего-левого угла).
Прототип функции имеет следующий вид:
Windows::TPoint __fastcall ScreenToClient(const Windows::TPoint &Point);
На рис.2. представлены форма, с размещённой на ней компонентой TImage и окно инспектора объектов.
![]() |
Рис.2. Внешний вид компоненты TImage на форме и инспектора объектов.
3.0. Возможные способы изменения положения и формы графических объектов в окне приложения.
3.1. Изменения положения.
При редактировании графических объектов часто возникает необходимость в непрерывном измененении их положения (перемещении) в пределах клиентной области экрана. Для реализации перемещения существует множество способов, большинство из которых использует промежуточный буфер.
Рассмотрим один из возможных способов перемещения графических объектов с использованием буфера. Пусть имеется класс для представления прямоугольных фигур - ClFigura, у которого есть данные члены, характеризующие его положение и размеры: x, y,width, height (соответственно координаты верхнего-левого угла региона, занимаемого фигурой, его ширина и высота). Кроме того, имеется приложение, содержащее множество объектов (экземпляров класса) типа ClFigura, которые требуется произвольным образом перемещать в рабочем поле формы приложения.
Один из наиболее часто используемых методов перемещения графических объектов заключается в следующем:
q Стереть старое изображение перемещаемого объекта.
q Изменить координаты его местоположения.
q Отрисовать объект с новыми координатами.
В результате должен создаваться эффект плавного перемещения изображения графической картинки объекта вслед за курсором. Проблема здесь заключается в том, чтобы стереть старое изображение, не испортив изображения остальных объектов или фоновой картинки рабочего поля. Для этого следует использовать вспомогательный буфер для хранения изображения участка экрана под перемещаемым объектом. При этом общую последовательность необходимость действий следует разбить на три фазы: подготовительную, собственно - перемещения и заключительную.
Подготовительная фаза. Одну из возможных последовательностей действий при перемещении изображения объекта на первой фазе можно представить следующим образом:
q Определение перемещаемого объекта.
q Перерисовка всех графических объектов, кроме того, который определён для перемещения.
q Определение и выделение объёма памяти под буфер, необходимый для временного хранения изображения участка экрана под перемещаемым объектом.
q Вырисовывание изображения перемещаемого объекта.
Фаза перемещения. Возможную последовательность действий можно представить в следующем виде:
q Определить требуемое смещение объекта относительно своего старого положения. Для того, чтобы выделенный объект перемещался вслед за курсором, то вполне очевидно, что в качестве такого смещения следует принять смещение курсора.
q Восстановить изображение экрана под объектом, хранимое в промежуточном буфере (стираем старое изображение объекта).
q В соответствии с фактическим смещением курсора изменить координаты перемещаемого объекта.
q Запомнить в промежуточном буфере новый участок экрана, где будет нарисован перемещаемый объект.
q Отрисовать перемещаемый объект в новом месте и вернуться к первой операции фазы перемещения.
Заключительная фаза. На этой фазе требуется просто освободить память, выделенную под промежуточный буфер.
3.2. Изменения формы.
Рассмотрим один из многих возможных способов изменеия формы графического объекта, представленного в виде многоугольника.
Один из наиболее простых и часто используемых методов изменения формы многоугольника, в частности изменени положения одной из его вершин заключается в следующем:
q Изменять координаты перемещаемой вершины и одновременно, в зависимости от направления перемещения растягивать или сжимать, сопряжённые с перемещаемой вершиной объекта. Для этого можно использовать режим "Резинка", рассмотренный предыдущей лабораторной работе.
q После окончания редактирования положения корректируемой вершины многоугольника необходимо перерисовать все графические фигуры заново.
В результате создаётся эффект плавного изменения (вслед за курсором) положения корректируемой вершины объекта при одновременном и соответствующем изменении размеров и положения смежных с ним сторон. При этом общую последовательность необходимость действий также целесообразно разбить на три фазы: подготовительную, корректировки положения вершины и заключительную.
Подготовительная фаза.
q Определение объекта и его вершины для редактирования её положения.
q Вырисовывание (в режиме pmNotXor) части контура объекта, включающей в себя стороны, сопряжённые с корректируемой вершиной. Это делается для последующей реализации режима "Резинки" при растягивании или сжатии модифицируемых сторон многоугольника.
Фаза корректировки положения вершины. Возможную последовательность действий можно представить в следующем виде:
q Определить требуемое смещение корректируемой вершины относительно своего старого положения. Для того, чтобы выделенная вершина перемещалась вслед за курсором, то в качестве такого смещения целесообразно принять соответствующее смещение курсора.
q Стереть сопряжённые с корректируемой вершиной сопряжённые стороны многоугольника. Фактически это будет означать повторное вырисовывание этих сторон в режиме pmNotXor, что приводит к эффекту стирания.
q Изменить координаты корректируемой вершины
q Нарисовать сопряжённые со скорректированной вершиной стороны многоугольника в режиме pmNotXor.
q Повторить все операции начиная с первой.
Заключительная фаза. На этой фазе требуется просто перерисовать всю совокупность фигур, включая и корректируемую.
Примечание.
При реализации рассмотренных выше методик редактирования положения и формы геометрических фигур, следует выбрать функции отклика видимой компоненты, расположенной на форме окна приложения(например, PaintBox), на внешние события, такие как: OnMouseDown, OnMouseUp и OnMouseMove.
Подготовительную фазу следует реализовать с помощью реакции на событие OnMouseDown, фазу редактирования - OnMouseMove и заключительную фазу - с помощью OnMouseUp.
4.0. Основные принципы разработки интерфейса класса.
4.1. Структура класса.
4.1.1. Состав класса.
Класс, как и структура, представляет собой набор данных и функций, предназначенных для совместного выполнения определённой задачи. Как говорят, класс инкапсулирует задачу. Классы имеют следующие характерные элементы:
q Средства контроля доступа.
q Конструкторы.
q Деструкторы.
q Члены-данные.
q Функции-члены.
q Специальный скрытый указатель с именем this.
Как и структура, класс должен быть предварительно объявлен. Объявление класса обычно содержится в заголовочном файле с расширением ".h". Как правило, для определения функций класса создают исходный файл с именем, близким к имени класса, и расширением ".cpp". Поскольку Windows поддерживают длинные имена файлов, то при желании можно использовать имя, в точности совпадающее с именем класса. Например, если есть класс MyClass, то исходный файл следует назвать MyClass. cpp, а заголовочный - MyClass. h.
4.1.2. Уровни доступа к членам класса.
Члены класса могут иметь три уровня доступа: закрытый (private), открытый (public) или защищённый (protected). Уровни доступа к членам класса определяют способ работы пользователей с классом. Программируя самостоятельно, программист может быть как создателем класса, так и их пользователем. При работе в команде один программист может быть создателем класса, а остальные - его пользователями.
Любой класс содержит открытую часть, к которой возможен доступ извне класса, и закрытую часть. Закрытая часть класса определяет его внутреннюю реализацию. В хорошо спроектированном классе от пользователя скрыто всё, что ему не требуется знать.
Абстрактное представление данных - это сокрытие внутренней реализации свойств класса от взгляда извне. Абстрактное представление данных даёт пользователю возможность знать о классе ровно столько, сколько необходимо, и предохраняет от вмешательства туда, куда вмешиваться не стоит. Но если внутренняя работа класса закрыта, то интерфейс пользователя является открытым.
К защищённым членам класса, как и к закрытым, пользователь обращаться тоже не может. Однако эти члены могут быть доступными для классов, которые являются производными от данного класса.
4.1.3. Конструкторы.
Конструктор это функция, которая автоматически вызывается при создании экземпляра класса. Конструктор используется для инициализации переменных-членов класса, выделения необходимой памяти и выполнения других действий, необходимых перед началом использования класса. Необходимо помнить, что неинициализированные переменные содержат случайные значения. Это касается и членов данных класса. Поэтому для безопасности следует присваивать переменным - членам класса какие-либо начальные значения.
Конструктор, у которого нет аргументов, называется конструктором по умолчанию. Имя конструктора должно совпадать с именем класса. Это служит отличительным признаком конструктора. Конструктор не может возвращать никакого значения и поэтому для него не указывается тип возвращаемого значения.
Важно понимать, что нельзя явно вызывать конструктор. Конструктор используется только при создании объекта (или реализации) класса. Возможно использование любого количества конструкторов, но при этом нельзя допускать неоднозначности в списке параметров.
4.1.4. Деструкторы.
Деструктор - это специальная функция, которая автоматически вызывается перед уничтожением объекта. Обычно он используется для освобождения памяти, выделенной под экземпляр (объект) класса, или выполняет другие задачи по наведению порядка после работы класса. Класс может иметь не более одного деструктора. Наличие деструктора не является обязательным. Деструктор не возвращает никакого значения и не принимает никаких аргументов. Его имя образуется из имени класса с доюавлением впереди знака тильды (~).
Как было сказано, деструктор вызывается непосредственно перед разрушением объекта класса. Объект класса может быть разрушен либо при выходе из области видимости, либо в результате применения оператора delete. В любом случае, вызов деструктора будет последним действием перед окончательным исчезновением объекта класса.
4.1.5. Члены - данные.
Члены - данные класса это просто переменные, объвленные в описании класса. Их областью видимости по умолчанию является класс. По сравнению с членами - данными структур, можно управлять доступом к членам-данным класса, объявляя их как private, public или protected. Независимо от установленного уровня доступа, члены-данные класса могут использоваться всеми функциями этого класса. Уровень доступа определяет видимость члено-данных вне класса. Для работы с закрытыми членами-данными можно написать и использовать специальные функции доступа к этим данным. Одна функция будет возвращать значение определённого члена класса, а другая - изменять его значение. Это открытые функции-члены, работающие с закрытыми членами-данными.
Возможность использования специальных функций для изменения членов-данных класса даёт важное преимущество - возможность контроля входных данных. Это позволяет следить за изменением значений, которые принимают члены-данные.
Для каждого экземпляра класса в памяти создаётся отдельная копия членов-данных. Исключение делается только для членов-данных, объявленных как статические с модификатором static. В этом случае все экземпляры класса используют одну единственную копию соответствующего члена.
Существуют некоторые рекомендации при работе членами-данными:
q Необходимо использовать столько членов-данных, сколько необходимо для нормального функционирования объектов класса, но по возможности требуется обходится локальными переменными.
q Не нужно делать все члены-данные открытыми.
q Для обращения к закрытым членам=данным необходимо использовать специальные функции, которые должны быть доступны.
q Чтобы избежать неправильного ввода, необходимо с помощью функций контролировать значения, присваиваемые закрытым членам-данным.
q Необходимо инициализировать все члены-данные либо в списке инициализаторов, либо в теле конструктора.
q Члены-данные, размещаемые в памяти динамически, требуется уничтожать.
4.1.6. Функции - члены.
Функции-члены класса - это функции, принадлежащие классу. Они являются локальными по отношению к классу, в котором они определены, и не существуют вне класса. Функции-члены могут быть вызваны только изнутри класса. Они имеют доступ ко всем открытым, защищённым и закрытым членам-данным своего класса.
Открытые функции-члены класса представляют собой интерфейс между пользователем и классом. Именно через открытые функции пользователи класса получают доступ к тем возможностям, которые предоставляет класс.
Закрытые функции-члены предназначены только для использования самим классом. Их вызов пользователем класса не предполагается, они скрыты от внешнего мира. Для некоторых классов начальные процедуры инициализирующих действий могут потребовать выполнения кода довольно большого объёма. Чтобы не загромождать конструктор, лучше всего написать функцию Init(), которая будет вызываться из конструктора и выполнять все необходимые действия. Эта функция никогда не должна напрямую вызываться пользователями класса и поэтому она должна быть закрытой.
Защищённые функции-члены - это функции, доступные только для тех классов, которые являются производными данного класса. Доступ извне к этим функциям невозможен.
4.1.7. Скрытый указатель с именем this.
Все классы имеют скрытый член с именем this. Это указатель на экземпляр данного класса. Следует вспомнить, что каждый экземпляр класса имеет свою копию членов-данных. При этом все экземпляры используют один набор функций-членов класса. Как же компилятор определяет, какой из экземпляров вызвал функцию? Для этого каждая функция-член класса имеет скрытый аргумент this.
4.2. Проектирование классов.
При проектировании всегда следует учитывать тот факт, что этот процесс неизбежно будет расширяться, переноситься, перенастраиваться и, вообще изменяться множеством способов, которые невозможно предвидеть заранее. Поэтому необходимо стремиться к к проектированию и разработке систем, которые достаточно просты, и эта простота должна обуславливаться возможностью будущей модификации системы в различных направлениях. Система должна проектироваться так, чтобы оставаться после последовательности видоизменений настолько простой, насколько это возможно. Необходимо проектировать, имея в виду неизбежные модификации, и при этом обеспечить:
q Гибкость.
q Расширяемость.
q Переносимость.
Лучше всего попытаться это осуществить, попытавшись инкапсулировать (соединить в одно целое) все части системы, которые, вероятно, будут изменяться, и обеспечить способы модификации кода. Этого можно достигнуть, выявляя в данной области ключевые понятия и возложив обязанности по содержанию и использованию всей информации о каждом понятии на соответствующий класс. В идеале такая модификация могла бы осуществляться путём наследования свойств новым классом или передавая особые аргументы объектам класса.
4.2.1. Этапы проектирования.
Отметим, что любое понятие не существует изолировано, а, как правило, определяется на фоне других понятий. Точно также и класс не существует обособленно, а определяется вместе с логическими связанными с ним классами. Обычно разрабатывается сразу множество взаимосвязанных классов. Такое множество часто называют библиотекой классов.
Множество классов объединяются посредством некоторого логического критерия, или общего стиля, или часто - опоры на общий сервис. Поскольку проектирование такого множества классов почти всегда вызывает определённые трудности, то рекомендуется придерживать следующей последовательности действий:
q Найти понятия (классы) и их основные взаимосвязи.
q Уточнить классы, задав множество операций над ними.
q Разбить операции на группы. Проанализировать потребность в конструкторах, деструкторах и операциях копирования.
q Принять во внимание полноту, минимальность и удобство.
q Уточнить классы, точно определив, как они зависят от других классов. Для классов выбрать выбрать одну из следующих альтернатив:
q Наследуют свойста.
q Находятся в отношении подчинения.
q Точно определить отношения для классов.
q Отделить открытые функции от защищённых.
q Задать типы операций над классами.
Необходимо отметить, что это только несколько шагов итеративного процесса. Обычно нужно повторить эту последовательность несколько раз, прежде, чем будет выработан проект, который в достаточной степени подходит для начально, либо для повторной реализации.
4.2.2. Общие рекомендации по проектированию классов.
Родоначальник языка С++, Бъярн Страуструп утверждает, что ключ к искусному проектированию можно подобрать, если непосредственно моделировать некоторые аспекты "окружающей действительности", то есть "поймать" понятия из данной прикладной области в виде классов, представить зависимости между классами формальным образом, например, в виде наследования, и проделывать это повторно на разных уровнях абстракции.
Но как найти такие понятия и как определить - какие классы нам нужны? Лучше всего начинать с изучения самой прикладной области как множество абстракций и концепций. Особое внимание при этом следует обратить на используемый словарь терминов. Часто утверждают, что существительные соответствуют классам в программе. Глаголы могут означать операции над объектами. Часто в виде классов можно можно представить даже прилагательные. Такие прилагательные, как "хранимый", "согласованный", "зарегисирированный" можно представить в виде виртуальных базовых классов с той целью, чтобы разработчик мог отбирать из них подходящие атрибуты-классы и наделять (используя наследование) этими атрибутами классы, разрабатываемые позднее.
Уточнять эти понятия на начальной стадии лучше всего путём обсуждения с экспертами в данной прикладной области и коллегами. Такое обсуждение необходимо для того, чтобы выработать жизнеспособный начальный словарь и концептуальную основу для дальнейшего движения. На уровне реализации классы могут также представлять системные ресурсы и другие абстракции. Взаимосвязи на данной стадии проектирования возникают естественным образом в результате понимания прикладной области, либо вследствие последующей работы над структурой класса..
4.2.3. Определение операций.
При поиске классов основное внимание сосредотачивается на ключевых понятиях. При задании действий над классами, самым важным является нахождение полного и удобного набора операций. Очень трудно рассматривать обе эти стороны, принимая в расчёт, что взаимосвязанные классы должны разрабатываться вместе.
Обычно используется следующая стратегия:
q Прежде всего, рассмотреть то, как следует создавать, копировать и уничтожать объект класса.
q Определить минимальный набор операций, требуемых для для поддержки данного понятия класса.
q Рассмотреть, какие операции можно добавить для удобства записи, и из них включить только несколько по-настоящему важных.
q Рассмотреть, какие операции должны быть виртуальными, т. е. операциями, для которых класс играет роль интерфейса, а реализация поддерживается в производных классах.
q Проанализировать, какой функциональной общности из простоты наименования можно достичь во всём множестве классов.
Гораздо легче добавить любую функцию, которая могла бы впоследствии оказаться полезной и сделать все операции виртуальными. Однако, чем больше будет функций, тем более вероятно, что они будут оставаться неиспользованными и будут сдерживать процесс разработки и дальнейшее развитие системы. Легче добавить функцию к интерфейсу, раз уж в этом возникла бесспорная необходимость, чем убрать её в том случае, когда она стала помехой. При подборе операций важно сконцентрировать своё внимание на том, что нужно сделать, а не на том, как это будет реализовываться.
4.2.4. Определение зависимостей.
При определении зависимости от других классов самыми важными являются отношения наследования свойств и использования. Обе эти зависимости подразумевают анализ того, как класс может отвечать за некоторые свойства системы. Отвечать за свойство - вовсе не означает, что класс должен содержать все данные сам или его функции-члены должны непосредственно выполнять все необходимые операции. Наоборот, то, что каждый класс имеет только один ответственный участок, убеждает в том, что основная работа, выполняемая классом - это направлять запросы куда-нибудь в другое место для обработки другому классу, ответственному за эту подзадачу. Чрезмерное использование этой методики может привести к неэффективному и с трудом понимаемому проекту из-за увеличения числа объектов до момента, когда уже не осуществляется никакая работа, кроме каскада последовательных запросов на обслуживание.
5. Создание меню.
Меню является важной частью большинства приложений. В C++ Builder для создания меню используется специальный редактор меню, что очень облегчает работу. Редактор меню обладает следующими возможностями:
q Создание как главного, так и контекстного меню.
q Обеспечение оперативного доступа к редактору кода для обработки событий OnClick, соответствующих пунктам меню.
q Вставка меню из шаблонов или файлов ресурсов.
q Сохранение пользовательских меню в виде шаблонов.
Все команды редактора меню доступны через его контекстное меню или из инспектора объектов. Соответствующие окна инспектора объектов и редактора меню показаны на рис.3 и 4.
![]() |
5.1. Создание главного меню.
Редактор меню позволяет быстро разрабатывать меню любой структуры. Главное меню представлено компонентом TMAinMenu библиотеки VCL. Каждый пункт меню, в свою очередь, является компонентом MenuItem, инкапсулированным в класса TMenuItem. Вам не требуется знать о том, как функционируют эти классы, поскольку редактор берёт на себя всю работу по созданию меню.
5.1.1. Добавление главного меню к форме.
· Прежде всего, необходимо добавить к форме компонент TMainMenu.
· Далее рекомендуется изменить значение его свойство Name (например, на MainMenu). Обратите внимание на то, что компонента MainMenu имеет очень мало свойств и совсем не имеет событий. Дело в том, что работа меню полностью определяется компонентами MenuItem.
· Дважды щёлкните на значке (иконке) главного меню. На экране появится окно редактора меню.
Редактор меню выглядит как пустая форма без узлов сетки. Её размер можно изменить произвольным образом. Размер редактора определяется исключительно из соображений удобства, и не влияет на работу меню во время выполнения программы.
Таким образом, для создания меню необходимо поместить на главную форму приложения компоненту TMainMenu со страницы Standard. Нажав на правую клавишу мыши, из контекстного меню можно выбрать пункт Menu Designer. Перемещаясь с помощью стрелок клавиатуры, создадим новые компоненты - пункты меню верхнего и последующего уровней, вводя текстовые строки в колонку значений напротив свойства Caption.
Например, можно создать следующие меню: "&Файл" (с пунктами "Созд&ать", "&Открыть...", "&Сохранить", "Сохранить &как...", '"-","В&ыход") и "&Вид" (с пунктом "&Инструментальная панель").
Если в свойстве Caption какого-либо пункта меню стоит знак "-", то в этом месте появится горизонтальная разделительная линия.
Значок "&" нужен для связывания с пунктом меню так называемых "горячих" клавиш. Если перед какой-либо буквой в названии пункта меню стоит такой значок, то при отображении меню эта буква оказывается подчеркнутой, и нажатие на соответствующую буквенную клавишу при нажатой клавише Alt приведет к активизации соответствующего пункта меню. Разумеется, в одном меню все "горячие" клавиши должны быть разными, хотя C++ Builder этого не проверяет.
Кроме этого, для работы с меню с помощью клавиатуры используются клавиши быстрого доступа. Подходящую комбинацию клавиш можно выбрать, установив значение свойства ShortCut (Рис.5).
![]() |
Рис.5. Создание меню с помощью Menu Designer.
С помощью инспектора объектов можно выбрать страницу событий и связать функции отклика на выбор того или иного пункта меню с соответствующей функцией-обработчиком, выбрав название функции из выпадающего списка или собственноручно задав его.
5.1.2. Вставка из шаблона.
При формировании своего собственного меню можно воспользоваться более лёгким способом. Для этого необходимо щёлкнуть правой клавишей мыши по полю редактора меню и выбрать в открывшемся контекстном меню пункт Insert From Template ("Вставить из шаблона"). На экране появится диалоговое окно Insert Template, в котором приведён список доступных шаблонов:
· Edit Menu.
· File Menu.
· File Menu (for TextEdit Example).
· Help Menu.
· Help Menu (Expanded).
· MDI Frame Menu.
· Window Menu.
Таким образом, возможно использование предопределённых шаблонов или создание своих собственных. Можно выбрать из списка любой из шаблонов (например, Edit Menu) и нажать на клавишу ОК. В редактор меню сразу же будет вставлено полное меню Edit. Замечание! Можно использовать шаблоны для создания контекстных меню точно так же, как и при создании пунктов главного меню.
5.1.3. Удаление пунктов меню.
Если требуется удалить некоторые пункты меню, то для этого необходимо выполнить следующее:
· Выбрать уничтожаемый пункт меню и щёлкнуть по нему правой клавишей мыши.
· Нажать на клавишу Delete или выбрать пункт Delete в контекстном меню редактора.
В результате, выделенный пункт исчезнет, а оставшиеся сдвинутся вверх.
5.1.4. Вставка пунктов меню.
Вставка пунктов меню выполняется следующим образом. Необходимо щёлкнуть мышью на том пункте, над которым требуется разместить новый пункт и нажмите на клавишу Insert или выберите Insert в контекстном меню редактора. После этого можно соответствующим образом изменить свойства Caption и Name для нового пункта.
5.2. Создание подменю.
Создание подменю не имеет каких-либо особенностей. Подменю (submenu) - это меню, которое вызывается при выборе пункта вышестоящего меню. Наличие подменю обозначается стрелкой вправо, расположенной за названием пункта. Можно создать подменю, выбрав в контекстном меню редактора пункт Create Submenu, или нажав одновременно клавишу Ctrl и стрелку вправо на клавиатуре. При создании подменю справа от соответствующего пункта основного меню размещается пустой пункт. Можно добавлять пункты в подменю точно также, как и при создании главного меню. Создать подменю можно также и вставкой шаблонов.
6. Задание на лабораторную работу.
Разрабатываемое приложение должно обеспечивать формирование группы многоугольников на рабочей поверхности, размеры которой превышают размеры клиентной области окна приложения. Для этого необходимо сделать следующее:
Первый этап.
1. Создать проект нового приложения с пустой формой главного окна.
2. Из палитры компонентов "Additional" выбрать компоненту "ScrollBox" и разместить её в клиентной части окна.
- Свойство "Align" установить в значение "alClient".
- В инспекторе объектов выбрать свойство "HorzScrollBar" и установить его свойство "Range" в значение, превышающее ширину клиентной части окна (например - 800).
- То же самое проделать с аналогичным свойством "VertScrollBar".
3. Из палитры компонентов "System" выбрать компоненту "PaintBox" и разместить её в клиентной части компоненты " ScrollBox ". Свойство "Align" установить в значение "alClient".
4. Из палитры компонентов выбрать "Standart" компоненту "MainMenu" и разместить её в любом месте главной формы приложения.
5. Из палитры компонентов выбрать "Standart" компоненту "Panel", разместить её в любом месте главной формы приложения и установить свойство "Align" в значение "alTop". Подобрать необходимую высоту панели управления, на которой впоследствии будут размещать кнопки управления, дублирующие соответствующие пункты меню.
Второй этап. Разработка класса для представления многоугольных геометрических фигур.
1. Добавить в проект новый модуль. Для этого нужно выбрать меню "File" и в открывшемся диалоговом окне "New Items" выбрать элемент "Unit". При этом в редакторе кода должна появиться новая страница для формирования программного кода для нового модуля "Unit. cpp". Сохранить его под именем, отражающем назначение данного модуля (например, Figura. cpp).
2. Открыть заголовочный файл этого модуля "Figura. h" и, в соответствии с рекомендациями в разделе 4, описать в нём класс для представления многоугольных фигур.
3. Открыть файл исходного кода ("Figura. cpp ") и определить в нём функции перечисленные в соответствующем заголовочном файле.
Третий этап. Разработка редактора изображений группы геометрических фигур, который позволяет:
1. Используя результаты, полученные в предыдущей лабораторной работе, формировать контур новой фигуры (поточечно и в режиме "резинки") и добавлять её в рабочий список.
2. Редактировать положение и форму любой из фигур проектируемой группы многоугольников (см. разделы 2 и 3).
3. Для оперативного контроля процесса проектирования фигур, необходимо предусмотреть статусную панель для отображения режима работы приложения, признака захвата фигуры, выбранной для редактирования, и текущих координат курсора.
Литература:
1. Бъярн Страуструп. Язык программирования С++. Ч.2. Пер. с англ. - Киев, ДиаСофт, 19с.
2. . Borland C++ Builder. Программирование на С++ без проблем. М.: "Нолидж", с.
3. К. Рейсдорф, К. Хендерсон. Освой самостоятельно Borland C++ Builder / Пер. с англ. -М.: "Издательство БИНОМ", 19с.
4. М. Теллес. Borland C++ Builder: библиотека программиста. - СПб: Питер Ком, 19с.






