Библиотека: А. Горев, С. Макашарипов, Р. Ахаян. Эффективная работа с СУБД

Глава 5
Объектно-ориентированное программирование
5.1. Объектная модель и ее свойства
5.2. Объекты и их свойства
Объекты для работы с данными
Объекты для управления работой приложения
Объекты для оформления интерфейса пользователя
Объекты-контейнеры
Невизуальные объекты
Объекты OLE
5.3. Управление событиями
5.4. Использование методов

    Программирование - не такое уж приятное занятие, как может показаться на первый взгляд. Регулярно программисты сталкиваются с двумя сильно действующими на нервы событиями: они то часами мучаются в раздумьях, как запрограммировать то или иное функциональное решение, то их одолевает ужасная скука при многократной реализации давно отработанных решений. Способ борьбы с этими неприятностями называется "объектно-ориентированное программирование" (ООП).
    По разным причинам ООП, как неотъемлемая часть современных систем RAD, не сразу стала достоянием широкого круга программистов, долгое время оставаясь уделом профессионалов, пишущих на языках, подобных С++. Среди рассматриваемых в данной книге средств разработки наиболее развитые средства ООП имеет СУБД Visual FoxPro. Нисколько не сомневаясь, что остальные средства разработки будут двигаться в этом направлении, при изложении основ ООП мы будем ориентироваться именно на эту модель.

5.1. Объектная модель и ее свойства

    При структурном программировании, речь о котором шла в предыдущей главе, последовательно выполняются операторы, записываемые программистом в соответствии с логикой решения поставленной перед ним задачи. А теперь представьте интерфейс современной прикладной программы, что-нибудь типа Windows 95. Представили это многообразие окон, диалогов, задач? И все это то открывается, то закрывается, то перемещается, то изменяет цвет. Рискнем предположить, что такой интерфейс написать средствами стандартного структурного языка программирования просто невозможно.
    В этом параграфе вы узнаете:

  • Основные сведения о принципах ООП.
  • Термины и определения, используемые в ООП.
  • Возможности объектной модели Visual FoxPro.
  • Особенности использования объектов в Visual Basic.

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


Абстрактным типом данных называется такой тип данных, который описан программистом, но не поддерживается в используемом языке программирования.

    В языках программирования, которые не поддерживают ООП, таких как, например, стандартный С, абстрактный тип данных может быть создан из существующих типов данных. Хорошим примером такого подхода является использование структур. В языках, поддерживающих ООП, на понятии "абстрактный тип данных" основано описание классов, осуществляемое в программе на высоком уровне. В процессе работы программы это описание используется для создания объектов, выполняющих реальные функции. В Visual FoxPro такой тип данных поддерживается программно за счет использования команды DEFINE CLASS и визуально при использовании Конструктора классов (Class Designer). Объекты, созданные во время работы программы, доступны для управления посредством специальных переменных, которые служат в качестве указателей на эти объекты.


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

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


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

    На основании описания класса при работе программы создаются объекты, которые и обеспечивают выполнение заданных функций. Из описания одного класса может быть создано сколько угодно объектов. Такие объекты будут называться экземплярами одного класса. Описать класс программно можно с помощью команды DEFINE CLASS и визуально при использовании Конструктора классов.
    В Visual FoxPro классы делятся на визуальные и не визуальные. Визуальные классы служат прообразами объектов, которые будут видны и, соответственно, станут основой пользовательского интерфейса будущей программы. Не визуальные классы могут быть видны только в момент проектирования на их основе объектов, которые окажутся невидимыми при работе программы. Как правило, объекты, основанные на не визуальных классах, создаются и управляются программно, с помощью соответствующих команд и функций.
    Классы хранятся в файле библиотеки классов, что облегчает к ним доступ. Этот файл имеет расширение VCX и может содержать один или несколько классов.


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

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


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

Событие - это действие, которое связано с объектом. Событие может быть инициировано пользователем, вызвано программой или операционной системой.

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


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

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


Иерархия классов - это древообразная структура классов, отображающая взаимосвязи между используемыми в приложении классами одного типа.

    Разобраться в понятии "иерархия классов" вам поможет рис. 5.1. Классы, находящиеся на более низких ступенях иерархии, называются подклассами. Любой из классов, находящихся в иерархии на рис. 5.1 ниже базового класса, будет подклассом. Классы, находящиеся на более высоких ступенях, на основании которых описаны ниже стоящие в иерархии классы, называются родительскими классами или суперклассами. Например, на рис. 5.1 базовый класс разработчика будет родительским по отношению к классу кнопок для панели инструментов. На основании одного родительского класса может быть создано сколько угодно подклассов следующего уровня. Такие подклассы называются экземплярами данного класса. На рис. 5.1 такими экземплярами будут классы для выполнения определенных действий, созданные на основе родительского класса графических кнопок.


Рис. 5.1.

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


Базовым классом называется класс, находящийся на вершине иерархии классов, используемых в приложении.

    В Visual FoxPro базовые классы имеют весьма серьезную особенность. Они встроены в саму СУБД, и, следовательно, их описание не может быть изменено. В связи с этим полезно ввести понятие "базовых классов разработчика". Базовые классы разработчика являются дублерами базовых классов Visual FoxPro, стоят на следующей ступени иерархии после них, но являются классами более высокого уровня для всех остальных классов, используемых в приложении, как это видно на рис. 5.1 на примере классов для кнопок управления.
    Всего в Visual FoxPro программист может использовать около 30 базовых классов. Их классификация приведена на рис. 5.2, а назначение описано в табл. 5.1.


Рис. 5.2.
Таблица 5.1. Базовые классы Visual FoxPro
Имя классаОписание
CheckBoxСоздает поле проверки, которое используется для переключения между двумя состояниями.
ColumnСоздает столбец в объекте Grid. Столбец может содержать данные из поля в таблице или выражение, а также включать в себя какие-либо другие элементы управления.
ComboBoxСоздает список, из которого можно выбрать один элемент. Сочетает возможности элементов управления ListBox и TextBox, так как, помимо выбора из списка, позволяет вводить данные.
CommandButtonСоздает одиночную кнопку управления. Кнопка обычно используется, чтобы активизировать событие, подобное закрытию формы, перемещению курсора в другую запись, печати отчета и т. д.
CommandGroupСоздает группу кнопок управления.
ContainerСоздает объект, который может содержать другие объекты. Объекты Container могут содержать другие объекты и разрешают доступ к объектам, содержащимся внутри них.
ControlСоздает объект элемента управления, который может содержать другие защищенные объекты. Объекты Control могут включать в себя другие объекты, но в отличие от объектов Container не позволяют осуществлять доступ к объектам, находящимся внутри них
CustomСоздает определяемый пользователем объект на основе пользовательского класса. Определяемые пользователем классы - это классы со свойствами, событиями и методами, но без визуального представления.
EditBoxСоздает область редактирования. Используйте элемент управления EditBox для символьных полей большой длины или полей примечаний.
FormСоздает форму для работы с данными и управления работой программы. Форма - это объект-контейнер, который включает в себя все необходимые элементы управления и составляет основу пользовательского интерфейса.
FormSetСоздает объект-контейнер, который содержит набор форм.
GridСоздает объект Grid. Grid - это объект-контейнер, отображающий данные в строках и столбцах и по внешнему виду похожий на окно Browse, но имеющий расширенную функциональность, так как вы имеете полный контроль над каждым элементом в Grid за счет отдельного набора свойств.
HeaderСоздает заголовок для столбца в Grid. Объект Header позволяет отвечать на события, то есть может изменять свое значение в процессе работы программы.
ImageСоздает элемент управления, который показывает изображение в формате BMP.
LabelСоздает метку, которая отображает текст.
LineСоздает элемент управления, отображающий горизонтальную, вертикальную или диагональную линию.
ListBoxСоздает поле списка. Этот элемент отображает список пунктов, из которых вы можете выбрать один или несколько. Может применяться при вводе данных, когда пользователь должен ввести только заранее определенные значения.
OLE Bound ControlСоздает связанный элемент управления OLE. Связанный элемент управления OLE позволяет вам добавлять включаемые объекты OLE из других прикладных программ типа Microsoft Word и Microsoft Excel, поддерживающих стандарт OLE 2.0.
OLE Container ControlСоздает элемент управления OLE. OLE-объекты содержат элементы управления ActiveX (файлы с расширением OCX) и включаемые OLE-объекты из других прикладных программ типа Microsoft Word и Microsoft Excel. В отличие от элементов управления ActiveX, включаемые OLE-объекты не имеют собственного набора событий. Кроме того, элементы управления ActiveX не привязаны к полю типа General в таблице FoxPro, как связанные элементы управления OLE.
OptionButtonСоздает одиночную кнопку выбора. Такая кнопка может быть добавлена только к группе кнопок выбора.
OptionGroupСоздает группу кнопок выбора. Группа кнопок выбора - это контейнер, который содержит отдельные кнопки выбора. Позволяет пользователю выбрать одно действие из списка возможных вариантов, представленных набором кнопок.
PageСоздает страницу в страничном блоке. Объект Page позволяет с легкостью создавать многостраничные формы или диалоги путем помещения в окно формы набора страниц, переключаемых с помощью вкладок.
PageFrameСоздает страничный блок, в котором содержатся страницы формы. Страничный блок определяет глобальные характеристики страницы формы: размер и положение на экране, вид рамки, активную страницу и т. д.
ShapeСоздает элемент управления формы, который отображает геометрическую фигуру (прямоугольник, круг или эллипс).
SpinnerСоздает счетчик для фиксированного изменения числового значения.
TextBoxСоздает текстовое поле, в котором можно редактировать содержимое переменной, элемента массива или поля. Текстовое поле - это один из самых широко используемых элементов управления для ввода и редактирования заранее не определенных величин.
TimerСоздает невидимый во время работы программы объект, который обеспечивает контроль по времени за выполнением всей программы или отдельных ее фрагментов. Управление с помощью таймера является полезным для фоновой обработки. Типичное использование таймера - это получение системного времени для определения момента, когда необходимо выполнить какую-либо программу или прервать некоторое действие.
ToolBarСоздает пользовательскую панель инструментов. Панель инструментов представляет собой набор объектов, которые объединены в одном окне. Панель инструментов может быть пристыкована к верхней, нижней или боковым рамкам главного окна. Если панель не пристыкована, она ведет себя аналогично форме.

    Базовые классы делятся на контейнеры и элементы управления. Стоит пояснить несколько подробнее отличие классов, на основе которых создаются будущие объекты - элементы управления, от классов-контейнеров. Объекты-контейнеры могут содержать внутри себя другие объекты, в то же время допуская манипуляции с этими внутренними объектами. Их можно назвать составными объектами, при этом отдельные составляющие части не теряют своего "суверенитета". Объекты - элементы управления, основанные на не контейнерных классах, хотя тоже могут состоять из нескольких составных частей, допускают манипуляции с ними только как с единым компонентом.
    Некоторые базовые классы занимают особое положение в связи с тем, что сами являются составной частью другого базового класса и поэтому не могут быть основой для создания подкласса (на рис 5.2 выделены пунктирной линией).


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

    Вновь создаваемый подкласс автоматически наследует все свойства и методы родительского класса, но вы всегда можете изменить какие-то из этих свойств или методов для выполнения специализации данного подкласса. Наследование поддерживается не только при создании подкласса, но и в дальнейшем. Таким образом, все сделанные вами изменения в родительском классе тут же отразятся на его подклассах. Как видно на рис. 5.1, класс кнопок для вывода данных на печать наследует свой внешний вид от класса графических кнопок, но имеет специализированное изображение и, очевидно, специфическую реакцию на нажатие. Если мы решим изменить размер кнопки в классе графических кнопок, изменятся размеры всех используемых в приложении кнопок, стоящих ниже в иерархии классов.
    Оператор указания диапазона позволяет вызвать метод родительского класса с более низкого уровня, в пределах описания подкласса. Это позволяет расширить функциональность объекта без необходимости написания лишнего программного кода. При создании подкласса он автоматически наследует все методы родительского класса. Мы можем изменить унаследованный метод и в то же время выполнить не только этот измененный метод для данного подкласса, но и метод родительского класса. Оператор имеет следующий синтаксис:
cClassName::Method


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

    Это похоже на понятие абстракция - скрытие внутренних данных, то есть использование принципа создания объекта как "черного ящика". Такой объект будет работать без раскрытия своей внутренней структуры, обеспечивающей его функциональность. Элементы управления, основанные на не контейнерных классах, являются хорошим примером использования принципа инкапсуляции. Использование инкапсуляции дает два очевидных преимущества программисту:

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

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

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


Обращение - это инструкция от одного объекта к другому для выполнения одного из методов того объекта, к которому обращаются.

    Различают три части обращения: имя объекта, получающего сообщение, имя метода и, возможно, передаваемые параметры, если того требует выполняемый метод.
    В обращении имя объекта отделяется специальным оператором - точкой (.). Например, если надо сделать недоступным объект - список с именем MyList, необходимо выполнить команду:
MyList.Enabled = .F.
    Это вызовет изменение свойства, контролирующего доступность данного объекта для работы с ним пользователя. Список изменит свой внешний вид и для возвращение его в рабочее состояние нужна команда:
MyList.Enabled = .T.
    Обращение к объекту для выполнения каких-либо действий аналогично обращению для изменения его свойств. После имени объекта мы должны указать имя метода:
MyList.Refresh()
    В некоторых ситуациях мы не сможем прямо обратиться к интересующему нас объекту. Например, если мы захотим обратиться к упомянутому выше списку из другой формы, то должны будем послать наше обращение не списку, а форме, содержащей нужный список:
MyForm.MyList.Enabled = .T.
    Такой порядок обращения к объекту может показаться весьма утомительным, особенно если представить себе достаточно длинную цепочку вложенных объектов. Однако это позволяет не подыскивать сотню уникальных имен для кнопки выхода в каждой из 100 используемых в приложении форм. Все кнопки могут иметь одно и то же имя cmdClose, и для каждого обращения найдется правильный адресат, т. к. в них будет использоваться имя нужной формы:
FormName.cmdClose
    Значительно сократить программный код позволяют операторы относительной ссылки, в которых, в отличие от абсолютной ссылки, не используются имена объектов:

  • THIS - позволяет сослаться на текущий объект;
  • THISFORM - позволяет сослаться на текущую форму;
  • THISFORMSET - позволяет сослаться на текущий набор форм.

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

Таблица 5.2. Обращение к объектам с помощью относительной адресации
Источник обращенияПример
обращения к
объекту
MyObject
Другой метод того же самого объектаTHIS.Enabled = .T.
Форма, включающая объектTHIS.MyObject.Enabled = .T.
Другой объект той же самой формыTHISFORM.MyObject.Enabled = .T.
Извне формыMyForm.MyObject.Enabled = .T.
Объект другой формы, входящей в один набор форм THISFORMSET.MyForm.
MyObject.Enabled = .T.
Извне набора формMyFormSet.MyForm.
MyObject.Enabled =.T.

    В Visual FoxPro и Visual Basic есть два свойства, которые позволяют выполнять действия относительно активного объекта, то есть объекта, с которым в данный момент работает пользователь (на который указывает курсор), без необходимости знания его имени. Свойство ActiveForm формы или набора форм имеет следующий синтаксис:
FormSet.ActiveForm.Property [= Setting]
    или
FormSet.ActiveForm.Method
    Это свойство позволяет узнать заданное в Property свойство для активной формы или выполнить указанный в Method метод. Если мы задаем параметр Setting, то указанное значение сравнивается с установленным, и в случае равенства возвращается .T. Если Setting не указывается, возвращается установленное значение свойства Property.
    Если мы не используем набор форм, то на месте FormSet в Visual FoxPro мы должны сослаться на экранный объект с помощью системной переменной _SCREEN. Эта системная переменная выполняет в таком случае несколько нестандартные для системных переменных в Visual FoxPro функции. Она играет роль ссылки на главное окно Visual FoxPro, позволяя управлять им как объектом. Например, для очистки главного окна Visual FoxPro от выведенных данных можно в окне Command написать команду CLEAR. Тот же самый результат будет достигнут, если мы напишем следующую строку:
_SCREEN.Cls
    В Visual Basic с этой же целью используется объект Screen. Например:
Screen.ActiveForm.MousePointer = 4
    Свойство ActiveControl позволяет сослаться на активный объект формы, страницы в многостраничной форме или панели инструментов. Синтаксис этого свойства следующий:
Object.ActiveControl.Property [= Setting]
    Если во время работы с формой мы в окне Debug наберем приведенную ниже строчку и будем перемещаться между разными элементами управления, то увидим имя активного в данный момент элемента управления:
_SCREEN.ActiveForm.ActiveControl.Name
    В связи с тем, что объектная модель Visual FoxPro поддерживает наследование, при работе с классами не обойтись без соответствующей информационной поддержки. Для получения информации о созданных объектах можно воспользоваться следующими свойствами. Эти свойства имеют статус "только для чтения" и не могут использоваться для изменения свойств объекта.
Object.BaseClass
    Возвращает имя базового класса, на основе которого создан указанный объект.
Object.Class
    Возвращает имя класса.
Object.ClassLibrary
    Возвращает имя файла пользовательской библиотеки классов, в которой содержится определение класса, на основе которого создан объект.
Object.ParentClass
    Возвращает имя класса, который является родительским для класса, на основе которого создан указанный объект.
Control.Parent
    Обеспечивает ссылку на содержащий элемент управления объект-контейнер. Например, мы можем изменить цвет фона формы при каких-либо действиях с включенным в нее элементом управления без необходимости знать имя этой формы:
THIS.Parent.BackColor = RGB(192,0,0)
    Таким образом, главное назначение этого свойства - использование его при создании универсальных классов элементов управления, способных воздействовать на объект, в котором будут размещены элеметы управления, созданные на основе этого класса.
    Для почти любого объекта мы можем записать комментарий, что может оказаться очень полезным на этапе отладки или сопровождения программы. Необходимо воспользоваться свойством
Object.Comment [ = cExpression]
    Это свойство удобно использовать для дополнительной идентификации объектов, если нет необходимости изменять установленные идентификаторы, доступные для СУБД.
    Записать какие-либо данные для объекта можно с помощью еще одного свойства
Object.Tag [ = Expression]
    Оба перечисленных выше свойства по умолчанию, если им не присвоены какие-либо значения, возвращают пустую символьную строку.
    Для работы с классами и созданными на их основе объектами из программы в Visual FoxPro существует несколько очень важных команд и функций, которые мы и рассмотрим. Мы советуем вам максимально использовать возможности визуальной работы с классами и объектами, которые описаны в главе 10. В то же время мы сознательно уделяем этим командам и функциям столько внимания при описании объектной модели даже несмотря на то, что этот материал имеет специфическое отношение только к Visual FoxPro, так как если вы внимательно разберете приведенные здесь примеры, то в дальнейшем будете уверенно ориентироваться среди рассматриваемых в этом параграфе сложных понятий ООП.

ADD CLASS ClassName [OF ClassLibraryName1] TO ClassLibraryName2 [OVERWRITE]

    Добавляет описание класса в визуальную библиотеку классов. Параметр Class-Name определяет имя класса, добавляемого в визуальную библиотеку классов ClassLibraryName2. Если файл визуальной библиотеки классов не существует, Visual FoxPro создает визуальную библиотеку классов и добавляет в нее определение класса. Если вы опускаете необязательную опцию OF ClassLibraryName1, Visual FoxPro ищет описание класса в любых визуальных библиотеках классов, открытых командой SET CLASSLIB. Visual FoxPro сгенерирует ошибку, если определение класса не может быть размещено или определение класса с именем, которое вы задаете, уже существует в ClassLibraryName2. Опция OF ClassLibraryName1 определяет визуальную библиотеку классов, из которой копируется определение класса. Опция OVERWRITE удаляет все классовые определения из визуальной библиотеки классов прежде, чем определение нового класса будет добавлено.
    Использование команды ADD CLASS добавляет определение класса в библиотеку классов или копирует определение класса из одной визуальной библиотеки классов в другую. Определение класса не может быть добавлено из программы, процедурного файла или приложения Visual FoxPro (файлы с расширениями PRG или APP).

DEFINE CLASS ClassName1 AS ParentClass
     [[PROTECTED Property1, Property2 ...]
Property = Expression...]
     [ADD OBJECT [PROTECTED] Object AS ClassName2 [NOINIT]
[WITH cPropertylist]]...
     [[PROTECTED] FUNCTION | PROCEDURE Name
[NODEFAULT]
cStatements
     [ENDFUNC | ENDPROC]]...
ENDDEFINE

    Создает определяемый пользователем класс или подкласс и задает свойства, события и методы для класса или подкласса. Параметр ClassName1 определяет имя создаваемого класса.
    ОпцияAS ParentClass определяет родительский класс, на котором будет основан создаваемый класс или подкласс. Родительским классом может быть базовый класс Visual FoxPro, такой, например, как Form или любой другой определяемый пользователем класс или подкласс. Невизуальный определяемый пользователем класс может быть создан определением имени Custom для ParentClass.
    С помощью опции [PROTECTED Property1, Property2 ...] Property = Expression... можно назначить свойства создаваемому классу и установить для них значения, которые будут использоваться по умолчанию. Знак равенства говорит о том, что свойству PropertyName присваивается значение выражения Expression. Чтобы предотвратить доступ и изменение значений свойств вне определения класса или подкласса, включайте опцию PROTECTED и список защищенных свойств. Методы и события внутри определения класса или подкласса могут обращаться к защищенным свойствам.
    Опция ADD OBJECT позволяет добавить объект к определению класса или подкласса из базового класса Visual FoxPro, определяемого пользователем класса или подкласса, либо из класса OLE. Параметр Object определяет имя объекта и используется для ссылки на объект изнутри определения класса или подкласса после его создания. Параметр ClassName определяет имя класса или подкласса, содержащего объект, который вы добавляете к определению класса. Опция NOINIT указывает на то, что метод Init не выполняется при добавлении объекта.
    Опция WITH cPropertyList определяет список свойств и значений свойств объекта, который вы добавляете к определению класса или подкласса.
    Опции FUNCTION Name или PROCEDURE Name позволяют создать описание действий, выполняемых при возникновении события или выполнении метода для класса или подкласса. События и методы создаются как набор функций или процедур.
    Включение опции NODEFAULT указывает на то, что Visual FoxPro не будет реагировать на события, как это должно было бы случиться, или выполнять процедуры обработки методов. Это позволяет использовать свои собственные обработчики определенных событий, отличающиеся от логики, принятой в Visual FoxPro. Опция NODEFAULT может располагаться в любом месте внутри процедуры обработки события или метода, но эта опция должна быть помещена внутри процедуры обработки события или метода в Конструкторе формы (Form Designer).
    Параметр cStatements - это команды Visual FoxPro, которые выполняются, когда вызывается событие или метод.
    Функции и процедуры событий и методов могут принимать значения путем включения оператора PARAMETERS как первой выполняемой строки в функцию или процедуру.
    Чтобы создать объект на основе определения класса или подкласса, используйте функцию CREATEOBJECT() с именем соответствующего класса или подкласса.
    Определения класса и подкласса, созданные с помощью команды DEFINE CLASS, не могут размещаться внутри команд структурного программирования типа IF...ENDIF или DO CASE...ENDCASE и в циклах типа DO WHILE...ENDDO или FOR...ENDFOR.
    В качестве примера посмотрим, как используется эта команда для создания объектов. Создадим три различные формы.

oForm1 = CREATEOBJECT("frmTestForm")
oForm2 = CREATEOBJECT("frmTestForm")
oForm3 = CREATEOBJECT("frmTestForm")
* Изменим их заголовки
oForm1.Caption = "Первая форма"
oForm2.Caption = "Вторая форма"
oForm3.Caption = "Третья форма"
* Выведем на экран с помощью метода Show первую форму
oForm1.Show
* Немножко раздвинем их на экране
oForm2.Move(oForm1.Left + 50, oForm1.Top + 50)
oForm2.Show
oForm3.AutoCenter = .T.
oForm3.Show
* Подождем реакции пользователя
READ EVENTS
* Определим класс для создания наших форм
DEFINE CLASS frmTestForm AS Form
    BackColor = RGB(192,192,193)
    Caption = "TestForm"
    * Добавим в форму управляющую кнопку
    * для закрытия формы
    ADD OBJECT cmdExit AS CommandButton WITH ;
Caption = "\<<Выход", ;
Left = 150, ;
Top = 100, ;
AutoSize = .T.
    PROCEDURE cmdExit.Click
RELEASE THISFORM
* Когда с экрана будет убрана последняя форма,
* отменим состояние ожидания
IF _SCREEN.FormCount = 1
CLEAR EVENTS
ENDIF
    ENDPROC
ENDDEFINE

    Следующая команда:

SET CLASSLIB TO ClassLibraryName [ADDITIVE]
     [ALIAS AliasName]

    Открывает визуальную библиотеку классов с определениями хранящихся в ней классов. Параметр ClassLibraryName определяет имя файла библиотеки. Опция ADDITIVE позволяет открыть указанную библиотеку, не закрывая открытой ранее. Опция ALIAS AliasName позволяет задать псевдоним для библиотеки, на который можно ссылаться при создании объекта на базе класса, определение которого хранится в данной библиотеке. Задание этой команды в виде SET CLASSLIB TO закрывает все открытые библиотеки классов.

RELEASE CLASSLIB ClassLibraryName

    Позволяет закрыть указанную визуальную библиотеку классов из открытых ранее.
    Помимо команд при работе с классами в программе не обойтись без следующих функций.
CREATEOBJECT(ClassName [, Parameter1, Parameter2, ...])
    Создает объект из описания класса или объекта OLE. Аргумент ClassName определяет класс или OLE-объект, из которого будет создан новый объект. Visual FoxPro ищет класс или OLE-объект в следующем порядке:

  1. Базовые классы Visual FoxPro.
  2. Определяемые пользователем описания классов в том порядке, в котором они были загружены в память.
  3. Классы в текущей программе.
  4. Классы в библиотеках классов, открытые с помощью SET CLASSLIB.
  5. Классы в процедурах, открытых с помощью SET PROCEDURE.
  6. Классы в последовательности выполнения программ Visual FoxPro.
  7. Регистр Windows (для объектов OLE).

    Для создания OLE-объектов используется следующий синтаксис параметра ClassName:
ApplicationName.Class
    Например, для работы с таблицами Microsoft Excel с помощью средств OLE вы можете написать:
oExcelSheet = CREATEOBJECT("Excel.Application")
    Когда этот код будет выполнен, запускается Microsoft Excel в скрытом для пользователя виде. Вы не сможете обнаружить его отображение на панеле задач Windows 95. Но в перечне загруженных задач, появляющемся при нажатии клавиш Ctrl+Alt+Del, в этом случае пакет Excel присутствует. Заметьте также, что даже если пакет Excel загружен на компьютере, в скрытом виде загружается еще одна его копия. Подробнее работу OLE Automation мы обсудим в десятой главе.
    Необязательные параметры Parameter1, Parameter2, ... используются, чтобы передать значения в процедуру события Init для класса. Событие Init выполняется, когда вы используете функцию CREATEOBJECT() и она разрешает инициализацию объекта.
    Используйте функцию CREATEOBJECT() для создания объекта из описания класса или объекта OLE и назначения ссылки на объект с помощью переменной или элемента массива. Прежде чем вы сможете создать объект из определяемого пользователем класса, необходимо его определить с помощью команды DEFINE CLASS или получить к нему доступ в визуальной библиотеке классов, открытой с помощью SET CLASSLIB. Используйте знак равенства или команду STORE для назначения ссылки на объект с помощью переменной или элемента массива.
    В качестве примера с помощью этой функции давайте программно создадим несколько объектов на базе одного класса. В визуальной библиотеке классов у нас хранится описание класса панели инструментов. Создадим на его основе три панели и зададим им разные свойства.

* Открываем визуальную библиотеку классов
SET CLASSLIB TO Office
* Создаем три объекта
oTbr1=CREATEOBJECT("Office_Toolbar")
oTbr2=CREATEOBJECT("Office_Toolbar")
oTbr3=CREATEOBJECT("Office_Toolbar")
* Изменяем для каждой созданной панели заголовок ее окна
oTbr1.Caption = "Первая панель"
oTbr2.Caption = "Вторая панель"
oTbr3.Caption = "Третья панель"
* Для первой панели изменим цвет фона
oTbr1.BackColor = RGB(0,0,255)
* Выведем их на экран
oTbr1.Show
oTbr2.Show
oTbr3.Show
* Дадим 20 с для того, чтобы можно было их рассмотреть и
* подвигать
READ TIMEOUT 20

    Для определения ссылки на создаваемые объекты удобно использовать массив, как это видно из следующего примера, в котором создается пять форм.

* Определяем массив для создания ссылки
PUBLIC ARRAY aTest(1)
DIMENSION aTest(5)
* Очищаем экран
_SCREEN.CLS
* Создаем пять форм и помещаем ссылки на них в массив
FOR nCount = 1 TO 5
    aTest(nCount) = CREATEOBJECT("frmTestForm")
    * Размещаем их по центру экрана
    aTest(nCount).AutoCenter = .T.
ENDFOR
* Выводим созданные формы на экран
FOR nCount = 1 TO 5
IF TYPE("aTest(nCount)") = "O"
aTest(nCount).Show
ENDIF
ENDFOR
* Определяем класс для создаваемых форм с кнопкой
* для ее стирания
DEFINE CLASS frmTestForm AS Form
ADD OBJECT cmdExit As CommandButton WITH ;
    Caption = "\<<Выход", ;
    Top = 111, ;
    Left = 108, ;
    Height = 29, ;
    Width = 94, ;
    Visible = .T.
PROCEDURE cmdExit.Click
     RELEASE ThisForm
ENDPROC
ENDDEFINE

    Функция
AINSTANCE(ArrayName, cClassName)
    Размещает все образцы класса в массиве. Аргумент ArrayName определяет имя массива, в котором размещаются образцы. Если массива, который вы определяете, не существует, Visual FoxPro автоматически создаст его. Если массив существует, но не достаточно большой, чтобы вместить все образцы, Visual FoxPro автоматически увеличит его размер. Если массив оказывается больше, чем необходимо, Visual FoxPro усечет его до нужных размеров. В случае, когда массив существует и функция AINSTANCE() возвращает 0 - никакие образцы не найдены, - массив остается неизменным. Аргумент cClassName определяет имя базового класса Visual FoxPro, пользовательского класса или объекта Visual FoxPro (Cursor, DataEnvironment, Relation). Функция AINSTANCE() возвращает количество образцов класса, размещенных в массиве.
AMEMBERS(ArrayName, Object [, 1 | 2])
    Размещает в массиве для указанного объекта имена свойств, процедур и включенных объектов. Аргумент ArrayName определяет массив, в который записываются имена элементов свойств для ObjectName. Если массив не достаточно большой, чтобы вместить все имена, Visual FoxPro автоматически увеличивает его размер. Если вы определяете существующий двумерный массив, Visual FoxPro преобразует его в одномерный. Аргумент Object определяет объект, элементы свойств которого размещаются в массиве, указанном в ArrayName. Аргумент Object может представлять собой любое выражение, имеющее отношение к объекту, типа ссылки на объект, переменной объекта или элемента массива объекта. Аргумент 1 указывает на то, что в массив будут включены как свойства объекта, так и методы и включенные объекты. Массив является двумерным со вторым столбцом, уточняющим, к какому типу относится элемент, внесенный в список в первом столбце. Возможные значения для второго столбца: Property, Event, Method или Object. Аргумент 2 указывает на то, что массив будет содержать имена объектов, являющихся элементами объекта, указанного в Object. Массив является одномерным. Эта опция обеспечивает метод для определения имен всех форм в наборе форм или элементов управления в форме. Функция AMEMBERS() возвращает количество объектов, свойств и процедур для объекта, либо 0, если массив не может быть создан.
    COMPOBJ(oExpression1, oExpression2)
    Сравнивает свойства двух объектов и возвращает значение "истина" (.T.), если их свойства и значения свойств идентичны. Аргументы oExpression1, oExpression2 определяют объекты для сравнения. Параметры oExpression1 и oExpression2 могут быть любыми определяющими объекты выражениями, такими как ссылки на объект, переменные объекта или элементы массива объекта.
    Функция COMPOBJ() возвращает значение "ложь" (.F.), если объект имеет такие свойства, которых нет у другого объекта, или если объекты имеют идентичные свойства, но значения одного или нескольких свойств оказываются различными.

5.2. Объекты и их свойства

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

  • основными объектами и элементами управления для создания интерфейса пользователя;
  • назначением отдельных объектов;
  • основными свойствами объектов;
  • компонентами для расширения возможностей разработчика - объектами ActiveX.

    В Visual FoxPro создание объектов поддерживается стройной и мощной системой классов. На основе базовых классов программист может создать свои классы и, компонуя их в соответствующие библиотеки, обеспечивать их доступность для создания объектов и элементов управления в разрабатываемом приложении, как это показано на схеме, приведенной на рис. 5.3. Конечно, если быть совсем точным, эта схема существенно упрощена по сравнению с реальными возможностями. В распоряжении программиста, разрабатывающего приложение на Visual FoxPro, еще есть объекты для работы с данными при построении форм и отчетов, которые не имеют классов, и есть возможность использовать объекты других приложений и объекты ActiveX. Об этом мы поговорим в следующих главах.
    В отличие от Visual FoxPro, в Visual Basic нет системы классов, и программист работает непосредственно с набором предоставляемых ему объектов. По аналогии с Visual FoxPro можно сказать, что на схеме, приведенной на рис. 5.3, в его распоряжении находятся первый и последний блоки.


Рис. 5.3.

    В табл. 5.1 был приведен список объектов, которые программист может создать в Visual FoxPro на основе базовых классов. Визуально представляемые объекты легко создаются при проектировании форм простым перетаскиванием нужного класса объекта с панели инструментов Form Control на поверхность формы. Соответствующие кнопки этой панели инструментов можно видеть на рис. 5.4.


Рис. 5.4.

    В Visual Basic аналогичные функции выполняет панель инструментов, которая называется ToolBox. Она содержит довольно похожий набор объектов и элементов управления (рис. 5.5). Причем, если в Visual FoxPro мы можем расширить набор объектов, используемых при разработке приложения за счет подключения дополнительных библиотек классов, то в Visual Basic дополнительные объекты просто включаются в панель инструментов ToolBox.


Рис. 5.5. Визуальные объекты и элементы управления в Visual Basic

    Большинство объектов имеют достаточно общий набор свойств для определения их местоположения на экране или в форме, внешнего оформления и т. д. Отличия касаются в основном способов обеспечения тех особых функций, для которых собственно объект и существует в приложении.
    Дадим краткий комментарий тех свойств, которые есть у большинства объектов.
    Как вы уже заметили, чтобы что-то сделать с объектом, надо к нему обратиться. Каждый объект имеет уникальный идентификатор, который называется именем объекта. При создании объекта по умолчанию ему назначается имя, которое включает имя класса, на основе которого создается объект, и цифру по порядку включения в объект-контейнер. Например, при создании кнопки управления в форме она получит имя CommandButton1. Если мы создадим в этой форме еще одну кнопку, она получит имя CommandButton2 и т. д. Чтобы изменить имя объекта, надо использовать свойство
Object.Name [ = cName]
    Параметр определяет имя указанного объекта.
    В четвертой главе мы уже останавливались на общепринятых соглашениях о наименовании переменных. В табл. 5.3 приведены рекомендации по наименованию объектов, которые основаны на стандартах Visual Basic. В соответствии с ними тип объекта (префикс) характеризуется тремя прописными буквами. Каждая смысловая часть в имени объекта начинается с большой буквы, но не отделяется знаком подчеркивания.

Таблица 5.3. Правила наименования объектов
ОбъектПрефиксПример
CheckBoxchkchkReadOnly
ColumngrcgrcCurrentPrice
ComboBoxcbocboEnglish
CommandButton cmdcmdCancel
CommandGroupcmgcmgChoices
ContainercntcntMoverList
ControlctlctlFileList
Data ControldatdatAvto
Drive List BoxdrvdrvTarget
EditBox edtedtTextArea
File List BoxfilfilSource
FormfrmfrmFileOpen
FormSetfrsfrsDataEntry
FramefrafraControls
GridgrdgrdPrices
HeadergrhgrhTotalInventory
HScrollBarhsbhsbVolume
ImageimgimgIcon
LabellbllblHelpMessage
LinelinlinVertical
ListBoxlstlstPolicyCodes
OLEoleoleObject1
OLEBoundContrololbolbObject1
OptionButton optoptFrench
OptionGroupopgopgType
PagepagpagDataUpdate
PageFramepgfpgfLeft
SeparatorsepsepToolSection1
ShapeshpshpCircle
SpinnerspnspnValues
TextBoxtxttxtGetText
TimertmrtmrAlarm
ToolBartbrtbrEditReport
VScrollBarvsbvsbVolume

    Большинство объектов может отображать какой-либо текст. Мы имеем возможность выбрать вид шрифта для вывода текста с помощью свойства
Object.FontName [ = cName]
    Параметр cName определяет имя шрифта, который будет использоваться объектом с именем Object. По умолчанию будет использоваться шрифт Arial. Если вы изменяете шрифт и какие-либо его параметры, первоначально установите имя шрифта, а затем такие его параметры, как размер и начертание.
Object.FontSize [ = nSize]
    Устанавливает размер используемого шрифта в пунктах. По умолчанию используется шрифт размером 10 пунктов. Максимальное значение для nSize составляет 2048 пунктов. Напомним, что 1 мм составляет примерно 2,8 пункта.
Object.FontBold [ = lExpression]
    Устанавливает полужирное начертание шрифта, если параметр равен .T.. Это значение принято по умолчанию.
Object.FontItalic [ = lExpression]
    Устанавливает наклонное начертание шрифта, если параметр равен .T.. По умолчанию принято значение .F..
Object.FontStrikeThru [ = lExpression]
    Устанавливает перечеркнутое начертание шрифта, если параметр равен .T.. По умолчанию принято значение .F..
Object.FontUnderline [ = lExpression]
    Устанавливает подчеркнутое начертание шрифта, если параметр равен .T.. По умолчанию принято значение .F..
    Практически все объекты могут иметь различный цвет. Для изменения цвета объекта, как при его создании, так и в процессе работы программы, можно использовать следующие свойства.
Object.BackColor [ = nColor]
    Задает цвет фона объекта. Параметр nColor представляет собой число, которое обозначает цвет. Вместо этого числа удобнее использовать функцию
RGB(nRedValue, nGreenValue, nBlueValue)
    которая возвращает нужное значение nColor в зависимости от сочетания интенсивностей красного nRedValue, зеленого nGreenValue и синего nBlueValue цветов. Каждое значение интенсивности может меняться от 0 до 255. Максимальное значение обозначает наибольшую интенсивность цвета. В табл. 5.4 приведены значения для типичных цветов.

Таблица 5.4. Значения для типичных цветов
ЦветаЗначения RGBЗначение nColor
Белый255, 255, 25516777215
Черный0, 0, 00
Серый192, 192, 19212632256
Темно-серый128, 128, 1288421504
Красный255, 0, 0255
Темно-красный128, 0, 0128
Коричневый255, 255, 065535
Бежевый128, 128, 032896
Зеленый0, 255, 065280
Темно-зеленый0, 128, 032768
Морской волны0, 255, 25516776960
Темный морской волны0, 128, 1288421376
Синий0, 0, 25516711680
Темно-синий0, 0, 1288388608
Малиновый255, 0, 25516711935
Темно-малиновый128, 0, 1288388736

Object.ForeColor [ = nColor]
    Задает цвет выводимых символов.
Object.BorderColor [ = nColor]
    Задает цвет рамки.
Control.BorderWidth[ = nWidth]
    Для указанного элемента управления задает ширину рамки. Параметр nWidth может изменяться от 0 до 8192. Естественно, если параметр nWidth будет равен 0, рамка рисоваться не будет.
    Кроме текста многие элементы управления могут выводить изображение. Например, достаточно часто какое-то изображение (пиктограмма) на кнопке управления воспринимается оператором легче, чем надпись. К тому же такой подход позволяет проще реализовать многоязычные приложения, так как пиктограмма в отличие от текста не требует перевода. В то же время следует учитывать, что использование изображений требует больших ресурсов компьютера. Для вывода изображений на элементах управления служит свойство
Control.Picture[ = cFileName | GeneralFieldName]
    Изображение может храниться либо в файле cFileName, либо в поле типа General GeneralFieldName. Изображение должно храниться в формате BMP или ICO.
    Для объектов, которые не имеют обозначенных какими-либо видимыми элементами границ, можно установить свой фон или сделать их прозрачными, то есть принять для них фон объекта-контейнера, на котором они располагаются, с помощью следующего свойства
Object.BackStyle [ = nStyle]
    Для того чтобы фон стал прозрачным, параметр nStyle должен иметь значение 0, при этом установка свойства BackColor игнорируется. Для установки собственного фона объекта параметр nStyle должен быть равен 1.
    Наиболее часто используемые объекты для их идентификации пользователем имеют заголовки - надписи, размещаемые на элементе управления (кнопка управления, поле проверки) или вверху объекта (форма, страница). При создании такого нового объекта или элемента управления они получают по умолчанию заголовок такой же, как имя объекта. Изменить заголовок можно с помощью свойства
Object.Caption [ = cText]
    Параметр cText определяет текст заголовка для указанного объекта.
    Для задания размеров объекта и его расположения можно использовать следующие свойства:
Object.Height [ = nValue]
    Параметр nValue определяет высоту указанного объекта.
[Object.]Width [ = nValue]
    Параметр nValue определяет ширину указанного объекта.
Object.Left [ = nValue]
    Параметр nValue определяет расстояние от левого края объекта-контейнера до левой границы указанного объекта.
Object.Top[ = nValue]
    Параметр nValue определяет расстояние от верхнего края объекта-контейнера до верхней границы указанного объекта.
    Единица измерения для параметра nValue в четырех вышеперечисленных свойствах определяется свойством
Object.ScaleMode = nMode
    которое воздействует на форму или панель инструментов, а следовательно, действует и для всех расположенных в них объектах или элементов управления.
    В Visual FoxPro если параметр nMode равен 0, то в качестве единицы измерения используется фоксель, если 3 - пиксель (минимальная точка, которая может быть отображена на экране). Фоксель - это единица измерения, которая используется в Visual FoxPro для облегчения разработки приложений, которые должны работать и в текстовой и в графической среде. Фоксель примерно соответствует максимальной высоте и средней ширине символа в используемом шрифте. Мы настоятельно рекомендуем вам использовать пикселы, так как в противном случае вы рискуете наблюдать свои формы в виде, несколько отличном от предполагаемого при разработке. Недостатком использования пикселов является то, что на разных системах дисплеев и при разном разрешении число пикселов, которые размещаются на экране, различно. Это ведет к тому, что созданный при одном разрешении экранный интерфейс будет занимать слишком мало места при более высоком разрешении или не умещаться на экране при более низком. Для приложений производственного использования приемлемым решением является ограничение пользователя в выборе разрешения экрана. Если это не приемлемо, придется прибегнуть к специальным методам проектирования пользовательского интерфейса, обеспечивающим отслеживание установленного разрешения монитора и автоматическую коррекцию выводимых программой экранных элементов.
    В Visual Basic параметр nMode может принимать следующие значения:

  • 0 - используется собственная координатная система;
  • 1 - twip - единица измерения, которая обеспечивает сохранение пропорций пользовательского интерфейса независимо от используемых систем дисплеев;
  • 2 - типографский пункт (то же, что для шрифтов);
  • 3 - пиксель;
  • 4 - символ (120 twip по горизонтали и 240 - по вертикали);
  • 5 - дюйм;
  • 6 - миллиметр;
  • 7 - сантиметр.

    Пользователю значительно помогает ориентироваться в интерфейсе прикладной программы возможность получения оперативной подсказки о назначении того или иного элемента управления. Текст такой подсказки, которая появляется, если пользователь задержит указатель мыши на элементе управления, определяется свойством
Control.ToolTipText = cText
    Параметр должен содержать подсказку для указанного элемента управления.
    Для создания ссылки в файле контекстной помощи в пользовательской программе можно использовать следующее свойство
Object.HelpContextID [ = nContextID]
    Параметр nContextID определяет идентификатор темы, содержание которой выводится на экран, если пользователь нажимает клавишу F1, когда активен указанный объект.
    Естественно, мы используем в программе элементы управления, чтобы узнать желание пользователя выполнить то или иное действие. Определить этот выбор помогает свойство
Control.Value [ = nSetting]
    которое возвращает информацию о состоянии указанного элемента управления. При более подробном описании каждого объекта мы еще остановимся на особенностях использования этого свойства. Если мы предварительно хотим установить для элемента управления какое-то значение с помощью параметра nSetting, то следует соблюдать правильный тип данных, соответствующий элементу управления.
Object.Visible [ = lExpression]
    Позволяет сделать указанный объект невидимым на экране, если выражение lExpression будет иметь значение .F.. При создании объекта в Конструкторе формы свойство по умолчанию имеет значение .T., в программе - .F.. При добавлении объекта в форму, пока происходит определение его свойств или при изменении сразу нескольких характеристик объекта, чтобы избежать многочисленных перерисовок, установите свойство Visible равным .F..
Object.Enabled [ = lExpression]
    Позволяет сделать объект недоступным для изменения пользователем, если выражение lExpression будет иметь значение .F.. При этом данный объект перестает реагировать на какие-либо события и может использоваться, как например, TextBox или EditBox, только для отображения выводимых в него данных.
     Управлять порядком перемещения пользователя по элементам управления можно с помощью свойства
Control.TabIndex [ = nOrder]
    Параметр определяет номер элемента управления в объекте-контейнере (например, в форме), в соответствии с которым по умолчанию будет регулироваться порядок перехода пользователя к следующему элементу управления.
    Если вы заранее знаете, что будущие пользователи не любят использовать мышь, то установить действие, происходящее для элемента управления при нажатии клавиши Tab можно с помощью свойства
Control.TabStop [ = lExpression]
    Выражение lExpression определяет, включен ли элемент управления Control в стек свойства TabIndex для перехода между элементами управления с помощью клавиши Tab. Если выражение lExpression равно .F., то элемент управления в стек не включен, и при нажатии клавиши Tab этот элемент пропускается.
    Конечно, при создании приложения для обработки данных нас больше всего волнуют объекты, прямо для этого предназначенные. Поэтому более подробный разговор начнем именно с таких объектов.

Объекты для работы с данными

    Наиболее универсальным объектом для работы с данными, бесспорно, является Text Box - текстовое поле. С его помощью можно отображать и редактировать данные любого типа, кроме, пожалуй, изображений.
    Для того чтобы элемент управления отображал какие-то данные или изменял свое значение в зависимости от каких-либо условий, его надо привязать к переменной или полю в таблице. Сделать это в Visual FoxPro можно с помощью свойства
Object.ControlSource [ = cName]
    В параметре cName указывается имя переменной или поля в таблице.
    В Visual Basic для того, чтобы привязать какой-либо объект к данным в БД, необходимо сначала создать объект Data - элемент управления для работы с БД и указать для него в свойстве
Object.DatabaseName [ = cName]
    имя и путь к базе данных. Если в качестве источника данных используется формат, в котором таблицы хранятся в отдельных файлах и не объединены на постоянной основе, например FoxPro 2.x, то указывается только путь к папке с этими файлами.
    В число обязательных действий включается установка значений еще для двух свойств. Сначала выберите значение для свойства
Object.RecordsetType [= Value ]
    Процессор баз данных Microsoft Jet допускает выбор из трех вариантов:

    0 - tables - позволяет работать непосредственно с таблицами. Этот вариант допустим только для Access или БД, поддерживаемых драйверами ISAM. Но его нельзя использовать, например, для работы с БД, расположенной на MS SQL Server.
    1 - dynasets - позволяет создать обновляемый набор записей, выбирая и считывая из источника данных только необходимые записи на основе уникальных ключевых значений для каждой записи. Этот способ позволяет снизить объем данных, передаваемых на рабочую станцию с сервера. Данные из полей примечаний и изображения считываются только тогда, когда возникает необходимость их отображения на экране.
    2 - snapshots - позволяет создать набор записей, которые не будут иметь возможности обновления в источнике данных.
    После этого вы можете выбрать нужную для работы таблицу с помощью свойства
Object.RecordSource [= Value ]
    В качестве параметра Value для этого свойства можно использовать имя таблицы, символьное выражение, содержащее команду SQL, приемлемую для используемой БД, или имя одного из объектов QueryDef, содержащегося в коллекции QueryDefs объекта Database (об объектах для доступа к данным, используемых в процессоре баз данных Microsoft Jet, см. главу 6).
    Вот теперь, вернувшись к объекту TextBox и предварительно указав в свойстве DataSource имя элемента управления для работы с БД, мы можем назначить для него требуемый источник данных с помощью свойства
Object.DataField [ = cName]
    В качестве параметра cName вы можете указать имя поля, данные из которого хотите отобразить в текстовом поле.
    Для вывода и редактирования больших объемов текстовой информации, которая может храниться, например, в полях примечаний, в Visual FoxPro есть специальный элемент управления - EditBox - поле редактирования. В поле редактирования доступны все возможности по работе с текстом, такие как вырезка, копирование и т. д. Текст в поле редактирования может прокручиваться по вертикали, а длинные строчки автоматически усекаются по правой границе поля и переносятся на следующую строку.
    В Visual Basic для этого используется текстовое поле, которое имеет специальное свойство Multiline. При установке его значения в True текстовое поле может занимать несколько строк.
    В том случае, если пользователь должен выбрать какие-то значения из списка, лучше всего использовать элементы управления ComboBox - раскрывающийся список или ListBox - список.
    В случае, если необходимо так организовать ввод данных, чтобы дать пользователю возможность выбирать данные только из заранее определенного списка, следует присвоить свойству Style значение 2 (drop-down list). Комбинированный список с возможностью ввода создается при значении свойства Style равным 0 (drop-down combo). В Visual Basic вы можете использовать еще одно значение - 1. При этом создается список Simple Combo, состоящий из текстового поля, в которое пользователь может вводить данные, и незакрывающегося списка.
    В комбинированный список можно включать самые разнообразные данные. В Visual Basic источник данных будет определяться по такой же схеме, как для текстового поля. В Visual FoxPro тип определяется значением свойства RowSourceType.
Control.RowSourceType [ = nSource]
    Значения параметра nSource могут быть:

  • 0 - (по умолчанию) - нет данных. Список заполняется во время работы пользовательской программы с помощью методов AddItem или AddListItem.
  • 1 - значения. Список заполняется данными, непосредственно указанными в свойстве RowSource.
  • 2 - псевдоним. Список заполняется данными из полей в таблице, открытой в указанной рабочей области.
  • 3 - операторы SQL.
  • 4 - запрос. В список помещаются результаты выполнения файла запроса (QPR).
  • 5 - массив.
  • 6 - поля. В отличие от значения 2, поля в список можно включить в произвольном порядке и из различных таблиц.
  • 7 - файлы.
  • 8 - структура таблицы.

    Для заполнения списка используются значения, задаваемые свойством
Control.RowSource [ = cList]
    Параметр cList может представлять, в зависимости от значения свойства RowSourceType, разделенный запятыми список значений, таблиц, файлов, операторы SQL, имя массива или имя файла запроса. Перечень файлов можно задать, используя символы шаблона.
    В Visual Basic для вывода списков файлов, доступных устройств или папок есть специальные объекты - FileListBox, DirListBox и DriveListBox. Комбинация этих элементов дает возможность интерактивного выбора пользователем каких-либо файлов или места записи данных во время работы пользовательского приложения.
    В первых двух список выводимых файлов или папок определяется свойством Path.
    Данные, которые принимают одно из двух значений, наиболее удобно отображать с помощью элемента управления CheckBox - поле проверки.
    Свойство Value этого элемента управления может принимать значение "истина" .T. (1) или "ложь" .F. (0). Например, при изменении данных можно создать копию файла с данными до изменения, а можно не создавать. Программно для поля проверки можно задать и третье, неопределенное состояние, когда элемент управления не находится ни в первом, ни во втором состоянии. При этом свойство Value будет иметь значение NULL или 2.
    Все вышеупомянутые объекты способны отображать данные из одного поля. Исключением являются списки, так как они могут отображать несколько колонок, а следовательно, и полей с данными. Но все-таки исключительно любимым программистами и, что особенно важно, пользователями способом представления данных остается таблица. Для создания таблицы проще всего использовать специально предназначенный для этого объект - Grid.
    В отличие от Visual FoxPro в Visual Basic нет "родного" объекта Grid. Для создания таблицы вы можете использовать поставляемые вместе с Visual Basic дополнительные элементы управления - ActiveX. Об этих объектах мы расскажем в отдельном разделе этого параграфа.
    Объект Grid является объектом-контейнером, который содержит объект-контейнер Columns, содержащий, в свою очередь, объект Header. Объекты Columns и Header тоже имеют свои свойства, события и методы. По умолчанию данные в каждой колонке отображаются с помощью текстового поля, но мы можем использовать для этого любой другой элемент управления, способный работать с данными. Например, ничто не мешает нам в каждой клетке Grid разместить еще один Grid.
    Объект Grid является элементом управления, который позволяет эффективно работать одновременно с несколькими строками данных и является функциональным эквивалентом Browse. В Grid мы можем помещать данные как из таблиц, так и из просмотров и курсоров или запросов. Целый ряд свойств позволяет динамически управлять Grid в зависимости от самых разнообразных условий. Например, мы можем легко обеспечить такую экзотическую функциональность, как вывод данных различным цветом в зависимости от их значения.
    Для работы с данными в Grid можно использовать следующие свойства.
Grid.RecordSourceType [ = nType]
    Определяет тип источника данных для заполнения Grid. Параметр nType может принимать следующие значения:

  • 0 - таблица. Автоматически открывается таблица, указанная в свойстве RecordSource.
  • 1 - псевдоним (по умолчанию).
  • 2 - по выбору пользователя. Источник данных устанавливает пользователь во время работы программы.
  • 3 - запрос. В свойстве RecordSource должно быть указано имя файла-запроса (QPR).

Grid.RecordSource [ = cName]
    Определяет имя источника данных. Чаще всего это псевдоним курсора или таблицы.
    Специальный набор свойств позволяет изменять параметры, установленные для колонки во время работы программы при каждом обновлении Grid. К таким свойствам относятся:

  • DynamicAlignment - выравнивание данных;
  • DynamicCurrentControl - используемый элемент управления;
  • DynamicForeColor - цвет символов;
  • DynamicBackColor - цвет фона;
  • DynamicFontName - имя шрифта;
  • DynamicFontSize - размер шрифта;
  • DynamicFontBold - полужирное начертание шрифта;
  • DynamicFontItalic - курсивное начертание шрифта;
  • DynamicFontStrikeThru - перечеркнутое начертание шрифта;
  • DynamicFontUnderline - подчеркнутое начертание шрифта.

Объекты для управления работой приложения

    В эту группу объектов выделим средства создания различного типа кнопок, с помощью которых пользователь может выполнить какое-либо действие или вариант работы приложения. Здесь сразу придется оговориться, что выбор подобных действий может быть организован с помощью практически любого элемента управления, включая и такие, как текстовое поле, изображения, линии и т. д. - лишь бы такой элемент управления реагировал на какие-нибудь события. Эту группу объектов мы выделили исключительно из-за того, что управление работой приложения является их главным предназначением и их трудно использовать, например, для работы с данными.
    Наиболее часто используемым объектом для управления работой приложения, несомненно, является элемент управления CommandButton - кнопка управления.
    Объект CommandButton создает отдельную управляющую кнопку. Управляющая кнопка обычно используется для запуска процедуры или события, которые реализуют какие-либо действия типа закрытия формы, перемещения к другой записи в таблице и т. д.
    На кнопку мы можем поместить поясняющий текст с помощью свойства Caption или изображение (только в Visual FoxPro) с помощью свойства Picture.
    Чтобы не задумываться над размерами кнопки, особенно если вы интерактивно меняете на ней текст, в Visual FoxPro установите для свойства Autosize значение .T..
    Как правило, действие, которое должно выполниться при нажатии на управляющую кнопку, определяется событием Click. Мы можем предусмотреть выполнение этого события и при нажатии клавиши Enter, для одной из двух или более управляющих кнопок в форме, когда активен какой-либо другой элемент управления, с помощью свойства
CommandButton.Default [ = lExpression]
    Если для указанной кнопки параметр lExpression равен .T., то эта кнопка сработает при нажатии клавиши Enter на любом другом элементе управления в форме. По умолчанию значение lExpression равно .F.. Естественно, только одна кнопка в форме может иметь значение lExpression, равное .T..
    Совершенно аналогично для одной из управляющих кнопок в форме мы можем предусмотреть выполнение присвоенного ей действия при нажатии клавиши Esc с помощью свойства
CommandButton.Cancel [ = lExpression]
    Для выбора какого-то одного действия из нескольких возможных лучше всего использовать кнопки выбора - OptionButton.
    Обратите внимание, что кнопку выбора мы можем использовать только как объект для создания группы кнопок выбора. Если вы используете визуальные средства проектирования, то кнопка выбора как объект может использоваться в Visual FoxPro только в Конструкторе класса.
    При создании кнопки выбора мы можем расположить поясняющий текст справа, как принято по умолчанию, или слева от изображения кнопки, присвоив свойству Alignment значение 1.
    Стоит отметить, что в Visual FoxPro для создания сразу нескольких кнопок существуют соответствующие объекты CommandButtonGroup и OptionButtonGroup. Их применение существенно ускоряет процесс создания экранных форм с постоянным набором управляющих действий.
    Объект Timer - таймер (счетчик времени) - позволяет задать интервал времени или продолжительность выполнения каких-либо действий в программе. В отличие от других элементов управления, этот объект не виден пользователю во время работы программы. Его назначение заключается только в обеспечении функциональности пользовательского приложения, связанной с продолжительностью работы.
    Основным свойством для таймера, которое позволяет задать интервал времени между его срабатыванием (выполнением события Timer), является
Timer.Interval [ = nTime]
    По умолчанию значение nTime равно 0, что препятствует срабатыванию таймера. Максимальное значение параметра nTime может быть равным 2147483647 миллисекунд, что превышает продолжительность 24 дней. При выборе значения для интервала срабатывания таймера необходимо учитывать следующее:

  • В связи с тем, что система вырабатывает прерывания с частотой 18 раз в секунду, реальное значение интервала не может быть меньше, чем 56 миллисекунд.
  • Установленное значение интервала может не соблюдаться, если система выполняет какие-либо длительные действия, связанные с большой загрузкой процессора (чтение и запись данных, интенсивные вычисления, сетевой доступ и т. д.). В этом случае событие Timer может наступить только после их завершения.
  • Чем меньшее значение вы устанавливаете для интервала, тем чаще программа должна генерировать событие Timer и, следовательно, меньше ресурсов будет оставаться на выполнение других операций, и скорость работы программы может существенно уменьшиться.

    Для сброса времени отсчета интервала и установки его отсчета с нуля используется метод Reset.
    В Visual Basic своеобразный элемент управления в виде движка может быть выполнен на основе объектов HScrollBar и VScrollBar. Эти же объекты могут быть использованы для прокрутки длинных списков или больших объемов данных.

Объекты для оформления интерфейса пользователя

    Объект Image создает элемент управления в виде изображения формата BMP. Может использоваться для создания областей на форме, реагирующих на действия пользователя.
    В Visual Basic кроме объекта Image есть и объект PictureBox, который обладает расширенной функциональностью, например, может выводить дополнительно изображения в формате ICO и WMF, но работает медленнее.
    Источник изображения для этого объекта устанавливается с помощью свойства

Control.Picture = cFileName

    В Visual FoxPro источник изображения может храниться и в поле типа General. В подобном случае имя этого поля указывается вместо имени файла.
    Объект Label создает метку для вывода поясняющего текста. Для придания метке нужного вида можно использовать следующие полезные свойства.

Control.Alignment [ = nValue]

    Если параметр nValue будет равен 0 (по умолчанию), то текст в метке выравнивается по левому краю, если 1 - по правому, если 2 - по центру.

Label.WordWrap [ = lExpression]

    Позволяет регулировать процесс изменения текста, заполняющего метку при изменении ее размера. По умолчанию параметр lExpression равен .F. и текст в метке не переносится между строками, при этом горизонтальный размер метки изменяется так, чтобы вместить текст по длине, а вертикальный остается без изменения, чтобы вместить имеющееся число строк текста с учетом размера шрифта. Если параметр lExpression равен .T., то текст может переноситься между строками с изменением вертикального размера метки в зависимости от длины текста и размера шрифта. При этом свойство AutoSize игнорируется.

Object.BorderStyle [ = nStyle]

    Это свойство определяет вид рамки для метки. По умолчанию параметр nStyle равен 0 и рамка не изображается. Если параметр nStyle равен 1, то метку будет окаймлять одинарная линия.
    Очень полезное свойство AutoSize позволяет не отслеживать размер помещаемого в элемент управления текста, особенно если текст изменяется во время работы программы.
    Объект Line создает элемент управления в виде линии, а Shape - в виде прямоугольника, окружности или овала. Требуемая форма последнего объекта в Visual FoxPro определяется свойством

Shape.Curvature [ = nCurve]

    По умолчанию параметр nCurve равен 0 и рисуется прямоугольник. Если значение параметра nCurve находится в диапазоне от 1 до 98, то будет рисоваться прямоугольник со все более скругленными углами, если 99 - круг или эллипс.
    В Visual Basic форма объекта определяется другим свойством и более жестко

Object.Shape [ = Value]

    Параметр может принимать одно из следующих значений:

  • 0 - прямоугольник (по умолчанию);
  • 1 - квадрат;
  • 2 - овал;
  • 3 - окружность;
  • 4 - прямоугольник со скругленными углами;
  • 5 - квадрат со скругленными углами.

    В Visual Basic объекты Line и Shape выполняют чисто оформительские функции, так как не реагируют на события. Аналогом объекта Shape, как элемента управления, в Visual Basic является Frame, который графически представляется прямоугольником с заголовком на верхней стороне и имеет необходимый набор событий.

Объекты-контейнеры

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

Object.ControlBox [ = lExpression]

    Определяет, появляется ли системное меню в верхнем левом углу формы во время ее выполнения. Если параметр lExpression принимает значение .T. (по умолчанию), то системное меню отображается, если .F., то нет.

Object.MaxButton [ = lExpression]

    Определяет, имеет ли форма кнопку Maximize (увеличение размера окна до максимального размера). Если параметр lExpression принимает значение .T. (по умолчанию), то форма имеет кнопку Maximize; если .F., то нет. Максимальное открытие окна Form во время выполнения программы вызывает событие Resize.

Object.MinButton [ = lExpression]

    Определяет, имеет ли форма кнопку Minimize (уменьшение размера окна до пиктограммы). Если параметр lExpression равен .T. (по умолчанию), то форма имеет кнопку Minimize; если .F., то нет. Уменьшение формы до пиктограммы во время выполнения программы генерирует событие Resize.

Object.Icon [ = cFileName]

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

Object.KeyPreview [ = lExpression]

    Определяет, прерывает ли событие KeyPress в форме событие KeyPress в элементе управления. Если параметр lExpression принимает значение .T., то сначала событие KeyPress получает форма, а затем активный элемент управления; если .F. (по умолчанию), то событие KeyPress получает активный элемент управления, а форма не получает.
    Вы можете использовать это свойство, чтобы создать для формы процедуру управления с помощью клавиатуры. Например, когда прикладная программа использует функциональные клавиши, вы можете обрабатывать нажатия клавиши на уровне формы скорее, чем для каждого элемента управления.
    Объект FormSet создает набор форм, что позволяет легко координировать работу сразу с несколькими формами. Этот объект есть только в Visual FoxPro, в Visual Basic ему в соответствие можно поставить коллекцию Forms. Набор форм обеспечивает следующие возможности:

  • Одновременное выполнение какого-либо действия сразу для нескольких форм.
  • Свободное управление расположением форм на экране для достижения максимального удобства в работе с ними.
  • Создание одного объекта DataEnvironment для всех форм в наборе и обеспечение тем самым синхронизации в перемещении данных.

    В то же время следует заметить, что наличие в Visual FoxPro такого объекта, как страничный блок (PageFrame), позволяет вместить практически неограниченный объем данных в одну форму.
    Для набора форм можно использовать множество свойств, событий и методов, доступных для отдельной формы. Некоторые свойства для набора форм особенно важны. Так, в Visual FoxPro для набора форм существует свойство

Object.WindowType [ = nType]

    Определяет поведение форм в наборе форм, если она запущена командой DO FORM.
    Для FormSet доступны следующие значения параметра Type:

nTypeОписание
0Независимо от режима.
1Модально. Никакие объекты других форм не могут стать активными, и меню не доступно. Все формы в FormSet активны.
2Чтение. Объект FormSet ведет себя, как будто он был активизирован командой READ. Выполнение останавливается на методе Show или команде DO FORM. Когда форма дезактивирована, выполнение программы продолжается. Включено для совместимости снизу вверх.
3 Модальное чтение. FormSet ведет себя, как будто он был активизирован командой READ MODAL. Выполнение программы останавливается на методе Show или команде DO FORM. Любые объекты формы в FormSet и объектах формы, указанных в свойстве WindowList, доступны, но объекты других форм и меню не доступны. Включено для совместимости снизу вверх.

    В Visual FoxPro в набор стандартных объектов входят и объекты для создания многостраничных форм.
    Объект Page создает страницу в страничном блоке для размещения блока данных. Страница объединяет информацию, одновременно видимую на экране пользователем. Перелистывая страницы, пользователь может работать с большим объемом данных без необходимости перехода в другие окна или формы.
    Страница как объект может входить только в страничный блок (PageFrame). В свою очередь, страница является объектом-контейнером и для определения количества включенных в нее элементов управления можно использовать свойство ControlCount. Для ссылки на отдельный элемент управления по его номеру и задания для него определенных значений свойств используется свойство Controls.

Object.KeyPreview [ = lExpression]

    Определяет, будет ли событие KeyPress в элементе управления прервано событием KeyPress в форме. Если параметр lExpression принимает значение .T., то сначала событие KeyPress получает форма, а затем активный элемент управления; если .F. (по умолчанию), то событие KeyPress получает активный элемент управления, а форма не получает.
    Вы можете использовать это свойство, чтобы создать для страницы в форме процедуру управления с помощью клавиатуры. Например, когда прикладная программа использует функциональные клавиши, вы можете обрабатывать нажатия клавиши на уровне формы скорее, чем для каждого элемента управления.

Page.PageOrder [ = nOrder]

    Определяет относительный номер страницы в страничном блоке, что будет влиять на порядок их расположения.
    Объект PageFrame создает страничный блок из набора страниц. Страничный блок позволяет компактно расположить большие объемы данных для работы с ними пользователя за счет размещения их на отдельных страницах, которые могут перелистываться. Узнать номер активной в данный момент страницы можно с помощью свойства ActivePage.
    Объект ToolBar создает в Visual FoxPro панель инструментов, которая может облегчить пользователю выполнение часто повторяющихся действий. На панели инструментов мы можем размещать любые элементы управления. Это позволяет создавать универсальный набор элементов управления для использования с однотипными формами, например справочниками, что сокращает время разработки программы и облегчает обучение пользователей.
    Панель инструментов имеет несколько специфических свойств.

Object.Movable [ = lExpression]

    Определяет, может ли панель инструментов перемещаться пользователем во время выполнения программы. Если параметр lExpression принимает значение .T. (по умолчанию), то панель инструментов может перемещаться. Если .F., то объект не может быть перемещен пользователем.

Object.Sizable = lExpression

    Определяет возможность изменения размеров панели инструментов. По умолчанию параметр lExpression равен .T., и размеры панели инструментов могут быть изменены пользователем. Если параметр lExpression будет равен .F., то сделать этого будет нельзя.

ToolBar.Docked [=lExpression]

    Возвращает логическое значение, с помощью которого можно определить, встроена панель инструментов в рамку окна Visual FoxPro (.T.) или нет (.F.). Если используется параметр lExpression, то свойство возвращает результат сравнения возвращаемого значения и параметра lExpression.
    Если вы хотите поэкспериментировать со свойствами панели инструментов, задавая команды из окна Command, то вам поможет следующий образец, который обеспечивает доступ к панели инструментов, добавленной к форме при ее проектировании.

?_SCREEN.ActiveForm.Parent.Office_toolbar1.Docked

    При добавлении панели инструментов к форме создается набор форм, поэтому для ссылки на него, как на объект более высокого уровня, используется указатель Parent.

nPosition = ToolBar.DockPosition

    Определяет положение панели инструментов в окне Visual FoxPro. Параметр nPosition может принимать следующие значения: -1 - панель инструментов не может быть встроена; 0 - встроена в верхнюю рамку; 1 - в левую; 2 - в правую; 3 - в нижнюю.
    На панели инструментов можно размещать специальный объект - Separator, который помещает пробел между элементами управления. Это позволяет визуально создавать на панели инструментов группы элементов управления, так как по умолчанию размещаемые на панели инструментов элементы управления следуют вплотную друг за другом.
    Универсальными объектами в Visual FoxPro для создания компонентных элементов управления, включающих несколько отдельных объектов, являются объекты Control и Container. Об отличиях между этими объектами мы уже рассказывали.

Невизуальные объекты

    Объект Custom создает единственный в Visual FoxPro невизуальный объект, исключая уже упоминавшиеся объекты Container и Control, которые выполняют специфические функции объединения других элементов управления.
    Этот объект удобно использовать для создания и последующего запуска стандартных, часто используемых процедур, при создании которых не требуется визуализация объекта.
    В качестве примера использования объекта Custom рассмотрим следующий пример, в котором мы создадим пользовательский класс, зашифровывающий пароль. Пароль может храниться в таблице с данными о доступе пользователей к элементам системы в зашифрованном виде. После ввода пароля пользователем хранимый пароль расшифровывается и сравнивается с введенным. В приводимой программе создается форма, в которой в поле, расположенное в левом верхнем углу, вводится пароль. Вводимые символы скрыты, и их число отображается звездочками. Нажмите кнопку "Зашифровать", и вы увидите в нижних полях формы слева зашифрованное значение, а справа введенное. Успехов в шифровании!

*** Пример использования объекта Custom для шифрования пароля

frmPwdForm = CREATEOBJECT("PwdForm") && Создаем форму.
frmPwdForm.Visible = .T.
READ EVENTS
* Описываем класс формы
DEFINE CLASS PwdForm AS FORM
     Caption = "Шифрование пароля"
* Добавляем объект в форму для формирования пароля
     ADD OBJECT CustPassword AS Pass_Word
     Height = 130
    Width = 350
     Autocenter = .T.
* Добавляем текстовое поле для ввода пароля
     ADD OBJECT txtText1 AS TextBox WITH ;
Height = 25, ;
Left = 25, ;
Top = 20, ;
Width = 125, ;
PasswordChar = "*", ;
Name = "txtText1"
* Добавляем текстовое поле для вывода
* зашифрованного пароля
     ADD OBJECT txtText2 AS TextBox WITH ;
Height = 25, ;
Left = 25, ;
Top = 72, ;
Width = 125, ;
Readonly = .T., ;
Name = "txtText2"
* Добавляем в форму кнопку для вызова процедуры
* шифрования,
* которая содержится в cmdCommand1.Click
ADD OBJECT cmdCommand1 AS CommandButton WITH ;
Top = 20, ;
Left = 200, ;
Height = 29, ;
Width = 125, ;
Caption = "Зашифровать", ;
Name = "cmdCommand1"
* Добавляем в форму текстовое поле для вывода введенного
* пароля
     ADD OBJECT txtText3 AS TextBox WITH ;
ControlSource = ; "THISFORM.custPassword.cUnencrypted", ;
Height = 25, ;
Left = 200, ;
ReadOnly = .T., ;
Top = 72, ;
Width = 125, ;
Name = "Text3"
* Процедура, выполняемая после набора пароля
     PROCEDURE txtText1.LostFocus
THISFORM.custPassword.Encrypt_It(TRIM(THIS.Value))
THISFORM.txtText2.Value =; {dd> THISFORM.custPassword.cEncrypted
THISFORM.cmdCommand1.SetFocus
     ENDPROC
* Процедура, выполняемая при нажатии на кнопку
* "Зашифровать"
     PROCEDURE cmdCommand1.Click
THISFORM.custPassword.Decrypt_It(THISFORM.custPassword.; cEncrypted)
THISFORM.Refresh
THISFORM.txtText1.SetFocus
ENDPROC
* Процедура, выполняемая при выходе из формы
     PROCEDURE DESTROY
CLEAR EVENTS
     ENDPROC
ENDDEFINE
* Описываем класс объекта Custom
DEFINE CLASS Pass_Word AS Custom
     Height = 17
     Width = 100
     Name = "Password"
     * Добавляем для создаваемого объекта свои свойства
     cUnencrypted = ""
     cEncrypted = ""
* Процедура выполнения шифрования пароля
     PROCEDURE Encrypt_It
PARAMETERS cPassword
cEncrypted_password = " "
* Запускаем цикл по количеству введенных в пароле
* символов
FOR i = 1 TO LEN(cPassword)
     cLetter = SUBSTR(cPassword, i, 1)
     cEncrypted_password = cEncrypted_password + ;
     CHR((ASC(cLetter)*2)+5) && Заменяем
          && введенный символ
NEXT i
THIS.cEncrypted = cEncrypted_password
     ENDPROC
* Процедура расшифровки пароля
     PROCEDURE Decrypt_It
PARAMETERS cPassword
cUnencrypted_password = " "
FOR i = 1 TO LEN(cPassword)
     cLetter = SUBSTR(cPassword, i, 1)
     cUnencrypted_password = cUnencrypted_password + ;
     CHR((ASC(cLetter)-5)/2)
NEXT i
THIS.cUnencrypted = cUnencrypted_password
     ENDPROC
ENDDEFINE

    В Visual Basic вместо одного универсального невизуального объекта используется достаточно большое число специализированных невизуальных объектов. Опишем те, которые наиболее часто используются при построении пользовательского приложения.
    Объект App определяет или задает такие параметры, как заголовок приложения, путь к исполняемому файлу и его имя, имя файла контекстной справки и т. д. Этот объект имеет только свойства и не имеет ни событий, ни методов.
    Объект ClassModule содержит свойства, которые управляют поведением класса так же, как программа может описывать свойства и методы класса. В приложении вы можете использовать этот объект как контейнер для программного кода, который описывает свойства и методы созданного вами класса. Объект ClassModule похож по своему поведению на форму, но без визуального интерфейса.
    Объект Clipboard обеспечивает доступ к системному буферу обмена. Этот объект используется для работы с текстом и графикой, содержащейся в буфере обмена, и с его помощью можно обеспечить пользователю возможность копировать, вырезать и вставлять данные в приложении.
    Объект Collection - коллекция - представляет собой набор объектов, к которому можно обращаться как к единому целому. Обычно в колекцию помещают группу однотипных объектов (членов коллекции), а затем обращаются к ним по номеру, который объект занимает в коллекции. Но в принципе, в коллекции могут быть объединены и объекты разного типа. Размещение объектов в коллекции позволяет выполнять необходимые действия одновременно над всеми объектами, обращаясь только к одному объекту Collection. Объект создается точно так же, как и другие объекты, например:/p>

Dim oCollect1 As New Collection

    Объекты в коллекцию могут быть добавлены с помощью метода Add и исключены из нее с помощью метода Remove.

Объекты OLE

    Элементы управления OLE - этот дополнительный инструмент, который позволяет расширить функциональность разрабатываемых прикладных программ. Возможность использования элементов управления OLE в приложении появилась за счет поддержки технологии OLE 2.0 (Object Linking and Embending) - стандартного интерфейса, разработанного Microsoft, для одновременного использования приложениями объектов в ОС Windows. Что дает эта технология разработчику прикладного программного обеспечения?
    При разработке прикладной программы мы можем использовать объекты из других приложений. Например, разместить в форме текстовый документ Word for Windows. Текстовый документ станет OLE-объектом. Тогда текстовый процессор примет статус сервера OLE, а прикладная программа - клиента OLE. При обращении к объекту OLE все необходимые функции предоставляет сервер OLE. Он продолжает работать до тех пор, пока в других приложениях останется хотя бы один его объект. В Windows 95 появился новый тип серверов OLE - внутренний сервер OLE. Он предоставляет запрашивающим приложениям тот же интерфейс, что и внешний сервер OLE, однако отличается от него намного более высоким быстродействием, так как не требует отдельного пространства памяти для второго приложения. Другая возможность технологии OLE 2.0 заключается в использовании настраиваемых элементов управления ActiveX (OLE Custom Controls - OCX). Элементы управления ActiveX - это стандартный формат объектов OLE, допустимый для приложений, написанных и на других языках программирования. Их использование позволяет обеспечить пользовательскому приложению практически любую функциональность, реализовать которую встроенными средствами было бы невозможно или затруднительно.
    Элемент управления OLE Bound создает встроенный OLE-объект, который связан с полем типа General таблицы Visual FoxPro. Встроенный OLE-объект не имеет собственного набора событий. Чаще всего в качестве встроенного OLE-объекта используется изображение, звук или видеоролик.
    Элемент управления OLE Container позволяет включить элемент управления OLE в пользовательское приложение Visual FoxPro. Элемент управления OLE обычно может быть использован в виде файла с расширением OCX. Кроме того, в виде подобного элемента управления может использоваться файл документа Word for Windows или таблица Excel.
    В Visual Basic функциональность обоих этих элементов управления обеспечивается одним объектом OLE.
    Для работы с OLE-объектами можно использовать следующие свойства.

Control.AutoActivate [ = nValue]

    Определяет, как могут быть активизированы элементы управления OLE. Если параметр nValue равен 0, то элемент управления не будет автоматически активизирован при выборе пользователем. Вы можете активизировать элемент управления программно, используя метод DoVerb. Если nValue = 1{/i>, то прикладная программа, являющаяся для объекта сервером, будет активизирована после выбора объекта пользователем. Если nValue = 2{/i> (по умолчанию), то объект OLE будет активизирован двойным щелчком мыши или нажатием клавиши Enter на этом объекте, если объект выбран. Если nValue = 2{/i>, то объект OLE будет активизирован двойным щелчком мыши на элементе управления или выбором этого объекта (автоматическая активизация).

Control.HostName [ = cExpression]

    Для некоторых приложений позволяет задать имя, которое будет использоваться в качестве заголовка окна при редактировании OLE-объекта.
    Пользователи профессиональной версии Visual FoxPro получают набор дополнительных элементов управления ActiveX вместе с пакетом. Набор состоит из четырех файлов - MSCOMM32.OCX, MSMAPI32.OCX, MSOUTL32.OCX и PICCLIP32.OCX, - которые при инсталяции Visual FoxPro записываются в директорий SYSTEM операционной системы Windows. Эти элементы управления наряду с другими входят и в профессиональную версию Visual Basic. Что же таится в этих файлах?
    MSCOMM32.OCX представляет элементы управления для передачи данных в приложении по последовательному интерфейсу (Communications control). Они обеспечивают следующие пути для управления передачей данных:

  • Событийно управляемая передача данных позволяет с помощью события OnComm отслеживать начало передачи данных на компьютер (Carrier Detect) и необходимость передачи данных с компьютера (Request To Send). Событие OnComm также отслеживает ошибки соединения.
  • Определять необходимость передачи данных можно и с помощью проверки значения свойства CommEvent после выполнения программой определенных действий, например, после получения сигнала OK от модема.

    Для каждого последовательного порта, который используется для передачи данных, необходимо использовать отдельный элемент управления.
    MSMAPI32.OCX - представляет набор элементов для создания в пользовательском приложении возможности передачи почтовых сообщений (Microsoft MAPI Controls). В файле содержатся два элемента управления:

  • Элемент управления сеансом связи (MAPI Session Control) позволяет установить связь с требуемым получателем почтового сообщения.
  • Элемент управления сообщениями (MAPI Messages Control) позволяет пользователю выполнять различные почтовые функции.

    Эти элементы управления невидимы во время работы программы, к тому же они не имеют собственных событий. Для их использования необходимо применять соответствующие методы.
    MSOUTL32.OCX - представляет элемент управления для создания иерархического списка (Outline Control), в котором каждый пункт может иметь подчиненный пункт, выводимый с отступом. Пользователь может сворачивать список, делая невидимыми подчиненные пункты, или, наоборот, раскрывать иерархию интересующих его пунктов. Такой тип списка используется в Windows 95 для вывода списка файлов и директорий, а в Visual FoxPro для отображения элементов, входящих в проект.
    PICCLP32.OCX - представляет элемент управления для вывода растровых изображений (Picture Clip Controls), который позволяет выбрать область в исходном изображении и затем вывести ее в форме. Этот элемент управления не видим в процессе работы программы. Он позволяет заменить множество используемых в программе файлов BMP или ICO одним файлом, содержащим все необходимые изображения. С помощью элемента управления для вывода изображений можно выбрать нужную область и вывести требуемую иконку или изображение, например, для каждой кнопки на панели инструментов. Это позволяет значительно эффективнее использовать память компьютера.
    При установке СУБД Access 7.0 вы получаете в свое распоряжение один дополнительный элемент управления - календарь (Calendar Control).
    Этот элемент управления находится в файле MSACAL70.OCX и может быть встроен в форму приложения для быстрого поиска даты. Календарь также поддерживает события, с помощью которых ваше приложение может автоматически выполнять какие-либо действия, связанные с той или иной датой.
    Значительное количество дополнительных элементов управления поставляется вместе с Visual Basic, особенно с профессиональной версией этого средства разработки. Дадим им краткую характеристику.
    В файле COMCTL32.OCX содержатся несколько элементов управления Windows 95.
    Элемент управления ListView позволяет отображать списки, используя один из четырех способов:

  • в виде значков (иконок);
  • используя уменьшенные версии значков;
  • в виде списка;
  • в виде таблицы с дополнительным текстом для пояснения к каждому пункту.

    Вы можете выстраивать пункты в колонках, используя заголовки и сочетая значки с текстом, а также устанавливать сортировку пунктов.
    Элемент управления ImageList предназначен для хранения коллекции объектов ListImage, каждый из которых может быть идентифицирован по его номеру в списке или по ключу. Элемент управления ImageList не предназначен для самостоятельного использования, а может быть включен в любой другой элемент управления как хранилище изображений.
    Элемент управления TreeView позволяет отображать иерархические списки специальных объектов Node, каждый из которых содержит метку и, возможно, изображение. Этот элемент управления можно эффектно использовать для отображения содержания каких-либо документов, списков файлов и папок и т. д. По своему назначению он аналогичен объекту Outline Control, но предоставляет более широкие возможности для программного управления сворачиванием и раскрытием иерархии пунктов, перемещением и выбором пунктов в списке, в том числе с использованием поиска первых символов по нажатии клавиш. Список выводится в окне, которое имеет полосы прокрутки. Элемент управления TreeView использует элемент управления ImageList для хранения значков, которые используются при выводе каждого объекта Node (пункта в списке).
    Элемент управления ProgressBar позволяет визуально контролировать длительность выполнения какого-то действия и представляет собой прямоугольник с движущейся в зависимости от скорости выполнения процесса полосой. В то же время этот объект оценивает только относительную длительность процесса без оценки каких-либо численных характеристик.
    Элемент управления StatusBar - строка состояния - позволяет создать окно, обычно располагающееся внизу формы, в котором могут отображаться различные данные о текущем состоянии приложения. Строка состояния может быть разделена максимум на 16 объектов Panel, которые составляют коллекцию Panels. Каждый объект Panel может содержать определенный текст и (или) изображение. Дополнительно вы можете использовать одно из семи значений свойства Style для автоматического отображения таких данных, как дата, время, состояние триггерных клавиш на клавиатуре и т. п.
    Элемент управления Slider - движок - это окно, содержащее движок со шкалой. Пользователь может перемещать движок, перетаскивая его, щелкая мышкой с разных сторон движка, или использовать клавиатуру. Основное назначение элемента управления Slider - выбор дискретных значений в каком-либо диапазоне. Вы можете располагать этот элемент управления как горизонтально, так и вертикально.
    Элемент управления TabStrip предназначен для создания многостраничных форм с вкладками. По принципу действия он аналогичен объекту PageFrame в Visual FoxPro, но не является контейнером, то есть не может включать другие объекты. Доступ к страницам основан на том, что TabStrip содержит несколько объектов Tab из коллекции Tabs. Каждый объект Tab имеет свойства, ассоциированные с его текущим состоянием и внешним видом. Например, вы можете включить в TabStrip элемент управления ImageList и затем использовать изображения на конкретной вкладке, используя объект Tab. Заголовки вкладок TabStrip могут включать помимо текста также изображения.
    Элемент управления Toolbar - панель инструметов - содержит коллекцию объектов Button, используемых для создания набора элементов управления в вашем приложении. Наличие панели инструментов является практически стандартным требованием к приложению Windows и обеспечивает пользователю быстрый доступ к часто выполняемым функциям. Изображения для кнопок, размещаемых на панели инструментов, хранятся в объекте ImageList. Элемент управления Toolbar имеет богатый набор свойств, методов и событий для эффективного управления панелью инструментов во время работы программы. Объекты Button поддерживают различные стили, допускающие создание группы кнопок, использование которых должно быть взаимоувязано, а стиль PlaceHolder допускает использование любых других элементов управления типа раскрывающегося списка.
    Следующий элемент управления Windows 95 находится в файле RICHTX32.OCX и обеспечивает возможность создания окна для работы с форматированным текстом - RichTextBox. В отличие от элемента управления TextBox, объект RichTextBox имеет ряд свойств, которые позволяют форматировать выделенный в этом объекте текст: изменять начертание шрифта, его цвет и использовать надстрочные и подстрочные индексы. Пользователь может также устанавливать вид выравнивания текста. Редактируемый текст может сохраняться как в RTF, так и в ASCII формате. За счет использования методов LoadFile и SaveFile элемент управления RichTextBox позволяет непосредственно считывать и записывать данные в файл. Поддерживается также открытие файла путем его перетаскивания, например из Windows 95 Explorer. Можно даже перетащить фрагмент текста из Microsoft Word и продолжить работу с ним в форме вашего приложения, включающей объект RichTextBox. Метод SelPrint позволяет распечатать весь текст или фрагмент данных на принтере.
    В связи с тем, что объект RichTextBox является связанным объектом, вы можете ассоциировать его с элементом управления Data для отображения данных из полей примечаний. Элемент управления RichTextBox поддерживает большинство свойств, событий и методов, используемых стандартным элементом управления TextBox, но не имеет ограничения на размер выводимых с его помощью данных.
    В файлах COMDLG16.OCX и COMDLG32.OCX содержатся 16- и 32-разрядные версии элемента управления CommonDialog Control, который обеспечивает набор стандартных диалоговых окон для таких операций, как открытие, сохранение и печать файлов, выбор цвета и шрифта. Этот элемент управления обеспечивает интерфейс между пользовательским приложением и функциями, размещенными в динамической библиотеке Microsoft Windows COMMDLG.DLL.
    Вы можете легко включить в свою форму необходимые стандартные диалоги путем простого добавления в нее объекта CommonDialog и задания для него требуемых свойств. После включения в форму в режиме проектирования этот элемент управления изображается в виде значка. Соответствующее диалоговое окно появляется на экране путем выполнения соответствующего метода.
    Следующие объекты ActiveX позволяют эффективно организовать работу с данными.
    Файл DBGRID32.OCX содержит элемент управления DBGrid, который позволяет создать таблицу для просмотра и редактирования данных объекта Recordset. Возможность привязки объекта DBGrid к элементу управления Data позволяет автоматически заполнить заголовки колонок на основании данных объекта Recordset. Элемент управления DBGrid содержит коллекцию Columns для формирования набора колонок. В каждой ячейке DBGrid может отображаться как текст, так и изображение, исключая связанные или внедренные объекты. Если текст слишком большой, чтобы разместиться по длине в ячейке, то он будет автоматически перенесен на следующую строку в той же ячейке. Объект DBGrid обеспечивает возможность программной ссылки на нужную ячейку. Свойства Text и Value объекта Column содержат значение текущей ячейки. Каждая колонка поддерживает свой шрифт, тип рамки, цвет и другие атрибуты, независимо от их установки в других колонках.
    В файлах GRID32.OCX и GRID16.OCX содержатся соотвественно 32- и 16- разрядные версии еще одного объекта Grid - Microsoft Grid Control. По своей функциональности он в основном аналогичен вышеописанному объекту - DBGrid.
    Файл DBLIST32.OCX включает два элемента управления для вывода данных в виде списков - DBList и DBCombo. Эти элементы управления автоматически заполняют список из полей одного элемента управления Data и могут передавать данные из выбранного поля во второй элемент управления Data, например, для редактирования. Элементы управления DBList и DBCombo отличаются от стандартных элементов управления ListBox и ComboBox тем, что не требуют использования метода AddItem для формирования списка, а также поддерживают автоматический поиск без необходимости написания дополнительного кода.
    В файлах MSMASK16.OCX и MSMASK32.OCX содержится элемент управления для ограничения вводимых данных по шаблону или их форматированного вывода на экран - Masked Edit Control. Этот элемент управления по использованию аналогичен стандартному элементу управления TextBox. Если вы опишете шаблон ввода, используя свойство Mask, каждое положение символа будет контролироваться по допустимому типу; станет также возможным использование заранее определенных символов, например, заключение междугородного телефонного кода в скобки: (812). При вводе данных курсор автоматически минует отображаемые символы шаблона, такие, например, как скобки в предыдущем примере. Попытка ввода символов, которые не будут соответствовать шаблону, сгенерирует событие ValidationError. Например, если задан шаблон "?###" и текущее отображаемое значение "A12.", то попытка ввести символ "B" перед "A" вызовет смещение символа "A" вправо, а так как в этом случае будет нарушен тип допустимого символа (число), то будет сгененирировано событие ValidationError.
    В файлах SPIN16.OCX и SPIN32.OCX вы можете найти элемент управления SpinButton - счетчик - для ввода дискретных значений. Этот элемент управления по своим возможностям аналогичен рассмотренному ранее стандартному объекту Visual FoxPro - Spinner.
    Альтернативой объекту TabStrip являются 16- и 32-разрядные версии элемента управления SSTab, который находится в файлах TABCTL32.OCX и TABCTL16.OCX. Этот элемент управления обеспечивает очень легкий путь создания многостраничных диалоговых окон в одной форме. Объект SSTab содержит страницы, каждая из которых может являться, в свою очередь, объектом-контейнером для любых других элементов управления. Используя соответствующие свойства, вы можете:

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

    Во время работы программы пользователь может перемещаться между страницами с помощью клавиш Ctrl+Tab.
    Разнообразить пользовательский интерфейс вам поможет использование следующих объектов ActiveX.
    В файлах GAUGE16.OCX и GAUGE32.OCX содержатся 16- и 32-разрядные версии элемента управления Gauge, широко известного среди программистов под жаргонным названием "термометр". Это шкальный индикатор, который может использоваться для визуального контроля длительности выполнения какого-то процесса аналогично уже описанному элементу управления Progress-Bar. От последнего Gauge отличается более точными показаниями, которые отслеживаются непрерывно.
    С версией Visual Basic масштаба предприятия поставляется объект для доступа к внешним данным - Microsoft Remote Data Control (MSRDC), который обеспечивает доступ к внешнему источнику данных с помощью технологии ODBC. Этот элемент управления обеспечивает интерфейс между объектами для доступа к внешним данным - Remote Data Objects (RDO) и элементами управления для отображения данных, расположенных в экранной форме. Используя элемент управления MSRDC вы можете:

  • установить соединение с источником данных, используя свойства MSRDC;
  • создать элемент управления для перемещения между записями;
  • передавать данные из текущей строки в соответствующие элементы управления;
  • получать и отображать данные о текущем положении указателя записи;
  • обновлять данные в источнике после их изменения пользователем.

    Подробнее об использовании объектов для доступа к внешним данным вы прочитаете в главе 8.
    В Visual FoxPro любой установленный на вашем компьютере объект ActiveX вы можете включить в форму, выбрав объект OLE Container Control, а затем в автоматически появляющемся диалоговом Insert Object окне выбрать опцию Insert Control. Из появляющегося списка можно выбрать соответствующий элемент управления, как это видно на рис. 5.6.


Рис. 5.6.

    В Visual Basic подобную процедуру вы можете выполнить в любой момент работы над приложением. В меню Tools выберите команду Custom Controls, выберите из появляющегося списка нужный объект (рис. 5.7). Соответствующий объект вы затем можете поместить в проектируюмую форму, выбрав его значок на панели инструментов ToolBox. На рис. 5.8 показана эта панель инструментов с описанными выше элементами управления.


Рис. 5.7.

Рис. 5.8. Визуальные объекты и элементы управления в Visual Basic с подключенными компонентами ActiveX

    Элементы управления OLE самого различного назначения в виде файлов OCX можно создать с помощью Control Development Kit в Microsoft Visual C++ или с помощью программного обеспечения других фирм. В этом случае вам придется вручную зарегистрировать те OLE-объекты, которые вы захотите использовать, с помощью программы REGSVR32.EXE. Эта программа находится в директории SAMPLES\OLE Visual FoxPro. При запуске программы REGSVR32 имя файла OCX надо указать в качестве параметра.

5.3. Управление событиями

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

  • Объекты-контейнеры не выполняют код для событий, если действия для этих событий предусмотрены во включенном в него объекте.
  • Если для данного события реакция элемента управления не описана, приложение ищет код для данного события в более высоком уровне классовой иерархии. Как только такой код будет найден, он будет выполнен и дальнейший поиск прекратится. В этом случае при разработке приложения в Visual FoxPro не забудьте про оператор "::", с помощью которого можно выполнить код более высокого уровня.

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

PROCEDURE Object.Init
[LPARAMETERS Param1, Param2,...]

    Это первое событие в последовательности событий при создании объекта. Обычно событие Init используется для получения параметров из вызывающей процедуры Param1, Param2, и выполнения установочных действий типа считывания нужных данных и т. п.
    Сказанное выше правильно для всех рассматриваемых в книге средств разработки, но нет полной радости у программиста. В Visual FoxPro упомянутое выше событие называется Init, а в Visual Basic примерно аналогичное событие называется Initialize. При этом процедура для описания действий, которые должны произойти при наступлении события, в Visual Basic имеет следующую структуру:

Private Sub ObjectName_EventName(<<Параметры>>)
<<Описание переменных и констант>>
<<Операторы>>
End Sub

    Имя события указывается после имени объекта, которому оно соответствует, и отделяется знаком подчеркивания. Тогда для события заголовок процедуры должен быть написан так:

Private Sub Object_Initialize()

    В Visual Basic это событие может относиться только к форме и объекту ClassModule.
    Событие Init всегда выполняется сначала для объекта, включенного в объект-контейнер, и лишь затем для самого объекта-контейнера. Если событие Init возвращает значение .F., то объект не будет создан. Например, если мы создадим форму, в которой собираемся работать с данными из какой-либо таблицы, а файла таблицы нет на диске, то следующий пример, написанный на Visual FoxPro, показывает, как в этом случае можно избежать загрузки формы.

oFrm = CREATEOBJECT("frmLook") && Создаем объект формы
IF type("oFrm") != "O"
     RETURN
ENDIF
oFrm.Show && Выводим ее на экран
READ EVENTS && Включаем состояние ожидания
* Описываем класс формы
DEFINE CLASS frmLook AS Form
     ScaleMode = 3 && Координаты в пикселях
     Width = 320 && Ширина
     Heigth = 200 && Высота
     Closable = .F. && Закрытие только кнопкой
* Добавляем объект Grid, с помощью которого будем выводить данные
ADD OBJECT grdCustomer AS Grid WITH ;
     RecordSource = "Customer", ;
     RecordSourceType = 1
* Добавляем кнопку для выхода из формы
ADD OBJECT cmdExit AS CommandButton WITH ;
     Caption = "Выход", ;
     Top = 220, ;
     Left = 100
* Описываем действия при создании объекта Grid - проверка файла
PROCEDURE grdCustomer.Init
     IF !FILE("CUSTOMER.DBF")
     =MESSAGEBOX("Файл данных не найден!")
     RETURN .F.
     ELSE
IF USED("CUSTOMER")
     SELECT CUSTOMER
ELSE
     USE CUSTOMER IN 0
ENDIF
     ENDIF
ENDPROC
* Описываем действия при щелчке мышкой на кнопке
PROCEDURE cmdExit.Click
     CLEAR EVENT && Отменяем состояние ожидания
ENDPROC
ENDDEFINE

    Последним событием при существовании объекта является событие Destroy. Это событие обычно используется для выполнения завершающих действий при работе с объектом, например, запись измененых данных и т. п.
    Аналогично событию Init и его примерному аналогу в Visual Basic - Initialize, для события Destroy в Visual Basic существует примерный аналог - событие Terminate.
    Одним из наиболее часто используемых событий для управления работой программы является событие Click. Это событие происходит, когда пользователь:

  • Щелкает левой кнопкой мыши на элементах управления CheckBox, CommandButton или Optionbutton, на пустом месте формы или в области ввода данных элемента управления Spinner.
  • Выбирает пункт в списке элементов управления Combobox или ListBox.
  • Нажимает клавишу Space (Пробел), когда активен элемент управления CheckBox, CommandButton или OptionButton.
  • Нажимает клавишу Enter, когда один из элементов управления CommandButton имеет свойство Default, равное .T.
  • Нажимает "горячую клавишу", определенную для какого-либо элемента управления.

    Событие Click наступает также, когда выполняются следующие действия в программе:

  • Значение свойства Value элементов управления CommandButton или Optionbutton устанавливается в значение .T. или 1 для OptionButton.
  • Изменяется значение свойства Value элемента управления CheckBox.
  • Выполняется команда MOUSE.

    Событие DblClick происходит, когда пользователь дважды быстро нажимает и отпускает левую кнопку мыши на каком-либо объекте. Для объектов ComboBox и ListBox это событие происходит также при выборе какого-либо пункта из списка и нажатии при этом клавиши Enter. При привязке каких-либо действий к событию DblClick следует помнить, что пользователи не всегда могут четко выполнить данное действие и двойной щелчок может быть воспринят системой как два одинарных щелчка, выполненных с небольшим интервалом.
    При выборе объекта, то есть при установке на него курсора, для этого объекта выполняется событие GotFocus. Это же событие выполняется при использовании в программе метода SetFocus. Следует учесть, что стать активным объект может, только если его свойства Enabled и Visible равны .T..
    Когда пользователь выбирает другой объект в форме для дальнейшей работы, текущий объект деактивизируется и для него происходит событие LostFocus.
    Следующее событие происходит для каждого объекта, размещенного на странице формы (Page), когда эта страница активизируется или деактивизируется.

PROCEDURE Object.UIEnable
LPARAMETERS lEnabled

    Параметр lEnabled может иметь значение .T. или .F., что будет свидетельствовать о, соответственно, активизации или деактивизации страницы, на которой расположен объект. Таким образом, это событие позволяет предпринимать какие-либо действия с элементом управления, например, обновлять данные при переходе пользователя на новую страницу в форме.
    Во время редактирования данных при каждом изменении пользователем значения свойства Value элемента управления происходит событие InteractiveChange для редактируемого элемента. Если изменение значения произведено из программы, для элемента управления происходит событие ProgrammaticChange.
    В Visual Basic эти функции приходится выполнять одному событию - Change. Его синтаксис:

Private Sub Object_Change([Index As Integer])

    Параметр Index позволяет получить номер объекта, если он включен в массив элементов управления.
    Для элементов управления, предусматривающих ввод данных, при нажатии и отпускании клавиши клавиатуры происходит событие KeyPress. Его синтаксис в Visual FoxPro выглядит так:

PROCEDURE Object.KeyPress
LPARAMETERS nKeyCode, nShiftAltCtrl

    Параметр nKeyCode возвращает код нажатой клавиши, совпадающий с кодом, возвращаемым функцией INKEY(). Параметр nShiftAltCtrl возвращает признак нажатия дополнительной клавиши. Клавиша Shift имеет код 1, Ctrl - 2, Alt - 4. Таким образом, если этот параметр имеет значение 1 - при вводе удерживалась клавиша Shift, если 6 - удерживались клавиши Ctrl и Alt.
    В Visual Basic это событие имеет следующий синтаксис:

Private Sub Form_KeyPress(Keyascii As Integer)

    Параметр Keyascii возвращает числовой ASCII-код, который передается по ссылке. Следующий пример позволяет преобразовывать все вводимые в текстовое поле символы в верхний регистр:

Private Sub Text1_KeyPress (KeyAscii As Integer)
     Char = Chr(KeyAscii)
     KeyAscii = Asc(UCase(Char))
End Sub

    Помимо этого события в Visual Basic есть еще два события, которые позволяют отслеживать работу пользователя с клавиатурой. Это событие KeyDown - срабатывает при нажатии клавиши и KeyUp - при ее отпускании. Эти события могут обрабатываться совершенно аналогично событию KeyPress в Visual FoxPro, то есть с их помощью можно отслеживать нажатие и комбинаций клавиш.
    Для большинства элементов управления в Visual FoxPro перед их активизацией возможность перехода в этот элемент управления проверяется с помощью события When. Если это событие возвращает .T. (по умолчанию), то управление передается на этот элемент управления и возникает следующее событие GotFocus. Если событие When возвращает .F., то этот элемент управления не активизируется. Для объекта типа List событие When возникает всякий раз, когда пользователь перемещается между пунктами в списке.
    Перед тем как передать управление следующему объекту, для текущего элемента управления в Visual FoxPro выполняется событие Valid. Если это событие возвращает значение .T., то данный элемент управления деактивизируется. Если .F., то элемент управления остается активным. Таким образом, событие Valid можно использовать для проверки допустимости значения, выбранного для данного элемента управления.
    В связи с тем, что основным объектом пользовательского интерфейса является форма, уделим теперь внимание характерным для этого объекта событиям.
    Событие Activate происходит, когда пользователь активизирует ранее не активную форму (щелкает мышкой на форме или входящем в нее элементе управления) или когда вызывается метод Show.
    Событие Deactivate происходит, когда форма перестает быть активна, то есть управление передается другому объекту в том же приложении.
    Следует учитывать, что ни событие Activate, ни Deactivate не происходят при передаче управления в другое приложение. Событие Deactivate также не происходит при стирании формы из памяти.
    При создании формы (ее загрузки в память) перед событиями Activate и SetFocus происходит событие Load.
    При стирании формы из памяти происходит событие UnLoad.
    Событие Paint происходит, когда форма перерисовывается. Форма перерисовывается после перемещения или увеличения, а также, если было сдвинуто окно, ранее его закрывающее.
    Использование события Paint для некоторых задач может вызывать каскад последующих событий. Если у вас нет веских причин, избегайте использовать событие Paint в следующих случаях:

  • Перемещение или изменение размеров формы или элементов управления.
  • Изменение любых переменных, которые воздействуют на размер или вид, типа установки свойства BackColor.
  • Вызов метода Refresh.

    При программировании реакции пользовательского приложения на происходящие события очень важно знать последовательность их возникновения. Рассмотрим эти последовательности для основных объектов Visual FoxPro. В Visual Basic, как вы, наверное, уже заметили, событий, на которые может реагировать приложение, значительно меньше и поэтому последовательность их возникновения для отдельного объекта не имеет такого значения.
    Для набора форм и входящих в него отдельных форм (пусть для примера в набор входят две формы) будет выполняться следующая последовательность событий при его запуске:

FormSet.DataEnvironment.BeforeOpenTables (если свойство AutoOpenTables = .T.)
FormSet.Load
FormSet.Form1.Load
FormSet.Form2.Load
FormSet.DataEnvironment.<<Объекты Data Environment>>.Init
FormSet.DataEnvironment.Init
FormSet.Form1.<<Объекты в Form1>>.Init
FormSet.Form1.Init
FormSet.Form2.<<Объекты в Form2>>.Init
FormSet.Form2.Init
FormSet.Init
FormSet.Activate
FormSet.Form2.Activate
FormSet.Form2.Deactivate
FormSet.Activate
FormSet.Form1.Activate
FormSet.Form1.<<Первый элемент управления>>.When
FormSet.Form1.GotFocus
FormSet.Form1. <<Первый элемент управления>>.GotFocus

    При завершении работы с набором форм выполняется следующая последовательность событий:

FormSet.Activate
FormSet.Form2.Destroy
FormSet.Form2.<<Объекты в Form2>>.Destroy
FormSet.Form2.Unload
FormSet.Form1.Destroy
FormSet.Form1.<<Объекты в Form1>>.Destroy
FormSet.Form1.Unload
FormSet.Unload
FormSet.DataEnvironment.AfterCloseTables
FormSet.DataEnvironment.Destroy
FormSet.DataEnvironment.<<Объекты Data Environment>>.Destroy

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

Form.Grid.When
Form.GotFocus
Form.Grid.AfterRowColChange

    Последнее событие AfterRowColChange возвращает номер колонки, в которой находится курсор, то есть которая является активной. Это событие сопровождает и каждое перемещение пользователя по клеткам Grid, и таким образом, любой переход курсора в другую клетку сопровождается двумя событиями:

Form.Grid.BeforeRowColChange
Form.Grid.AfterRowColChange

    Событие BeforeRowColChange возвращает номер колонки, в которой находился курсор до перехода в новую клетку.
    Если пользователь пометил запись для удаления или в программе выполнилась команда DELETE, для объекта Grid генерируется событие Deleted, которое возвращает номер помеченной для удаления записи.
    При прокрутке данных с помощью линейки прокрутки каждое нажатие на кнопку прокрутки или перемещение движка вызывает выполнение события Scrolled, которое возвращает следующий код для идентификации действий пользователя:

  • 0 - нажата кнопка прокрутки вверх.
  • 1 - нажата кнопка прокрутки вниз.
  • 2 - пользователь щелкнул мышкой на вертикальной линейке прокрутки сверху от движка.
  • 3 - пользователь щелкнул мышкой на вертикальной линейке прокрутки снизу от движка.
  • 4 - нажата кнопка прокрутки влево.
  • 5 - нажата кнопка прокрутки вправо.
  • 6 - пользователь щелкнул мышкой на горизонтальной линейке прокрутки слева от движка.
  • 7 - пользователь щелкнул мышкой на горизонтальной линейке прокрутки справа от движка.

    При переходе к другому элементу управления из Grid происходит следующая последовательность событий:

Form.Grid.Valid
Form.<<Выбранный элемент управления>>.When
Form.Grid.BeforeRowColChange

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

Form1.Combo1.When
Form1.GotFocus
Form1.Combo1.GotFocus
Form1.Combo1.MouseDown,1,0,108,48
Form1.Combo1.DropDown && Нажатие на раскрывающую стрелку
Form1.Combo1.MouseUp,1,0,108,48
Form1.Combo1.MouseDown,1,0,88,117
Form1.Combo1.MouseUp,1,0,88,117
Form1.Combo1.DownClick && Нажатие на кнопку прокрутки вниз
Form1.Combo1.MouseDown,1,0,92,11
Form1.Combo1.MouseUp,1,0,92,11
Form1.Combo1.UpClick <|>&& Нажатие на кнопку прокрутки вверх
Form1.Combo1.MouseDown,1,0,79,11
Form1.Combo1.MouseUp,1,0,29,27
Form1.Combo1.InteractiveChange && Изменение значения в списке
Form1.Combo1.Click
Form1.Combo1.Valid
Form1.Combo1.When
Form1.Combo1.Valid
Form1.<<Следующий элемент управления>>.When
Form1.Combo1.LostFocus

    Для текстового поля при вводе в него данных с помощью возникающих событий мы можем отследить ввод каждого символа. Поэтому рассмотрим последовательность событий для этого элемента управления. Если текстовое поле Text1 будет размещено в форме Form1, и в текстовое поле мы перейдем с помощью мыши, и будем вводить три символа Rus, а затем нажмем клавишу Enter, то для этого текстового поля произойдет следующая последовательность событий:

Form1.Text1.When          && Проверка доступности
Form1.Text1.Gotfocus
Form1.Text1.MouseDown, 1, 0, 25, 76
Form1.Text1.MouseUp, 1, 0, 25, 76
Form1.Text1.Click
Form1.Text1.KeyPress, 82,1 && Нажимаем клавишу R
Form1.Text1.InteractiveChange
Form1.Text1.KeyPress, 117,0 && Нажимаем клавишу u
Form1.Text1.InteractiveChange
Form1.Text1.KeyPress, 115,0 && Нажимаем клавишу s
Form1.Text1.InteractiveChange
Form1.Text1.KeyPress, 13,0 && Нажимаем клавишу Enter
Form1.Text1.Valid
Form1.Text1.LostFocus

5.4. Использование методов

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

Object.AddObject(cName, cClass [, cOLEClass]
[, aInit1, aInit2 ...])

    С помощью параметра cName мы задаем имя добавляемого объекта, а параметром cClass указывем класс, на основе которого будет создан объект в объекте-контейнере, указанном в Object. Определение класса, на основе которого создается объект, должно быть доступно, то есть если это не базовый класс, мы должны заранее открыть соответствующую библиотеку классов командой SET CLASSLIB. Если мы добавляем OLE-объект, то класс, на котором он будет основан, можно указать с помощью параметра cOLEClass. С помощью aInit1, aInit2... можно передать параметры в событие Init создаваемого объекта.
    В Visual Basic неким аналогом этого метода может являться метод Add, который позволяет добавлять объект в коллекцию.
    Для удаления объекта из его контейнера в Visual FoxPro используется метод RemoveObject, а для удаления объекта из коллекции в Visual Basic - метод Remove.
    Если объект использует данные, которые могут обновляться во время работы программы, использовать их последний вариант поможет метод

Object.Refresh

    который позволяет немедленно перерисовать форму или указанный объект. Причем, когда перерисовывается форма, автоматически обновляются все содержащиеся в ней элементы управления, когда перерисовывается страничный блок PageFrame, автоматически обновляется только активная страница Page.

Control.SetFocus

    Позволяет активизировать указанный элемент управления.

[Object.]ZOrder([nValue])

    Позволяет установить графический уровень отображения указанного объекта. Параметр nValue может принимать либо значение 0, либо 2. Если nValue равен 0 (по умолчанию), то объект выводится на переднем плане, если 2 - на заднем. Задний план обычно используется для отображения результатов работы графических методов (рисование линий, вывод изображений и т. д.), а передний - для отображения объектов. Объекты, отображаемые на переднем плане, перекрывают изображение заднего плана.

Object.Move(nLeft [, nTop [, nWidth
[, nHeight]]])

    Позволяет переместить объект в нужную точку, которая задается новыми координатами левой nLeft и верхней nTop границами объекта. При необходимости можно задать для объекта новую ширину nWidth и высоту nHeight. Обязательным является параметр nLeft, остальные должны указываться без пропусков, то есть если вы задаете ширину объекта, то должны использовать в методе все параметры.
    Если перемещаемый объект входит в объект-контейнер, то новые координаты указываются относительно левого верхнего угла объекта-контейнера, которые равны 0, 0. Например, если вы хотите переместить форму, размеры которой установлены в фокселях, на пятую строку и двадцатую колонку экрана, задайте следующий код:

ThisForm.Move(20, 5)
Object.Hide

    Скрывает форму путем присвоения свойству Visible значения .F.. Элементы управления в скрытой форме, естественно, становятся недоступными для пользователя, но доступны для воздействия на них с помощью программы.

Object.Show([nStyle])

    Выводит на экран форму и, если указан параметр nStyle, определяет способ ее вывода. Если параметр nStyle равен 1 (0 в Visual Basic), то форма является независимой и выполняется код, следующий после строчки, задающей выполнение метода Show. По умолчанию параметр nStyle равен 2 (1 в Visual Basic), и в этом случае программа ждет, когда пользователь завершит работу с формой или когда форма будет выгружена из памяти. До этого момента переход в другую форму или меню невозможен. Если параметр nStyle не указывается, то способ вывода формы определяется значением свойства WindowType.
    Для OLE-объекта можно использовать метод

Object.DoVerb[Verb]

    Выполняет команду для указанного объекта OLE. Параметр Verb - это одна из команд, поддерживаемая всеми объектами и предназначенная для выполнения в объекте-контейнере. Если параметр не указывается, выполняется команда, принятая по умолчанию для данного объекта. Параметр может также указывать номер в массиве свойства ObjectVerbs.
    Следующий список содержит возможные номера для стандартных команд:

ЗначениеДействие
0Действие для объекта по умолчанию
-1Активизирует объект для редактирования
-2Открывает объект в отдельном окне приложения
-3Для включенного объекта скрывает приложение, создавшее объект
-4Активизирует объект при условии, что его активизация поддерживается. При этом выводятся средства пользовательского интерфейса для редактирования объекта на месте (on-place editing)
-5Создает окно для объекта и загружает необходимые для редактирования этого объекта средства, когда пользователь щелчком мыши активизирует объект-контейнер OLE
-6Отменяет все выполненные в процессе модернизации изменения (выполняет действие UNDO) для объектов, открытых для редактирования

    Если вы установите для свойства AutoActivate значение 2, то объект-контейнер OLE автоматически активизирует объект, когда пользователь сделает двойной щелчок мышью на элементе управления.
    Использование имени команды (EDIT, OPEN, PLAY и т. д.) в параметре Verb всегда обеспечивает значительно большую скорость работы, чем использование номера команды.
    Упомянем еще несколько специфических для Visual FoxPro методов, которые часто используются при создании приложения.

Container.SetAll(cProperty, Value [, cClass])

    Позволяет в указанном объекте-контейнере присвоить значение Value для свойства cProperty всем размещенным в нем элементам управления или относящимся к классу cClass (не базовому классу Visual FoxPro!).
    Для Grid могут быть выполнены следующие специфические методы:

Grid.ActivateCell(nRow, nColumn)

    Активизирует клетку с указанными координатами номера строки nRow и колонки nColumn.

Grid.AddColumn(nIndex)

    Позволяет добавить колонку в Grid. Колонка с номером nIndex сдвигается вправо, и ее номер увеличивается на 1.

Grid.DeleteColumn[(nIndex)]

    Позволяет убрать текущую или указанную посредством номера nIndex колонку из Grid.
    Для прокрутки данных можно использовать метод
Grid.DoScroll(nDirection)
    Для выполнения нужного действия аргумент nDirection может принимать следующие значения:

  • 0 - прокрутка на строку вверх.
  • 1 - прокрутка на строку вниз.
  • 2 - прокрутка на страницу вверх.
  • 3 - прокрутка на страницу вниз.
  • 4 - прокрутка на колонку влево.
  • 5 - прокрутка на колонку вправо.
  • 6 - прокрутка на страницу влево.
  • 7 - прокрутка на страницу вправо.
Глава 4 || Содержание || Глава 6