This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
. Результатом выполнения любой из этих операций является окно Print (Печать). Расположенный в верхней части диалогового окна раскрывающийся список Name (Имя) содержит имена всех доступных принтеров. Установка переключателя в области Print range (Область печати) в положе ние All (Все) приведет к тому, что будут распечатаны все страницы отчета, Я вот выбор Pages (Страницы) позволяет задать номера печатаемых страниц'from (от), to (до). Используя счетчик Number of copies (Количество копий), можно задать количество печатаемых экземпляров. При нажатии кнопки Properties (Свойства) можно настроить параметры принтера, вид появляющегося при этом диалогового окна зависит от принтера, установленного в системе (рис. 11.20).
Урок 11. Создание отчетов
129
Рис. 11.19. Диалоговое окно Print
Рис. 11.20. Диалоговое окно Свойства
Впрочем, принтер можно настроить и заранее, используя Панель управлеия Windows.
н
Кнопка Options (Параметры) из окна Print (см. рис. 11.19) позволяет вы полнить дополнительную настройку принтера (рис. 11.21). Зак Ю02
130
Часть I. Процедурное программирование в Visual FoxPro
Рис. 11.21. Диалоговое окно Print Options
В области Print what (Что печатать) находится раскрывающийся список Туре (Тип), в котором можно указать тип печатаемой информации. В поле File (Файл) указан полный путь доступа к файлу. Флажки имеют следующее назначение: • Line numbers (Номера строк) — используется для печати в отчете нумера ции строк. Доступен при печати содержимого командного окна или файла; • Page eject before (Прогон страницы перед печатью) — перед печатью отчета дает принтеру команду перехода на новую страницу; • Page eject after (Прогон страницы после печати) — осуществляет перехс на новую страницу после окончания печати; • Restore environment (Восстановить среду данных) — эта "фишка" используется для совместимости со старыми версиями FoxPro. Как ни странно, и в этом окне есть кнопка, также называемая Options (Параметры). Используя данную кнопку, мы можем задать условия выборки записей, предназначенных для вывода на печать. По нажатию этой кнопки на экран выводится диалоговое окно Report and Label Print Options (Параметры для печати отчетов и этикеток) (рис. 11.22), в котором можно задать следующие параметры печати: • Scope (Диапазон значений) — в этом списке выбирается диапазон печатаемых записей; • For (Для) — запускается построитель выражений, в котором можно задать логическое выражение. При этом будут печататься только те записи, для которых значение этого выражение будет равным .Т. (Истина); • While (Пока) — все, как в предыдущем пункте, но в отличие от него печать отчета будет прекращена как только встретится первая запись, ДЛЯ которой значение этого выражения будет равным .F. (Ложь).
Урок 11. Создание отчетов
131
Рис. 11.22. Диалоговое окно Report and Label Print Options
Создание отчетов с использованием мастера Report Wizard Для запуска Report Wizard (Мастер отчетов) также имеется несколько спо собов — все они аналогичны тем, которые мы использовали при запуске Form Wizard (Мастер экранных форм). Независимо от способа запуска на экране появится первое диалоговое окно мастера (рис. 11.23).
Рис. 11.23. Диалоговое окно Wizard Selection
132
Часть I. Процедурное программирование в Visual FoxPro
В этом окне опять, как и при использовании мастера форм, предлагается сделать выбор мастера: • One-to-Many Report Wizard — этот мастер создает отчет для связанных таблиц; О Report Wizard — простой отчет для одной таблицы. Первый шаг работы мастера отчетов полностью идентичен первому шагу работы мастера экранных форм — здесь мы выбираем таблицу и необходи мые поля (рис. 11.24).
Рис. 11.24. Первый шаг работы мастера отчетов
На втором шаге работы мастера (рис. 11.25) можно задать поля, по которым будет производиться группировка данных в отчете. Поддерживается от од-] ной до трех групп данных. Параметры группировки задаются так: в раскры вающемся списке указываем имя поля, а затем, нажимая кнопку Grouping] options (Параметры группировки), задаем интервал группировки в диалого вом окне Grouping Intervals (рис. 11.26). В раскрывающемся списке Grouping intervals (Интервал группировки) мож но выбрать следующие значения: О Entire Field — полностью значение поля; О 1st Letter — по первой букве; • 2, 3, 4, 5 Initial Letters — по первым двум, трем и т. д. буквам. Кнопка Summary Options (Итоговые значения) вызывает диалоговое окно Summary Options, в котором можно сформировать итоговые значения ДЛЯ каждого поля (рис, 11.27).
Урок 11. Создание отчетов
133
Рис. 11.25. Второй шаг — группировка данных
Рис. 11.26. Диалоговое окно Grouping Intervals
В расположенной в этом окне таблице выбираем имя поля и ставим "птичУ" в нужном столбце. Значения столбцов: О Field — имя поля; ^ Sum — сумма значений; К
134
Часть I. Процедурное программирование в Visual FoxP/qj
Рис. 11.27. Диалоговое окно Summary Options
• Avg — среднее значение; • Count — число строк; • Min — минимальное значение; • Мах — максимальное значение. Переключатели, расположенные под таблицей, управляют отображением в отчете полос. На третьем шаге выбирается стиль отчета (рис. 11.28).
Рис. 11.28. Третий шаг работы мастера отчетов
Шаг четвертый (рис. 11.29) — указывается положение страницы: • Portrait — книжное расположение страницы на экране; • Landscape — альбомное расположение страницы.
ш
к 11. Создание отчетов
Рис. 11.29. Четвертый шаг работы мастера отчетов
Рис. 11.30. Заключительный шаг работы мастера отчетов
135
136
Часть I. Процедурное программирование в Visual FoxPro
Также здесь указывается порядок размещения полей с помощью группы переключателей Field Layout (Расположение поля). Шестой и последний шаг мастера отчетов (рис. 11.30) аналогичен такому же шагу мастера экранных форм. Откроем предварительный просмотр, нажав кнопку Preview (Просмотр) — рис. 11.31.
Рис. 11.31. Отчет, созданный мастером отчетов
Ну и что получилось? Применительно к нашей задаче — ничего хорошего^ Но зато мы познакомились с работой мастера отчетов, использование KOTOJ рого в других приложениях может стать более чем оправданным. Мы еше] вернемся к этому инструменту при работе с базой данных. Использование дополнительных инструментов для создания отчетов, такЖ как AutoReport Wizard и Quik Report, также будет изучено при создании на-j шего следующего приложения.
Вызов отчета из формы Теперь, когда мы узнали, как вывести отчет на печать, неплохо бы сделать так, чтобы отчет печатался при нажатии на определенную кнопку экранно) формы.
Урок 11. Создание отчетов
137
Откроем окно конструктора форм и определим действия, происходящие при наступлении события click для кнопки Печать. Вывод отчета на принтер выполняет следующая команда: REPORT FORM (Путь) Имя_Отчета ТО PRINTER
Но при этом вывод информации может происходить как на принтер, так и в окно экранной формы. Чтобы запретить вывод на экран, следует в данной команде указать параметр NOCONSOLE: REPORT FORM C:\EXAMPLES\REPORTl ТО PRINTER NOCONSOLE
Для открытия окна предварительного просмотра можно применить такую конструкцию: REPORT FORM C:\EXAMPLES\REPORTl PREVIEW
А еще можно поместить наш отчет в текстовом файле: REPORT FORM C:\EXAMPLES\REPORTl ТО FILE TXT1.TXT ASCII
Но при этом все графические элементы отчета будут проигнорированы. Преимуществом является то, что отчет в виде файла можно просматривать в любом текстовом редакторе, например, используя даже встроенный редак тор текста в Norton Comander или Блокнот Windows (рис. 11.32).
Рис. 11.32. Просмотр отчета в виде текстового файла в Блокноте
А вот результат работы нашей кнопки Печать, в которой использована команда REPORT FORM C:\EXAMPLES\REPORTI PREVIEW, показан на рис. 11.33. Отчет находится в границах формы, потому что мы используем форму верх него уровня. Для перемещения по странице используются горизонтальная и вертикальная линейки прокрутки. о конструкции REPORT FORM... можно также задать условия для выборки записей. Например, для того чтобы просмотреть или распечатать только те Уравнения, которые имеют два корня, достаточно ввести следующую команду: REPORT FORM REPORTI PREVIEW FOR D>O
138
Часть I. Процедурное программирование в Visual FoxPro
Рис. 11.33. Режим просмотра включается из нашей формы
УРОК 12
Компиляция проекта Теперь, когда практически все готово, можно перейти к созданию испол няемого приложения. Для формирования файла приложения с расширени ем арр или исполняемого файла, имеющего расширение ехе, достаточно щелкнуть на кнопке Build (Построить) в диалоговом окне Project Manager. Но прежде необходимо отметить главный файл, который будет использо ваться в качестве первого файла при генерации проекта. Главный файл ус танавливается при помощи команды Set Main (Установить главным) пункта Project (Проект) линейки системного меню или одноименной команды кон текстного меню, вызываемого нажатием правой кнопки мыши. Файл, отме ченный как главный, выделяется полужирным шрифтом. Обычно в качестве главного файла выступает меню, но таким элементом может быть практиче ски любой файл проекта. В нашем случае применим команду Set Main к файлу нашей экранной формы Formi (рис. 12.1). После нажатия кнопки Build открывается диалоговое окно Build Options (рис. 12.2). Используя группу переключателей Action (Действия) мы указываем те дей ствия, которые будут происходить при запуске процесса компиляции: • Rebuild Project (Перестроить проект) — при выборе этой опции файл проекта полностью заново перестраивается, при необходимости вновь добавленные в проект файлы компилируются; • Build Application (Создать приложение) — создается файл приложения с расширением арр. Приложение будет работать только на тех компьюте рах, на которых установлен полный пакет Visual FoxPro; • Build Executable (Создать исполняемый файл) — а вот это уже всем зна комый "ЕХЕ-шник"! В общем, все операции, происходящие при форми ровании данного файла, аналогичны тем, которые происходят при фор мировании файла приложения арр, но при этом еще добавляются при сущие ЕХЕ-файлам элементы: загрузчик и заголовок файла. Для работы
140
Часть I. Процедурное программирование в Visual FoxPro
данного файла также требуется наличие необходимых библиотек Visual FoxPro (Vfp6renu.dll и Vfp6r.dll); • Build COM DLL (Создать библиотеку) — создается файл с расширение dll (Dynamic Link Library, динамически подключаемая библиотека). Параметры, устанавливаемые в группе Options диалогового окна Buil Options, имеют следующее назначение: О Recompile All Files (Перекомпиляция всех файлов проекта) — заново компилируются все включенные в проект файлы, независимо от времени их создания;
Рис. 12.1. С помощью команды контекстного меню устанавливаем главный файл приложения
Рис. 12.2. Диалоговое окно Build Options
Урок 12. Компиляция проекта
141
О Display Errors (Просмотр ошибок) — вся информация об ошибках, воз никающих при компиляции приложения, заботливо складывается Лисом в одном файле — этот файл имеет расширение err. При установке данно го флажка после завершения процесса компиляции ERR-файл будет от крыт для просмотра; О установка флажка Run After Build (Запуск после создания) приведет к тому, что после завершения компиляции приложение будет сразу запу щено на выполнение; О при установке флажка Regenerate Component IDs (Перестроить иденти фикаторы компонентов) происходит установка и регистрация Auto mation-серверов, которые могут содержаться в проекте. Данный флажок доступен при установленной опции Build COM DLL или Build Executable. Для того чтобы включить файл проекта в процесс компиляции, или, наобо рот, исключить — используются команды контекстного меню Include (Включить) и Exclude (Исключить). Исключенные файлы отображаются ря дом с перечеркнутым кружком. Тебя, вероятно, уже насторожили фразы о том, что для работы твоего при ложения на "чужом" компьютере необходимо присутствие на нем Visual FoxPro: "Это что же творится, люди добрые?! Ночами не спишь, создаешь приложения, а потом еще на каждый компьютер своего Лиса ставить?!" Не все так трагично, дружок. Дело в том, что состав Visual FoxPro входит замечательное средство — Setup Wizard, с помощью которого ты за шесть секунд создашь фирменную программу установки, в которую будут входить как твое приложение, так и необходимые для его работы "фоксовские" фай лы. И все всегда везде и у всех будет работать. Ну а теперь давай построим наше первое приложение, пусть это будет файл с расширением арр. Установив необходимые параметры, нажмем кнопку Build диалогового окна Project Manager. В открывшемся диалоговом окне Save As (Сохранить как) укажем имя приложения и папку, в которой оно будет сохранено, после чего запустится процесс генерации приложения. Через несколько секунд компиляция будет закончена, и в строке состояния появится сообщение "Build application completed", после чего можно закон чить работу с Visual FoxPro и запустить приложение (рис. 12.3). Замечание При создании нашей экранной формы мы определили ее как форму верхнего уровня, поэтому для того чтобы она выполнялась не в окне FoxPro, а прямо на рабочем столе Windows, можно перед началом компиляции включить в свойст во i n i t следующую команду: SCREEN.VISIBLE=.F.
142
Часть I. Процедурное программирование в Visual FoxPro
Рис. 12.3. Приложение выполняется на Рабочем столе Windows
урок 13
Работа с базой данных Что такое база данных? В начале книги было дано определение базы дан ных, так сказать, с "обывательской" точки зрения. А вообще под базой дан ных в Visual FoxPro подразумевается совокупность таблиц, которые могут каким-то образом быть связанными между собой. А могут быть и не свя занными. А можно вообще обойтись без использования баз данных, успеш но применяя для решения поставленных задач свободные таблицы. Так для чего тогда усложнять себе жизнь? Все дело в том, что использова ние баз данных не усложняет, а, наоборот, значительно упрощает работу с данными. Это происходит потому, что именно в базе данных реализованы мощные и полезные функции, используемые при работе с таблицами. Создать новую базу данных можно так же, как и любой другой файл Visual FoxPro. Мы уже подробно рассматривали процесс создания новых файлов, повторяться не будем. Действия полностью аналогичны, за исключением того, что в открывающихся диалоговых окнах необходимо указать опцию Database (База данных). При использовании командного окна применяется следующая команда: CREATE DATABASE <имя_файла>
При работе с использованием окна диспетчера проекта (Project Manager) Для создания новой (кнопка New) или модификации существующей базы Данных (кнопка Modify) применяется конструктор базы данных — Database Designer.
Конструктор базы данных В окне конструктора базы данных (рис. 13.1) расположена панель управ ления Database Designer. Назначение кнопок данной панели описано в табл. 13.1.
144
Часть I. Процедурное программирование в Visual FoxPro
Рис. 13.1. Окно конструктора базы данных с панелью инструментов Database Designer Таблица 13.1. Кнопки панели Database Designer
Урок 13. Работа с базой данных
145 Таблица 13.1 (окончание)
Сейчас мы начнем создавать новое приложение, в котором рассмотрим ас пекты работы с базой данных. Назовем его отель Старый Лис. Вряд ли это приложение (по крайней мере, именно в таком виде) найдет применение в практической жизни, но это и не особо важно. Наша цель — познакомиться с принципами работы с базой данных, с остальными элементами управле ния экранных форм и т. д. Но, прежде чем приступить к работе, поговорим о следующем: как нам ор ганизовать файлы? Когда мы делали наше самое первое приложение, мы располагали все файлы в одной папке. Так можно делать, если файлов не очень много. А если их сотни, тысячи? Тут необходимо их как-то рассорти ровать по типам: формы в одной папке, отчеты в другой и т. д. Уловил мысль? Обычно в основном каталоге (папке), где "лежит" твое приложение, создается несколько подкаталогов, например: Database, Forms, Menus, Progs, Images, Others и т. д. И теперь всем, а тебе в первую очередь, ясно, где ка кой файл находится. Все это не догма, можешь делать, как хочешь, но предложенный способ, несомненно, поможет придать твоему приложению более стройный вид. Начнем с того, что создадим новую таблицу базы данных. Нажав кнопку New (Новая) на панели инструментов Database Designer и указав в открыв шемся диалоговом окне Create (Создать) имя новой таблицы, мы увидим уже знакомое окно Table Designer (Конструктор таблицы) (рис. 13.2). Окно вроде как бы знакомое, да что-то не то, не правда ли? Мы видим, что Данный инструмент "обзавелся" дополнительными возможностями. О Формат данных и маска ввода (поля ввода Format и Input mask) позво ляют задать формат представления значений поля и маску ввода. О Заголовок поля (поле ввода Caption). По умолчанию при просмотре таб лиц в режиме BROWSE в качестве заголовка поля FoxPro использует имя поля. Теперь мы можем изменить эту ситуацию, вводя для каждого поля его заголовок в поле ввода Caption. Q Контроль данных на уровне поля. Условие или правило можно как вве сти непосредственно в поле ввода Rule (Правило), так и используя уже
146
Часть I. Процедурное программирование в Visual FoxPro
знакомое нам диалоговое окно Expression Builder (Построитель выраже ния), нажав для его вызова расположенную справа от поля кнопку с тре мя точками. • В поле ввода Message (Сообщение) можно задать сообщение, которое будет отображаться на экране при несоблюдении условия, указанного в поле Rule. • Для любого поля можно задать значение по умолчанию, например, сис темную дату (Default value).
Рис. 13.2. Диалоговое окно Table Designer
Поле Field comment (Комментарий для поля) используется для ввода ком ментария для данного поля. Длина комментария может быть произвольной, т. к. этот элемент представлен в виде поля Memo.
Индексы Индексы используются для сортировки записей и организации связей меж ду таблицами, а также для ускорения доступа к данным. Индексы в Visual FoxPro хранятся в файлах, имеющих расширение cdx — это так называемые составные индексные файлы. В ранних версиях использовалось расширение idx, или простой индексный файл, который мог содержать только одно ин дексное выражение.
Урок 13. Работа с базой данных
147
Простые индексы Простые индексы, состоящие из одного индексного выражения, использо вались в FoxBase — предшественнике Visual FoxPro. В те древние времена для каждого индексного выражения использовался отдельный индексный файл. Вот и приходилось почти всегда при открытии таблиц специально открывать вместе с таблицей и все ее индексы. Для чего это делалось? Все просто — если не открыть необходимый индексный файл, Лис не сможет его модифицировать при добавлении или удалении записей из таблицы — он просто его не "увидит", ведь не могут все индексные файлы иметь имена, совпадающие с именем таблицы! В настоящее время уже как бы принято за правило использовать составные или структурные индексы.
Составные индексы Никто не запрещает использовать в приложениях простые индексы с рас ширением idx, но применение составных индексов кажется более предпоч тительным и вот почему: • в один индексный файл можно включить несколько индексных выраже ний; • если индексному файлу присвоить имя таблицы, то он всегда будет от крываться вместе с таблицей — потерять такой файл невозможно; • структурный индекс всегда автоматически привязывается к "своей" таб лице. Из чего состоит индексный файл? Файлы данного типа могут содержать один или несколько тегов. Тег (Tag) — это и есть индексное выражение. Чтобы узнать, какие именно теги используются в индексе, можно восполь зоваться функцией TAG о, которая возвращает имя тега. А вот сколько этих самых тегов — подскажет функция TAGCOUNT (). Узнать имя самого индекс ного файла можно, применив функцию CDX () или аналогичную ей MDX (). В Visual FoxPro имеется четыре типа индексов: О Primary (Первичный). В таблице может быть только один первичный ин декс (иногда его называют первичным ключом), который позволяет вво дить только уникальные значения данного поля; О Candidat (Кандидат или потенциальный). Также позволяет вводить толь ко уникальные значения поля, но в отличие от индекса Primary таблица может иметь несколько индексов такого типа; О Regular (Регулярный или простой). Данный индекс может быть создан для любого значения поля;
Часть I. Процедурное программирование в Visual FoxPro
148
• Unique (Уникальный). Может быть создан только для неповторяющихся значений поля. Как и Regular, данный индекс широко применялся в[ ранних версиях FoxPro. Теперь перейдем к практике и создадим в нашей базе данных три таблицы. Для этого откроем окно конструктора базы данных и, воспользовавшись кнопкой New Table (Новая таблица) панели Database Designer, создадим таблицу Countries.dbf со структурой, отображенной в табл. 13.2. Таблица 13.2. Countries.dbf
Тип поля
Имя поля
Заголовок
Integer (4)
IDcountry
Идентификатор
Character (10)
cCountry
Страна
Таким же образом (табл. 13.4).
создадим таблицы
Cities.dbf (табл. 13.3),
Таблица 13.3. Cities.dbf Тип поля
Имя поля
Заголовок
Integer (4)
Idcountry
Идентификатор
Character (30)
CCity
Город
Integer (4)
idcity
Идентификатор города
Таблица 13.4. Streets.dbf
Тип поля
Имя поля
Заголовок
Integer (4)
Idcity
Идентификатор города
Character (10)
cStreet
Улица
И проиндексируем их следующим образом: •
таблица Countries.dbf: TAG: Idcountry TAG: country
•
Primary Regular
INDEX ON : idcountry INDEX ON: country
Regular Regular Candidate
INDEX ON: Idcountry INDEX ON: ccities INDEX ON: idcity
таблица Cities.dbf: TAG: idcountry TAG: ccities TAG: idcity
Streets.dbf
Урок 13. Работа с базой данных
149
0 таблица Streets.dbf: TAG : i d c i t y TAG: s t r e e t
Regular Regular
INDEX ON : i d c i t y INDEX ON: s t r e e t
Рассмотрим подробно процесс индексации на примере создания индексов для таблицы Countries.dbf. В окне конструктора таблиц (Table Designer) пе рейдем на вкладку Indexes (Индексы). В поле Name вводим имя индекса, а из раскрывающегося списка Туре (Тип) выберем необходимый тип. Затем, нажав кнопку справа от поля ввода Expression (Выражение), вводим значе ние индексного выражения в окне построителя выражений. Но в данном примере мы не будем применять сложные выражения и просто зададим имена полей (рис. 13.3).
Рис. 13.3. Создание индексов в окне конструктора таблиц
Вот теперь, когда созданы таблицы и соответствующие индексные файлы, можно перейти к следующему шагу.
Создание постоянных отношений Отношения (Relation) могут быть временными и постоянными. Вся разница состоит во времени "жизни" и способа их создания.
150
Часть I. Процедурное программирование в Visual FoxPro
Временные отношения создаются командой SET RELATION (имеющей много дополнительных параметров) и существуют только в текущем сеансе Visual FoxPro. После завершения работы созданные таким образом отношения "приказывают долго жить". Такого же результата можно добиться, введя команду SET RELATION без параметров. Постоянные же отношения создаются в конструкторе базы данных и сохра няются после сеанса работы. Для создания отношений между таблицами (а говоря проще, для того чтобы связать их) необходимо, чтобы таблицы были соответствующим образом проиндексированы. Это, как ты уже догадался, обязательное условие! Также нужно соблюдать еще одно правило: таблица, с которой начинаем установку отношений, должна иметь индекс типа Primary или candidate, потому что никак не получится создать отношение, начав с регулярного индекса. Теперь от слов переходим к делу: открой конструктор базы данных (рис. 13.4). На каждой из трех таблиц после списка полей изображены име на индексов. Таблица countries содержит рядом с именем индекса изобра жение ключика. Вот это и есть так называемый первичный ключ, именно с него мы начнем связывать таблицы. Процесс создания отношений довольно прост — щелкаем мышью на имени | индекса и тащим его к индексу в другой таблице (в нашем случае к cities). Все, отношение установлено. Таким же образом свяжем таблицу cities] С таблицей s t r e e t s .
Рис. 13.4. Установка отношений между таблицами
Таблица countries является родительской таблицей (parent table) по отно шению к таблице cities, которая, в свою очередь, является дочерней (child table) по отношению к таблице countries. Но таблица c i t i e s является одно временно и родительской по отношению к таблице streets. Сложно? А ты как думал! Здесь только три таблицы, а если бы их было сто тридцать три, знаешь, какое можно "генеалогическое дерево" нарисовать! Итак, шутки в сторону, что мы имеем? Таблицы связаны, связи отобража ются линиями, заканчивающимися тремя штрихами. Эти штрихи показы-
Урок 13. Работа с базой данных
151
вают, что в данном случае имеет место связь "один-ко-многим" (one-tomany). Что же будет происходить, когда мы начнем перемещаться по записям таб лицы countries? При этом "на другой стороне" отношения, в таблице горо дов cities, будут отображаться только те города, которые относятся к стра не, выбранной в таблице countries. А это и определяется значением индек са idcountry. Так как в любой стране имеется как минимум два города, в данном случае применяется именно отношение "один-ко-многим". Ты спрашиваешь, какие еще бывают отношения? Еще есть отношение "один-к-одному". При таком виде связи указатель в дочерней таблице оста новится на первой встретившейся записи, имеющей такое же значение ин декса, что и запись в родительской таблице. Связь типа "один-к-одному" установится в том случае, если мы будем связывать таблицы по их первич ным ключам, которые имеют уникальные, неповторяющиеся значения. Во всех остальных случаях будет автоматически установлено отношение "одинко-многим". Для редактирования связей между таблицами используется диалоговое окно Edit Relationship (Редактирование отношений) (рис. 13.5). Для его вызова достаточно дважды щелкнуть на линии, отображающей отношение, или воспользоваться соответствующей командой контекстного меню.
Рис. 13.5. Диалоговое окно Edit Relationship
Ну вот, все готово и можно с удовлетворением вздохнуть. Ан нет, не все спокойно в мире! Попробуй, измени значение поля idcountry для какойнибудь записи в таблице countries (теоретически, записей пока нет). Что же тогда произойдет с записями в связанной с ней таблицей cities? В физиче ском смысле — ничего с ними не случится, а вот что касается отношений — здесь нас поджидает неприятность — Лис просто не найдет эти записи. Чтобы избежать подобной ситуации, необходимо каким-то образом сделать т ак, чтобы при изменении значений индексов в родительской таблице авто матически обновлялись соответствующие индексы в дочерних таблицах. Другими словами, необходимо обеспечить ссылочную целостность базы Данных.
152
Часть I. Процедурное программирование в Visual FoxPro
Для этой цели в Visual FoxPro имеется инструмент, называемый Referential Integrity Builder (Построитель ссылочной целостности).
Referential Integrity Builder Для вызова Referential Integrity Builder достаточно щелкнуть правой кнопкой мыши на линии, отображающей связь между таблицами, и выбрать команд контекстного меню Edit Referential Integrity (Редактировать ссылочную це лостность). После выбора данной команды открывается окно построителя (рис. 13.6).
Рис. 13.6. Диалоговое окно Referential Integrity Builder
В данном окне есть три вкладки: Rules for Updating (Правила при обновле** нии), Rules for Deleting (Правила при удалении) и Rules for Inserting (Пра-y вила при вставке). Внизу расположена таблица, в которой перечислены все отношения. В пер^ вом столбце этой таблицы указано имя родительской таблицы, а во вто*| ром — дочерней. В трех следующих столбцах указаны правила соблюдение 1 ссылочной целостности для каждого конкретного случая: Update (Обновле*] ние), Delete (Удаление), Insert (Вставка). В двух последних столбцах указа^ ны теги. По умолчанию в трех столбцах (Update, Delete, Insert) установлено значенЖ Ignore (Игнорировать) и никакая ссылочная целостность, естественно, пок не соблюдается. При щелчке мышью в любом из этих столбцов появляется меню, содержу шее допустимые варианты поведения.
Урок 13. Работа с базой данных
153
Существуют следующие правила поведения, которые могут быть использо ваны при изменении значений индекса в родительской таблице: О Cascade (Каскадное изменение) — при изменении значения ключа в ро дительской таблице произойдет каскадное обновление соответствующих индексов и в дочерней таблице. Это как раз тот случай, который мы рас сматривали ранее; П Restrict (Ограничить) — обновление значений ключа в родительской таб лице невозможно, если имеются соответствующие значения в записях дочерних таблиц; О Ignore (Игнорировать) — правила ссылочной целостности не соблюдают ся и возможны любые изменения в значениях индексов. Мы рассмотрели правила при обновлении, правила при удалении записей полностью аналогичны. А вот правила при вставке (Insert) следующие: • Restrict (Ограничить) — не удастся вставить в дочернюю таблицу записи в том случае, если в родительской таблице нет записей с таким же зна чением ключа; О Ignore (Игнорировать) — разрешена вставка записей, ссылочная целост ность соблюдаться не будет. В верхней части построителя расположена группа переключателей, при по мощи которых также можно реализовать все сказанное ранее. Что же, давай разрешим обновление значений индекса в таблице c i t i e s в случае обновления соответствующего индекса в родительской таблице countries и обновление в таблице streets при изменении значений в таб лице cities. Установив необходимые правила для соблюдения ссылочной целостности, закроем диалоговое окно построителя, воспользовавшись кнопкой ОК. При этом появится диалоговое окно, в котором Лис спросит, действительно ли мы хотим сохранить произведенные изменения (рис. 13.7).
Рис. 13.7. Сохранение произведенных изменений
Ответим Да и после генерации соответствующего кода процесс определения ссылочной целостности будет завершен. Теперь, прежде чем приступить к заполнению наших таблиц, необходимо Рассмотреть следующий важный вопрос — что такое идентификаторы?
154
Часть I. Процедурное программирование в Visual FoxPro
Идентификаторы Практически любая таблица имеет поле, специально выделенное для хране ния значения, которое однозначно идентифицирует каждую запись. Вот это и есть идентификатор, он же "первичный ключ" (primary key). Например, в нашей таблице countries значение в поле idcountry соответствует назва нию страны. Значения в этом поле должны быть уникальными, неповто ряющимися — не может быть двух стран с одинаковым названием. В даль нейшем мы рассмотрим вопрос, каким образом можно реализовать автома тическую генерацию значений ключа при добавлении записей в таблицу, а теперь поговорим вот о чем: значение идентификатора нежелательно ника ким образом связывать со значениями других полей. Что это значит? На пример, не нужно в качестве идентификатора фирмы использовать ее на звание: во-первых, оно может со временем измениться, а во-вторых, может быть несколько компаний с одинаковыми названиями. Также нежелательно в качестве идентификатора человека использовать номер его паспорта — та же причина (человек существо беспокойное, он с легкостью может сменить паспорт, герб, флаг и даже пол...). В общем, идентификатор должен быть абсолютно абстрактной величиной,, не подверженной никаким внешним воздействиям. Займись на досуге буд дизмом! Теперь перед нами встает следующий вопрос: какого типа должны быть идентификаторы: символьного или числового? Рассмотрим и те и другие. Преимущества числовых идентификаторов: • всегда точное сравнение, не зависящее от длины поля; • для получения нового значения идентификатора достаточно произвести одну-единственную математическую операцию — "сложение", и не нуж но "выдумывать" никаких специальных функций. Их недостатки: • можно по неосторожности включить их в какие-то вычисления. Преимущества символьных идентификаторов: П они никогда не могут быть использованы в математических вычисле-! ниях; • использование в идентификаторе сочетания цифровых и алфавитных символов значительно повышает его "емкость". Их недостатки: • для генерации нового значения необходимо использовать специальные функции, здесь не удастся обойтись "простыми" математическими опера циями; /
Урок 13. Работа с базой данных
155
- необходимо всегда точное сравнение значений (они могут занимать не все поле целиком), как следствие, необходимо повсеместно использовать функцию ALLTRIMO, которая убирает из выражения начальные и конеч ные пробелы. Как видно, недостатки идентификаторов одного типа являются преимуще ствами другого, и наоборот. Теперь обсудим такой вопрос: как произвести генерацию неповторяющихся значений? Первое, что приходит на ум — метод последовательного увеличе ния. Просто берем последнее значение и увеличиваем его на какую-то ве личину. Обычно используется два варианта: - в таблице находится последнее значение (максимальное) и вычисляется следующее; - последнее значение хранится в отдельной таблице. Просто берем его от туда и на его основе вычисляем следующее. Рассмотрим первый вариант, когда последнее значение идентификатора на ходится непосредственно в таблице. Допустим, у нас есть форма с кнопкой, при нажатии которой происходит добавление записи в таблицу. Код для события click будет выглядеть примерно так, как описано в листинге 13.1. Листинг 13.1. Первый вариант вычисления значения идентификатора *переходим в рабочую о б л а с т ь , в которой открыта наша таблица SELECT C o u n t r i e s *проверяем, есть ли хотя бы одна запись. Функция RECCOUNT() возвращает количество записей в таблице IF RECCOUNT()=0 *если записей нет, добавляем новую запись и вводим первое значение идентификатора APPEND BLANK REPLACE Idcountry WITH 1 ELSE *если записи есть, переходим на последнюю GO RECCOUNTO *присваиваем значение идентификатора переменной Lastid = Idcountry Добавляем запись и устанавливаем новое значение идентификатора APPEND BLANK REPLACE Idcountry WITH Lastid +1 ENDIF
Спрашивается, почему для перехода на последнюю запись мы использовали Go RECCOUNTO? Есть же команда GO BOTTOM! А все дело в том, что функция
156
Часть I. Процедурное программирование в Visual FoxPro
RECCOUNTO возвращает количество физических записей в таблице, в то время как GO BOTTOM подвержена влиянию команд SET ORDER TO (порядок отобра жения индексированных записей) и SET FILTER TO (отображение записей, удовлетворяющих условию). А посему при применении GO BOTTOM нам при
шлось бы где-то запомнить значение тегов и фильтра, "снять" их, а после перехода опять восстановить эти значения. А к чему нам лишние пробле мы? При использовании же данного метода максимальное значение иден тификатора всегда будет находиться в последней записи, его и искать не надо. Недостатком этой процедуры является то, что пользователь может удалить какие-то записи, а затем при добавлении новых окажется, что данное значение идентификатора уже использовалось ранее. И если не задать условия сохранения ссылочной целостности — сам понимаешь, к чему это может привести. Второй вариант: последнее значение идентификатора хранится в единст венной записи дополнительной таблицы, пусть это будет Myjast_id.dbf с полем iast_id (integer) и одной пустой записью (листинг 13.2). Листинг 13.2. Второй вариант вычисления значения идентификатора SELECT Countries APPEND BLANK REPLA Idcountry WITH my__last_id . Last_id+1 SELECT My_Last_Id REPLA Last_Id WITH countries . Idcountry SELECT Countries
В этом случае мы можем не беспокоиться о том, что после удаления запи-| сей из основной таблицы и последующем добавлении новых нам может встретиться уже применявшееся ранее значение идентификатора. Недостатком является то, что, применяя этот метод, так сказать, "в чистом] виде", нам придется создавать для каждой таблицы свою дополнительную таблицу, хранящую последнее значение идентификатора. Никто, конечно, так не делает — все гораздо проще: просто нужно слегка) "модернизировать" таблицу My_iast_id, добавив в нее поля с названиями, совпадающими с псевдонимами всех необходимых таблиц, а потом изме-нить код указанной ранее процедуры для каждой таблицы. В этом случае в каждом поле будет находиться значение идентификатора только для "своей" таблицы. А если таблиц очень много, то для каждой писать почти одинаковый код? Это "не есть хорошо!" А если приложение в процессе работы создаст новые таблицы, например, используя команду COPY? А если...
Урок 13. Работа с базой данных
157
Да, вопросов может возникнуть множество. Поэтому вот тебе, дружок, поч ти универсальный рецепт на все случаи жизни. Создаем дополнительную таблицу Lastid.dbf со следующей структурой — табл. 13.5. Таблица 13.5. Lastid.dbf
Тип поля
Имя поля
Integer (4)
lastid
Character (20)
alias
И ПИШем ФУНКЦИЮ M y l a s t i d (ЛИСТИНГ 13.3). Листинг 13.3. Функция M y l a s t i d FUNCTION M y l a s t i d PARAMETER a l i a s IF TYPE ("Myalias")#"C".OR.EMPTY("Myalias") Myalias=ALIAS() ENDIF SELECT Lastid LOCATE FOR Lastid.Alias=Myalias IF FOUND()=.T. REPLACE Lastid.Lastid WITH Lastid.Lastid+1 ELSE APPEND BLANK REPLA Lastid.Alias WITH Myalias,Lastid.Lastid WITH 1 ENDIF SELECT SMyalias RETURN Lastid.Lastid
Вот и все! Теперь у нас есть всего одна таблица, которая хранит значения идентификаторов для любого количества таблиц. Более того, данную функ цию мы запишем как хранимую процедуру, входящую в состав нашей базы Данных.
Хранимые процедуры Хранимая процедура — это программа или функция, которая определяется Пользователем, т. е. тобой, и хранится в контейнере базы данных. Создать хранимую процедуру можно так: выбрать в окне диспетчера проекта баз У данных, перейти в группу Stored Procedures (Хранимые процедуры)
158
Часть I. Процедурное программирование в Visual FoxPro
(рис. 13.8) и нажать кнопку New (Новая). После этого откроется окно ре дактирования хранимых процедур, в котором могут содержаться как про цедуры, созданные тобой ранее, так и автоматически сгенерированные Vis ual FoxPro. (Лис автоматически создает процедуры и функции при опреде лении условий ссылочной целостности базы данных.)
Рис. 13.8. Группа Stored Procedures содержит хранимые процедуры
Как записать свою процедуру? Очень просто — если окно редактирования) хранимых процедур пустое, просто бери и пиши в нем свой код. А если там уже есть ранее определенная процедура? Тогда просто "пролистай" все нахо дящиеся в этом окне процедуры и функции (используя вертикальную линейку прокрутки) и пиши свой код после них, на свободном месте (рис. 3.9).
Рис. 13.9. Окно редактирования хранимых процедур
Урок 13. Работа с базой данных
/59
Совет Никогда не изменяй те функции, которые получены путем автоматической гене рации при определении условий ссылочной целостности — к чему могут при вести эти изменения, одному Лису известно...
Теперь для таблиц, входящих в состав базы данных, нужно определить триг геры (правила).
Триггеры Триггер INSERT определяет действия, которые будут выполняться после до бавления в таблицу новой записи. Триггер UPDATE — то же самое, только после изменения записи. Триггер DELETE определяет действия, которые будут выполняться после уда ления записи из таблицы. На вкладке Table окна Table Designer имеется группа Triggers (Триггеры), в которой расположены три поля ввода: Insert Trigger, Update Trigger, Delete Trigger. Вот в эти-то поля и заносится вызов хранимой процедуры, логиче ское выражение или операторы сравнения — в общем, любое допустимое выражение. И если результатом вычисления данного выражение будет .Т. (True) —- все в порядке! В противном случае нашего уважаемого пользовате ля ждет сообщение об ошибке. Вызов триггеров происходит в следующих случаях: • триггер UPDATE — при любом изменении значения поля, а также при вы полнении команд REPLACE, REPLACE FROM ARRAY, UPDATE-SQL, GATHER; • триггер DELETE — при установке на записи метки на удаление в режиме просмотра или/и при выполнении команды DELETE; • триггер INSRET — при вводе новой записи в режимах BROWSE ИЛИ EDIT, a также при выполнении команд APPEND FROM, APPEND FROM ARRAY, APPEND BLANK,
IMPORT,
RECALL,
INSERT-SQL И П р и СНЯТИИ ОТМеТКИ об у д а л е н и и
записи в режиме просмотра. Но при использовании триггеров имеются и ограничения: если ты пометил запись для удаления, а потом вдруг начал ее же модифицировать — тригге ры вызываться не будут. Убрать" триггер из таблицы проще простого — нужно очистить соответст вующее поле ввода или использовать команду DELETE TRIGGER. Как все это претворить в жизнь? Сначала о хранимой процедуре (рис. 13.10): открой окно конструктора таблиц (Table Designer) с таблицей countries и в поле Default value (Значение по умолчанию) введи следующее выражение: m y l a s t i d ("countries")
160
Часть I. Процедурное программирование в Visual FoxPro
Рис. 13.10. Вызов хранимой процедуры
А вот теперь попробуй ввести несколько значений. Ну как, получается?, А ты как думал! Эта же функция может успешно применяться и в других таблицах, напри-1 мер в таблице cities. В поле ввода Default value для этой таблицы следует указать myiastid ("cities") и вперед! А что у нас в таблице lastid? Смоге рим на рис. 13.11.
Рис. 13.11. В таблице l a s t i d хранятся последние значения идентификаторов
Практическое использование триггеров Да, признаюсь, здесь я не оригинален — подобный пример использования триггеров встречается во многих учебниках по программированию. Суть та-
Урок 13. Работа с базой данных
jgj
кая: неплохо бы вести какой-нибудь учет, например, сколько ты ввел новых записей, допустим, сегодня — кто знает, вдруг ты действительно отель от кроешь? Но сначала доведем "до ума" нашу базу данных, создав новые таб лицы со следующей структурой — табл. 13.6. В этой таблице будет храниться информация о клиентах, которые прожива ют в нашем отеле в настоящее время. Таблица 13.6. Names.dbf
Описание
Поля Idcountry
(i4)
Идентификатор страны
Idcity (i4)
Название
города
Ccountry (c30)
Название страны
Ccity (c30)
Название города
CFirstname (c30)
Имя
CSecondname (c30)
Фамилия
CLastname (c30)
Отчество
DBirthday (d8)
Дата рождения
CStreet (c30)
Улица
CHome (c5)
Дом
CRoom (c5)
Квартира
GPhoto (g)
Фотография
Csex (clO)
Пол
Darrdate (d8)
Дата приезда
Ddepdate (d8)
Дата отъезда
Idroom (i4)
Номер в отеле
MDescr (Memo)
Дополнительные сведения
А в таблице Depclients.dbf будет храниться информация обо всех клиентах, когда-либо проживавших в отеле (табл. 13.7). При "выписке" клиента дан ные о нем будут скопированы в эту таблицу из таблицы Clients.dbf. Таблица 13.7. Depclients.dbf
6
Поля
Описание
Idcountry (i4)
Идентификатор страны
Ccountry (сЗО)
Название страны
Зак Ю02
162
Часть I. Процедурное программирование в Visual FoxPro Таблица 13.7 (окончание)
Поля
Описание
Ccity (сЗО)
Название города
Idcity (i4)
Идентификатор города
CFirstname (сЗО)
Имя
CSecondname (сЗО)
Фамилия
С Lastname (сЗО)
Отчество
DBirthday (d8)
Дата рождения
CStreet (сЗО)
Улица
CHome (c5)
Дом
CRoom (c5)
Квартира
GPhoto (g)
Фотография
Csex (clO)
Пол
Darrdate (d8)
Дата приезда
Ddepdate (d8)
Дата отъезда
Ndays
Время проживания
Ncost
Стоимость проживания
Idroom (i4)
Номер в отеле
MDescr (Memo)
Дополнительные сведения
В таблице Rooms.dbf— информация о номерах нашего отеля (табл. 13.8). Таблица 13.8. Rooms.dbf
Поля
Описание
Idroom (Integer)
Номер (идентификатор гостиничного номера)
Idfloor (Integer)
Идентификатор этажа
Nprice (Numeric)
Стоимость проживания в сутки
Nplaces (Numeric)
Количество мест в номере
Ltv (Logical)
Наличие телевизора
Lphone (Logical)
Наличие телефона
В таблице Floors.dbf, как видно из ее названия, хранится информация об| этажах (табл. 13.9).
Урок 13. Работа с базой данных
163 Таблица 13.9. Floors.dbf
Поля Idfloor Cfloor
Описание (Integer) (Character)
Идентификатор этажа Описание этажа (первый, второй и т. д.)
А вот в таблице Todayrecords.dbf мы и будем вести ежедневный учет при бывших постояльцев (табл. 13.10). Таблица 13.10. Todayrecords.dbf Поля Icounter
Описание (i4)
DToday (d8)
Счетчик Дата
После определения соответствующих индексов и установки отношений на ша база данных будет выглядеть примерно так, как показано на рис. 13.12.
Рис. 13.12. База данных Oldfox
Часть I. Процедурное программирование в Visual FoxPro
164
Так, на чем мы остановились? А, использование триггера... Выбрав таблицу names, откроем окно Table Designer и перейдем на вкладку Table. Затем в поле ввода Insert trigger введем вызов функции newrecordso — рис. 13.13. Замечание В таблице todayrecords должна быть одна пустая запись.
Рис. 13.13. Использование триггера
Откроем окно редактирования хранимых процедур и введем следующий текст: PROCEDURE Newrecords SELECT Todayrecords REPLACE Icounter WITH Icounter+1 REPLACE Dtoday WITH DATE() SELECT Todayrecords RETURN .T.
Теперь посмотрим, как это все работает: переходим в рабочую область, в которой открыта таблица todayrecords, увеличиваем значение поля icounte на единицу, а в поле dtodae ставим текущую дату, используя функцию DATE (). Все просто, не так ли?
Урок 13. Работа с базой данных
165
Контроль достоверности ввода данных На вкладке Fields (Поля) диалогового окна Table Designer имеется область Field validation (Проверка ввода). В поле ввода Rule (Правило, условие) вводится логическое выражение, и если его результатом вычисления будет False (Ложь) — появляется выраже ние, указанное в поле Message (Сообщение). Например, при вводе значения в поле dbirthday (Дата рождения) таблицы names необходимо следить за тем, чтобы введенная дата не была больше да ты сегодняшней: действительно, новорожденные еще "туда сюда", но к чему нам "гости из будущего"?! Так вот (рис. 13.14): переходим на вкладку Fields, указываем поле dbirthday и в поле ввода Rule пишем dbirthday < DATE о, а в поле Message вводим текст с о о б щ е н и я Дата рождения не может быть датой из будущего! Все, на жимаем ОК.
Рис. 13.14. Определение условий достоверности ввода данных на уровне поля
Точно так же (с небольшими изменениями) можно задать хранимые про цедуры, триггеры и правила проверки и для других таблиц и полей. Ты спрашиваешь, для чего их вообще использовать? Ведь все эти проверки и прочее можно организовать, используя экранные формы? Естественно,
166
Часть I. Процедурное программирование в Visual FoxPro
можно. Но в этом случае мы ничего не сможем поделать с теми пользовате лями, которые решат редактировать данные в таблицах, минуя экранные формы — например, используя BROWSE ИЛИ командное окно. А используя эти функции, мы в любом случае сможем обеспечить ссылочную целостность. И еще: никто тебя не заставляет писать собственные процедуры (как было показано ранее). Referential Integrity Builder достаточно мощное и удобное средство, в большинстве случаев его применение более чем оправданно и достаточно. Но если ты решишь обрабатывать изменения данных не так, как это предусмотрено по умолчанию в Visual FoxPro — пожалуйста, как ты уже убедился, в этом нет ничего сложного. А теперь мы ненадолго оставим нашу базу данных и продолжим знакомство с экранной формой. Пусть тебя не удивляет такая "непоследовательность", действительно, во многих учебниках главы построены таким образом, что полностью раскрывают какую-то определенную тему. Но я считаю, что тебе будет понятней рассматривать процесс построения приложения именно так, максимально приблизившись к "боевым" условиям. Да и врачи советуют, что лучший вид отдыха — это смена вида деятельности.
/
УРОК 1 4
Экранная форма. Продолжение знакомства На данном уроке мы продолжим знакомство с элементами управления экранных форм, рассмотрим их назначение и свойства, научимся работать с различными построителями элементов управления.
Объект ListBox List в переводе с английского список. Источником данных для этого эле мента управления могут быть значения полей, элементы массивов, пункты меню, список значений и т. д. Всем этим хозяйством управляет свойство RowSourceType (Тип источника данных), возможные значения которого при ведены в табл. 14.1. Таблица 14.1. Значения свойства RowSourceType Значение
Тип источника данных
0 (None)
Значение определяется программно
1 (Value)
Список значений задается в виде строки, элементы которой отделяются друг от друга запятыми
2 (Alias)
Источник данных — таблица
3 (SQL-Statement)
Источник данных — результат SQL-оператора
4 (Query)
Источник данных — результат запроса
5 (Array)
Источник данных — массив
6 (Fields)
Значения элементов списка являются значениями полей таблицы
7 (Files)
Значения элементов списка — перечень файлов
8 (Structure)
Источник данных — структура таблицы
9 (Popup)
Источник данных — пункты Рорир-меню
168
Часть I. Процедурное программирование в Visual FoxPro
Пример использования Создадим новую форму, в которой расположим объект ListBox, воспользо вавшись для этого панелью Form Controls (рис. 14.1).
Рис. 14.1. Экранная форма с размещенным в ней объектом L i s t B o x
При создании или редактирования объекта ListBox можно использовать по-| строитель (Builder), вызываемый нажатием кнопки на соответствующей команде контекстного меню. Рассмотрим этот вопрос более подробно (рис. 14.2).
Рис. 14.2. Вкладка List Items окна построителя List Box Builder
Урок 14. Экранная форма. Продолжение знакомства
169
На вкладке List Items (Список объектов) необходимо задать тип источника данных для заполнения списка. Тип источника указывается в раскрываю щемся списке Fill the list with, в котором доступны следующие значения: • Fields from a table or view (Поля из таблицы или представления данных); • Data entered by hand (Источником данных является список значений); • Values from an array (Источником данных является массив). Мы будем использовать первое значение, и при этом в списке Databases and tables (Базы данных и таблицы) нужно указать таблицу, поля которой будут являться источником данных. Выбрав таблицу, мы увидим список ее полей в списке Available fields (Имеющиеся поля). При помощи кнопок со стрелками перенесем необхо димые поля в область Selected fields (Выбранные поля). А вот в том случае, когда мы укажем в качестве источника данных массив, внешний вид вкладки List Items изменится (рис. 14.3).
Рис. 14.3. Вкладка List Items окна построителя при установленном значении Values from an array
В поле ввода Array Name указывается имя массива. Если массив использует ся не весь — ставим переключатель в положение Range of the array и указы ваем диапазон значений. Вернемся к нашему случаю. После задания необходимых параметров на вкладке List Items перейдем к следующей вкладке — Style (Стиль) (рис. 14.4). Здесь мы видим две группы переключателей: • Three-dimensional (Трехмерный) — позволяет придать объекту эффект объемности; • Plain (Плоский) — объект отображается плоским;
170
Часть I. Процедурное программирование в Visual FoxPro
• Yes, enable incremental searching (Да, возможен поиск) — означает, что при вводе каждой буквы будет осуществляться поиск подходящего зна чения из списка; • No, don't enable incremental searching (Нет, поиск не возможен) — при вводе букв никакого поиска, соответственно, не будет.
Рис. 14.4. Вкладка Style окна построителя List Box Builder
Счетчик Rows to display (Отображение строк) позволяет задать количество одновременно показываемых значений списка. Разобравшись с этой вкладкой, двигаемся дальше на вкладку Layout (Распо ложение) (рис. 14.5).
Рис. 14.5. Вкладка Layout окна построителя List Box Builder
Урок 14. Экранная форма. Продолжение знакомства
у 77
Расположенный на данной вкладке флажок Adjust the width of the list box to display all columns автоматически увеличивает ширину списка для отображе ния всех колонок. Ширину каждой колонки можно изменить вручную, установив мышь на границу между ними и "растянув" колонку до необходимого размера. И, наконец, последняя вкладка нашего построителя — Value (Значение) (рис. 14.6).
Рис. 14.6. Вкладка Value окна построителя List Box Builder
Эта вкладка используется для того, чтобы задать источник данных. В окне Properties (Свойства) за это отвечает свойство controisource. Закончив "строительство", нажмем ОК и вернемся к Конструктору форм. Выделим наше поле ввода Texti, а в окне свойств дважды щелкнем на ме тоде Keypress (Нажатие клавиши), после чего в открывшемся окне редакти рования процедур напишем следующий код — рис. 14.7. nKeycode — это параметр, передаваемый методу Keypress (Нажатие клави ши). Если нажата клавиша <Enter> (13 — это ее код), выполняется провер ка, не является ли значение данного поля ввода пустой строкой — функция EMPTY о возвращает истину, если в данном поле нет данных. Если условие верно, в таблицу добавляется новая пустая строка и заполняется значения ми поля ввода формы. Затем поле ввода снова очищается. Таким образом, Мы можем заполнять наш справочник, вводя название стран в соответст вующее поле ввода и нажимая клавишу <Enter>. По умолчанию в объекте ListBox отображается восемь значений, а если их будет больше — в нем появится линейка прокрутки.
172
Часть I. Процедурное программирование в Visual FoxPro
Рис. 14.7. Код для заполнения таблицы
Раскрывающийся список (ComboBox) Этот элемент мы уже видели в главном окне Visual FoxPro, именно в нем отображается открытая база данных. Данный элемент управления часто применяется в экранных формах, и, естественно, мы никак не можем щ обратить внимание на сей объект. Можно сказать, что ComboBox является более "продвинутым" братом-близнеиом объекта ListBox — так много у них общего. Данный объект, как и обычный список, имеет собственный построитель (Builder) для определения и редактирования источника данных и других свойств. Использование построителя для раскрывающегося списка практи чески идентично использованию построителя для обычного списка, поэтому мы не будем на нем останавливаться. Вместо этого мы определим свойства данного элемента управления с помощью окна Properties (Свойства). Давай откроем форму, на которой у нас размещен ListBox, выделим его и удалим, нажав клавишу
Урок 14. Экранная форма. Продолжение знакомства
Рис. 14.8. Мы заменили в форме простой список на раскрывающийся
173
Рис. 14.9. Форма с раскрывающимся списком
Видишь, нам даже не пришлось изменять код для события Keypress для по ля ввода новых значений. Это наглядно демонстрирует сходство между ComboBox И ListBox.
Теперь рассмотрим тот случай, когда в качестве источника данных выступа ет не таблица, а список значений. Уберем таблицу из среды данных (Data Environment) нашей формы. Свойство RowSourseType определим равным i (Value, Значение). Свойство Controisourse примем равным None (Нет). А вот в RowSourse занесем через запятую список значений.
Переключатели (OptionGroup) Эти элементы называются переключателями, потому что они могут прини мать только одно из нескольких значений поля или переменной. То есть когда один из них включен, другие, входящие в эту группу переключателей, выключены. Их еще иногда называют радиокнопками — раньше на старых радиоприемниках применялись подобные устройства, правда, механические. Объект OptionGroup является контейнером, т. е. состоит из нескольких эле ментов, обладающих определенными свойствами. Создадим новую экранную форму и разместим на ней элемент управления OptionGroup, воспользовавшись соответствующей кнопкой на панели Form Controls (рис. 14.10).
Рис. 14.10. По умолчанию объект O p t i o n G r o u p состоит из двух элементов
174
Часть I. Процедурное программирование в Visual FoxPro
Вызовем контекстное меню для этого элемента управления и посмотрим, как работает построитель для группы переключателей — рис. 14.11.
Help
I
OK
Cancel |
Рис. 14.11. Вкладка Buttons окна построителя Option Group Builder
Счетчик Number of buttons определяет количество элементов в группе пере ключателей. Переключатели Standard и Graphical позволяют определить "внешний вид" элементов. Standard (Стандартный) — обычный для этого объекта вид (см. рис. 14.10), Graphical (Графический) — элементы отображаются в виде кно-| пок. В расположенной ниже таблице можно определить надпись для каждого элемента (Caption) и, если нужно, изображение (Graphic). Теперь перейдем на вторую вкладку окна Option Group Builder — Layout (Расположение), которая позволяет задать параметры отображения объектов (рис. 14.12): • Button layout (Vertical, Horizontal) — отвечает за расположение элементов в группе: вертикально (по умолчанию) или горизонтально; • Spacing between buttons (in pixels) — определяет расстояние между эле ментами в пикселах; • Border style (Single, None) — определяет, будет ли группа переключателей иметь обрамление в виде одинарной линии (Single) или вообще обрамле ния не будет. На последней, третьей вкладке Value (Значение) можно определить таблицу и поле, в которое будут заноситься значения элементов. В окне свойств j Properties за это отвечает свойство controisource (Источник данньгх).
Урок 14. Экранная форма. Продолжение знакомства
175
Рис. 14.12. Вкладка Layout окна построителя Option Group Builder
Рис. 14.13. Вкладка Value окна построителя Option Group Builder
В качестве примера давай создадим группу переключателей, состоящую из четырех элементов, и таблицу, поле которой может принимать одно из че тырех значений (рис. 14.14). При выборе одного из элементов соответствующее значение будет занесено в поле таблицы. А вот на рис. 14.15 приведен пример графического стиля отображения эле мента OptionGroup. Естественно, все эти свойства, а также и другие (цвет и т. д.) доступны в °кне Properties (Свойства). Для того чтобы "добраться" к элементам данного
Часть I. Процедурное программирование в Visual FoxPro
176
объекта, необходимо щелкнуть на нем правой кнопкой мыши — только так ты получишь доступ к его "внутренностям". Это относится и к другим объ ектам-контейнерам.
Рис. 14.14. Использование O p t i o n G r o u p для занесения значения в таблицу (режим Standard)
Рис. 14.15. Использование O p t i o n G r o u p Для занесения значения в таблицу (режим Graphical)
Контейнер (Container) А вот и сам контейнер. Как ясно из названия, перед нами самый настоящий контейнер, в который можно включать различные элементы управле ния. Данный объект очень широко используется при создании классов — на его основе можно соорудить такие элементы, как группа командных кнопок, progressBar (Индикатор) и многое другое. В экранных формах он так же частенько применяется, например, на рис. 14.16 представлен фрагмент экранной формы с тремя контейнерами. Свойство speciaiEffect у первого равно 2 (Плоский), у второго — 1 (Утопленный), у третьего — о (Выпук лый).
Рис. 14.16. Фрагмент экранной формы стремя контейнерами
Счетчик (Spinner) Счетчик применяется для ввода числовых значений. К сожалению, для него не предусмотрен построитель, поэтому для определения его свойств тебе придется часа четыре двигать мышью (шутка). Поместив объект на форме, открываем окно Properties (Свойства) и начи^ наем творить: 1. Используя уже знакомое нам свойство controisource (Источник данных) определяем поле, для которого, собственно, и нужен счетчик. Смотри, поставь поле Character!
Урок 14. Экранная форма. Продолжение знакомства
177
2. Теперь необходимо задать максимальное и минимальное значения для с ч е т ч и к а — с о о т в е т с т в е н н о с в о й с т в а SpinnerHighValue И SpinnerMinValue.
3. В предыдущем пункте мы определили максимальное и минимальное допустимые значения, которые вводятся с использованием стрелок счет чика. Но значения можно вводить и с клавиатуры, поэтому для та кого случая определим дополнительно значения следующих свойств — KeyboardHighValue И KeyboardMinValue.
4. Определим шаг, с которым изменяется значение поля, воспользовавшись СВОЙСТВОМ I n c r e m e n t .
Но счетчик, кстати, можно использовать и для других целей. Например, пользователь не может изменить размер кнопок, а ему это ну очень надо! Так сделай ему счетчик рядом с кнопкой, определи максимально допусти мые значения, допустим, для ширины кнопки, а для события interactiveChange запиши следующее: THISFORM.Commandl.WIDTH=THIS.VALUE THISFORM.Commandl.REFRESH()
Вот и пусть изменяет... Пошутили, расслабились — поехали дальше!
Группа вкладок (PageFrame) Вкладки используются в основном тогда, когда на форме предполагается разместить большое количество объектов и каким-то образом их сгруппи ровать. Создадим новую форму, которая будет входить в состав нашего приложе ния, и разместим на ней три вкладки. Вкладки располагают на форме сле дующим образом: выбирается соответствующая кнопка на панели Form Controls, затем мышью обводится контур необходимого размера. По умол чанию при встраивании вкладок в экранную форму их число равняется Двум. Вкладки не имеют своего построителя, и вся настройка осуществляет ся при помощи окна Properties (Свойства). Более того, объект PageFrame также является контейнером и содержит в контекстном меню пункт Edit (Редактировать). Разместив в нашей форме вкладки, увеличим их число до трех, изменив значение свойства PageCount в окне Properties (рис. 14.17). Как видишь, у нас появились три вкладки, имеющие заголовки Pagel, Page2, Page3. Кстати, эти объекты имеют и такие же имена. Изменим заго ловки вкладок — для этого щелкнем правой кнопкой на объекте PageFramel
178
Часть I. Процедурное программирование в Visual FoxPro
и выберем пункт Edit контекстного меню. После этого станет возможным переключение между вкладками и определение свойств для каждой из них. Первое, что мы сделаем — изменим значение свойства caption (рис. 14.18).
Рис. 14.17. Размещение вкладок на форме
Рис. 14.18. Изменение заголовков вкладок
Теперь поговорим о размещении объектов на вкладках. Правило здесь такое — не забывать включать режим Edit из контекстного меню, иначе раз мещаемый объект "вставится" не на нужную вкладку, а на сам объект; PageFrame.
Урок 14. Экранная форма. Продолжение знакомства
179
Вот и давай разместим на первой вкладке три "утопленных" контейнера. Для этого в режиме Edit перейди на первую вкладку (если она не открыта — это происходит по умолчанию) и размести необходимые объекты. Можешь поставить туда только один контейнер, определить необходимые свойства, а затем, воспользовавшись командами копирования и вставки, добавить ос тальные (рис. 14.19).
Рис. 14.19. Размещение объектов на вкладках
Флажок (CheckBox) Элемент управления в виде флажка используется, когда значение поля мо жет иметь только одно из двух значений. Ты догадался, о чем это я говорю? Ну конечно, речь идет о полях типа Logical, ведь именно они могут иметь только два возможных значения — "Истина" (True) и "Ложь" (False). При Установке флажка значение в поле будет "Истина", а при сбросе — "Ложь", 'фоцесс размещения данного объекта в форме сводится к следующему: '• Размещаем его на форме, воспользовавшись соответствующей кнопкой на панели Form Controls.
180
Часть I. Процедурное программирование в Visual FoxPro
2. Определяем источник данных controisource — понятно, что это должно б ы т ь ПОЛе L o g i c a l
3. Определяем надпись для данного элемента — свойство Caption. Пример объекта спесквох, помещенного на форму, представлен на рис. 14.20.
Рис. 14.20. Пример объекта CheckBox
Линия (Line) Ну, линия — она и есть линия. Объект, скажем прямо, декоративный. Для) размещения линии в форме нужно воспользоваться соответствующей кно...| Слушай, тебе не надоело читать каждый раз про кнопку? Я думаю, ты уже и так на всю жизнь запомнил, как "вставить" в форму тот или иной объект. В общем, переходим сразу к сути: устанавливаешь указатель мыши в начало линии и тащишь на необходимое расстояние. В Paint рисовал? Вот-вот, почти то же самое. А когда линия уже нарисована, определяем ее свойства: | • толщина линии определяется значением Borderwdth; •
ц в е т о м "заведует" B o r d e r C o l o r ;
• чтобы более точно задать длину линии, используется свойство width для| горизонтальной линии и Height — для вертикальной. Они же "регулиру ют" угол наклона линии; • стиль отображения указывается с помощью свойства Borderstyle, кото рое может иметь значения, перечисленные в табл. 14.2. Таблица 14.2. Значения свойства Borderstyle Значение Borderstyle
Стиль
0 — Transparent
Прозрачная линия
1 - Solid (Default)
Просто тонкая линия
2 - Dash
Штрих
3-Dot
Пунктир
4 — Dash-Dot
Штрихпунктир
5 - Dash-Dot-Dot
Штрих-двойной пунктир
6 — InsideSolid
Непрерывная линия
/
Урок 14. Экранная форма. Продолжение знакомства
181
Но т. к. наш Лис является натурой творческой — было бы наивно думать, что его "художества" ограничиваются только рисованием примитивных ли ний. Нет! Немного фантазии, и Лис запросто выдаст нечто в стиле "матема тического сюрреализма". Делаем простейшую форму с двумя полями ввода и двумя кнопками. В коде события click одной из кнопок пропишем сле дующий код — листинг 14.1. Листинг 14.1. Событие C l i c k DECIA X ( 4 0 0 ) , Y ( 4 0 0 ) FOR I = 1 TO 360 FOR K=l TO 200 Z=6.6832*1/360 X ( I ) = 120+90*SIN(5*Z)*COS(THISFORM.TEXT1.VALUE*Z) Y d ) = 120+90*COS(5*Z)*SIN(THISFORM.TEXT2.VALUE*Z) THISFORM.CURRENTX=X(I) THISFORM.CURRENTY=Y(I) THISFORM.PRINT ( " ( ( * ) ) " ) ENDFOR ENDFOR
Задавая в полях ввода различные значения, рисуем "картинки" (рис. 14.21 и 14.22).
Рис. 14.21. Лис в качестве художника (значения 60, 1)
Рис. 14.22. Лис в качестве художника (значения 5, 1)
182
Часть I. Процедурное программирование в Visual FoxPro
Контур (Shape) Расположив в необходимом месте экранной формы контур, настраиваем его свойства: •
цвет ф о н а — BackColor;
• Прозрачность — BackStyle; •
СТИЛЬ рамКИ — B o r d e r S t y l e ;
• эффект объемности — SpecialEffeet; • изгиб — curvative (значения от 1 до 99); • цвет узора — Fiilcoior; • сам узор, заполнение — свойство Fiiistyie, которое может принимать) несколько значений (табл. 14.3). Таблица
14.3. Значения свойства Fiiistyie
Значение F i i i s t y i e
Узор
0 - Solid
Сплошная заливка
1 — Transparent(Default)
Без заливки
2 — Horizontal Line
Горизонтальная штриховка
3 — Vertical line
Вертикальная штриховка
4 — Upward Diagonal
Штриховка по диагонали слева направо
5 — Downward Diagonal
Штриховка по диагонали справа налево
6 — Cross
Крестик (горизонтально-вертикальная штриховка)
7 — Diagonal Cross
"Косой" крестик
Пример объекта shape, помещенного на форму, представлен на рис. 14.23.
Рис. 14.23. Пример объекта Shape
Урок 14. Экранная форма. Продолжение знакомства
183
Изображение (Image) Элемент управления image предназначен для размещения в экранной форме изображений (рис. 14.24). Непосредственно за само изображение отвечает свойство Picture, в котором нужно указать путь к графическому файлу. Помнишь, мы использовали данное свойство для экранной формы? Разме щаем объект, указываем путь к файлу и производим настройку других свойств, а именно свойства stretch, которое может принимать следующие значения: О Clip (Обрезать) — картинка сохраняет свои размеры; О Isometric (Изменить, сохранив форму) — картинка занимает весь объект image, причем пропорционально изменяет свои размеры; О Strech (Изменить, заполнив рамку) — картинка занимает весь объект image, но размеры не меняет.
Рис. 14.24. Размещение изображения в форме
Таблица (Grid) Объект Grid используется для отображения данных в табличной форме. С первого взгляда он похож на таблицу в режиме просмотра Browse, но это только с первого. Данный элемент управления представляет собой объектконтейнер, включающий в себя несколько объектов. Об объектах, входящих в состав Grid, поговорим позже, а сейчас начнем создавать этот элемент при помощи построителя. Откроем в окне конструктора форм нашу форму с вкладками. Разместим при объекта Grid в ранее созданных контейнерах. Но начнем, естественно, с одного.
184
Часть /. Процедурное программирование в Visual FoxPro
После расположения его внутри первого контейнера выберем команду Builder контекстного меню (рис. 14.25). Ну и как всегда в таких случаях, происходит запуск построителя (рис. 14.26).
Рис. 14.25. Размещение в форме объекта G r i d и вызов построителя
Окно Grid Builder (Построитель таблицы) содержит четыре вкладки, первую из которых мы и видим в данный момент. Она называется Grid Items (Элементы) и здесь мы можем сформировать список полей, которые будут раз мещены в нашем объекте. Для этого в раскрывающемся списке Databases and tables (Таблицы и базы данных) укажем нашу базу данных oidFox, после чего внизу отразится список имеющихся в базе данных таблиц. Выбрав не обходимую таблицу, мы увидим список полей данной таблицы в области AvaiJables fields (Имеющиеся поля). При помощи кнопок со стрелками пе ренесем те поля, которые мы хотим разместить в Grid, в область Selectee fields (Выбранные поля). На этом работу с первой вкладкой построителе можно считать законченной, и мы переходим ко второй — Style (Стиль) (рис. 14.27). Данная вкладка используется для задания стиля отображения данных в таблице. Всего имеется пять различных стилей. Рядом расположено окно npeкварительного просмотра. Выбрав желаемый, переходим к третьей вкладке Layout (Расположение) (рис. 14.28).
Урок 14. Экранная форма. Продолжение знакомства
185
Рис. 14.26. Первый шаг работы построители Grid Builder
Рис. 14.27. Вторая вкладка построителя Grid Builder
По умолчанию заголовки столбцов совпадают с их именами. Ясно, что это н е всегда удобно. Для переопределения заголовка используется поле ввода Caption (Наименование). Раскрывающийся список Control type (Тип эле мента управления) содержит список объектов, которые могут отображаться в этом столбце. Некоторые из них в данный момент недоступны — это зав исит от типа поля.
186
Часть I. Процедурное программирование в Visual FoxPro
Рис. 14.28. Третья вкладка построителя Grid Builder
Открываем последнюю, четвертую вкладку построителя — Relationship (От ношения).
Рис. 14.29. Четвертая вкладка построителя Grid Builder
Здесь можно указать ключевое поле для главной (родительской) таблицы и индекс подчиненной (дочерней). Это, как ты уже догадался, применяется при создании объекта Grid для многотабличных форм. Закончив манипуляции с построителем, разместим на вкладке нашей формы надписи и поле ввода для добавления записей в таблицу, расположив его ниже объекта Grid (рис. 14.30).
Урок 14. Экранная форма. Продолжение знакомства
187
Рис. 14.30. Мы расположили в форме справочник стран в виде объекта G r i d
Для события Keypress объекта Text 11 запишем код из листинга 14.2. Листинг 14.2. Добавление записей в таблицу LPARAMETERS N k e y c o d e , N s h i f t a l t c t r l IF N k e y c o d e = 1 3 && ЭТО КОД КЛАВИШИ ENTER DO CASE CASE EMPTY ( T h i s . V a l u e ) = . F . SELECT C o u n t r i e s APPEND BLANK REPLACE C c o u n t r y WITH T h i s . V a l u e This.Value="" _SCREEN.ACTIVEFORM.REFRESH() ENDCASE ENDIF
Теперь рассмотрим создание объекта Grid "вручную", без использования по строителя. Сделаем Grid, отображающий справочник городов. Для этого от кроем нашу форму в конструкторе форм, щелкнем мышью на объекте p ageFramei, и войдем в режим редактирования, воспользовавшись соответст вующей командой контекстного меню (Edit). Выбрав на панели инструмен тов кнопку Grid, разместим наш объект во втором контейнере (рис. 14.31) и начнем настройку его свойств, используя окно Properties (Свойства). Перейдем на вкладку Layout окна Properties. За отображение числа столбцов (Column) отвечает свойство coiumncount. По умолчанию данное свойство имеет значение -1 (поэтому в таблице поначалу как бы ничего и нет). Так как нам нужен всего один столбец, в котором будут отображаться только названия городов, мы установим данное свойство равным единице. Источ ником данных для нашего объекта будет таблица со списком городов cities. Для того чтобы определить источник данных, перейдем на вкладку Data окна Properties и зададим значение для свойства RecordSource (Источник данных) (рис. 14.32).
188
Часть I. Процедурное программирование в Visual FoxPro
Рис. 14.31. Мы встроили в экранную форму еще один G r i d
Рис. 14.32. Определение источника данных для объекта G r i d
Как я уже и говорил, объект Grid включает в себя несколько объектов, т. e.j является контейнером. Нажми на кнопку в раскрывающемся списке окна Properties и ты увидишь, какие именно объекты входят в состав нашего Grid] (рис. 14.33).
Рис. 14.33. В состав G r i d входит несколько объектов
Column — это столбец. Кроме уже известного нам Coiumncount, данный объ-| ект имеет множество других свойств. Рассмотрим некоторые из них: • controisource — определяет источник данных для столбца; • Alignment — выравнивает информацию в столбце; • coiumnOrder — определяет порядок отображения столбцов; • Backcolor — определяет цвет фона. Используя эти, а также и другие свойства, можно для всего столбца зада цвет фона, цвет шрифта, размер шрифта и прочие параметры. /
урок 14. Экранная форма. Продолжение знакомства
189
Объект Header — это не что иное, как заголовок столбца. По умолчанию он называется так же, как и соответствующее поле таблицы, но заголовок можно легко изменить, задав значение свойства caption. Объект Text — это тот элемент управления, который определяет, в каком виде будет выводиться информация. В данном случае это обычное поле ввода. В Grid для отображения информации могут использоваться такие элементы управления, как счетчик (spiner), флажок (checkbox), поле редак тирования (EditBox), раскрывающийся СПИСОК (ComboBox). Таким образом, настроив необходимые свойства для нашего второго объек та Grid, добавим в форму поле ввода, с помощью которого будем добавлять в справочник городов новые наименования. Код для события Keypress будет такой же, как и в предыдущем случае (см. листинг 14.2), только вместо таб лицы стран нужно указать таблицу городов cities и, соответственно, изме нить название поля в команде Replace. А теперь самостоятельно добавь в третий контейнер экранной формы еще один Grid, в котором будет располагаться справочник улиц. Также не забудь добавить поле для ввода нового значения. После того как ты это сделаешь, посмотри на рис. 14.34. Именно такая форма (или почти) у тебя может по лучиться, если добавишь еще несколько объектов.
Рис. 14.34. Первая вкладка формы для ввода данных
Часть I. Процедурное программирование в Visual FoxPro
190
Ну и что теперь делать? Как все это будет работать? Сейчас разберем. Во-первых, для полей ввода, отвечающих за ввод фамилии, имени, отчест ва, даты рождения и дополнительной информации о клиенте, необходимо в качестве источника данных назначить соответствующие переменные памя ти. Их имена будут совпадать с именами полей таблицы Names.dbf за одним лишь исключением — перед именем поля необходимо ставить префикс т. А вот в качестве источника данных для полей, указывающих страну, город и улицу, укажем не переменные памяти, а сами имена полей из соответст вующих таблиц. Да еще и сделаем данные поля доступными только для чтеНИЯ (ReadOnly=.T.).
Посмотрим, как будет работать форма на этом этапе? Давай только еще не много отредактируем свойства наших элементов Grid. Конкретно нас инте ресует событие AfterRowCoichange, которое наступает после того, как мы перейдем на другую строчку Grid. Так вот, в первом объекте Grid (где страны) для данного события пишем следующий код: THISFORM.REFRESH()
&& после перехода на другой ряд Grid && форма просто перерисовывается с новыми данными.
Для второго Grid (Города): THISFORM.PAGEFRAME1.PAGE1.ТЕХТ5.REFRESH()
То есть во втором случае мы только обновляем информацию для поля ввода Text5.
Ну и почти то же самое для третьего Grid: THISFORM.PAGEFRAME1.PAGE1.TEXT6.REFRESH()
А сейчас мы сделаем программу, которая будет запускать наше будущее приложение. Для этого в окне диспетчера проекта перейди на вкладку Code (Код) и выбери пункт Programs (Программы). Нажми кнопку New (Новая). В открывшемся окне напиши код из листинга 14.3. Листинг 14.3. Программа для запуска SET TALK OFF SET ECHO OFF SET DATE TO GERMAN SET PATH TO C:\OLDFOX\ OPEN DATABASE Oldfox USE Names IN 1 EXCLUSIVE USE Depclients IN 2 EXCLUSIVE DO FORM Main && Main - это название файла нашей формы
Урок 14. Экранная форма. Продолжение знакомства
191
Вот и все. Сохрани эту программу под любым именем, и теперь можешь попробовать запустить форму на выполнение и позаполнять наши справоч ники. Сначала заполняется справочник стран — тут все просто, в поле вво да набираешь название и нажимаешь <Enter>. Затем, указав в этом Grid нужную страну, также заносишь данные в справочник городов для этой страны. Указав город, заносим название улиц этого города. Таким образом, у нас уже имеется форма с тремя связанными и, что совсем уже удивительно, работающими объектами Grid. Ну а как же все-таки добавлять записи в таблицу names, где у нас "фамилии, пароли, явки" и т. д.? Кнопка Новая запись может иметь примерно такой программный код для события click — листинг 14.4. Листинг 14.4. Код события C l i c k для кнопки Новая запись SELECT names && переходим в рабочую область с таблицей names.dbf SCATTER MEMVAR BLANK && создаем переменные памяти THISFORM.REFRESH() && обновляем информацию в экранной форме
Ничего сложного. Немного сложнее с кнопкой Сохранить (листинг 14.5). Листинг 14.5. Код события c l i c k для кнопки Сохранить SELE Names APPEND BLANK GATHER MEMVAR REPLACE I d c o u n t r y WITH C o u n t r i e s . I d c o u n t r y ; Ccountry WITH C o u n t r i e s . C c o u n t r y REPLACE C s t r e e t WITH S t r e e t s . S t r e e t REPLACE I d c i t y WITH C i t i e s . I d c i t y , C c i t y WITH C i t i e s . C c i t y REPLACE Idrooms WITH Rooms.Idroom I E THISFORM.Pageframel.Pagel.Optiongroupl.Optionl.Value=l REPLACE Csex WITH "M" ELSE UEPLACE Csex WITH "Ж" ENDIF
Но очевидно, что здесь необходимо каким-то образом предотвратить воз можность ввода пустых записей в таблицу names. Один из вариантов — про ить значения полей ввода. Например, вот так — листинг 14.6.
192
Часть I. Процедурное программирование в Visual FoxPro
Листинг 14.6. Проверка значения полей ввода IF EMPTY(THISFORM.Pageframel.Pagel.Textl.Value) -> = MESSAGEBOX("УКАЖИТЕ ФАМИЛИЮ КЛИЕНТА", "ОШИБКА...") ELSE ... <приведенный ранее код>... END IF
Как ты уже догадался, здесь Лис проверяет — а не забыл ли пользователь] ввести фамилию клиента? Аналогичным способом можно осуществить про верку и других полей. На второй вкладке нашей формы мы расположим информацию о тех кли4 ентах, которые проживают в нашем отеле в настоящий момент (рис. 14.35).
Рис. 14.35. Вторая вкладка нашей формы
На третьей вкладке мы поместим информацию о клиентах, которые выех< из нашего отеля. Здесь мы можем расположить как общий список клиенте так и некоторую дополнительную информацию: номер, в котором клие | жил, даты прибытия и выезда, стоимость проживания. Возможно, это 6yJ выглядеть так — рис. 14.36. /
Урок 14. Экранная форма. Продолжение знакомства
193
Рис. 14.36. Третья вкладка экранной формы
по нас в данный момент интересует совсем Другое обстоятельство — а от куда взялись записи в таблице с выбывшими клиентами (Depclients.dbf)? па второй вкладке нашей экранной формы есть кнопка Удалить запись. о нашем случае это будет означать, что при щелчке на этой кнопке запись о клиенте удаляется из таблицы names (клиент выехал) и добавляется в ар хив — таблицу depciients (листинг 14.7). Листинг 14.7. Код заполнения таблицы d e p c i i e n t s Объявляем локальную переменную (стоимость проживания в номере за сутки) LOCAL Nroomprice *переходим в рабочую область с таблицей rooms SELЕСТ Rooms * в таблице rooms переходим на запись с тем номером, где проживает клиент LOCАТЕ FOR Idroom=Names.Idrooms * присваиваем соответствующее значение нашей переменной Nroomprice=Rooms .Nprice * т е п е р ь переходим в таблицу names SELECT Names
194
Часть I. Процедурное программирование в Visual FoxPro
* создаем переменные памяти, в которых находится вся информация о текущей записи SCATTER MEMVAR MEMO * помечаем запись на удаление DELETE * переходим в рабочую область с таблицей depclients SELECT Depclients * добавляем пустую запись APPEND BLANK * заполняем ее значениями из таблицы names GATHER MEMVAR MEMO * производим замену значения даты выезда на сегодняшнюю дату REPLACE Ddepdate WITH DATE() * вычисляем количество прожитых в номере дней REPLACE Ndays WITH Ddepdate-Darrdate * вычисляем полную стоимость проживания REPLACE Ncost WITH Ndays*Nroomprice * опять переходим в область с таблицей names SELECT Names * удаляем запись PACK * обновляем информацию в экранной форме THISFORM.REFRESH()
Тут поневоле вспоминаются триггеры и хранимые процедуры — ведь весь этот код можно было (с небольшими изменениями) занести в контейнер базы данных в виде триггера удаления. И еще одно дополнение — данный метод подходит в том случае, когда нам нужно "выселить" клиента раньше срока, ну допустим, кому-то срочно нужно выехать домой. А как быть с ос тальными? Не искать же по всей базе данных (а в твоем пятизвездочном отеле уже ежедневно проживает по 15 тыс. человек) тех, у кого дата предпо лагаемого выезда совпадает с сегодняшним числом! Конечно, нет. Доста точно немного изменить код и наша программа сама при каждом запуске будет удалять из базы данных необходимые записи (листинг 14.8). %
Листинг 14.8. Измененный код заполнения таблицы d e p c l i e n t s SELECT Names SCAN FOR Ddeptdate=DATE () LOCAL Nroomprice SELECT Rooms LOCATE FOR Idroom=Names.Idrooms Nroomprice=Rooms.Nprice
Урок 14. Экранная форма. Продолжение знакомства
195
SELECT Names SCATTER MEMVAR MEMO DELETE SELECT Depclients APPEND BLANK GATHER MEMVAR MEMO REPLACE Ndays WITH Ddepdate-Darrdate REPLACE Ncost WITH Ndays*Nroomprice SELECT Names ENDSCAN PACK THISFORM.REFRESH ()
А если этот код еще и поместить в метод i n i t нашей формы, то все полу чится именно так, как мы задумали. Но при этом есть и грустный мо мент — посмотри теперь на нашу форму (рис. 14.37).
Рис. 14.37. Вид формы изменился при модификации кода приложения
Что случилось? Почему вместо Grid мы теперь видим какую-то белую "дыру? А это результат использования команды PACK. Более того, я тебя сейчас
196
Часть I. Процедурное программирование в Visual FoxPro
еще обрадую — тот же эффект мы будем наблюдать каждый раз, когда бу! дем удалять записи из таблицы, являющейся источником данных для объек-3 та Grid. Избежать этого довольно просто, нужно сделать следующее: перед использованием команды удаления необходимо "очистить" источник данных для Grid, а потом восстановить его (листинг 14.9). Листинг 14.9. Очистка и восстановление G r i d
SELECT Names THISFORM.Pageframel.Page2.Gridl.Recordsource=.NULL. PACK THISFORM.Pageframel.Page2.Gridl.Recordsource="NAMES"
И еще одно замечание по этому поводу: в восстановленном объекте Gril столбцы будут отображаться в том порядке, в котором были расположена поля при создании таблицы. Отсюда вывод — если порядок отображения нА соответствует желаемому, можно модифицировать таблицу, изменив поря док следования полей. Если же это невозможно, то следует назначать ис точник данных не для всего Grid, а отдельно для каждого столбца.
/
урок 15
Выборка, упорядочение и просмотр данных Итак, что мы имеем? У нас есть база данных, есть несколько таблиц, есть экранная форма и, наконец, есть сами данные. А что мы умеем? Мы умеем заносить в базу данных новые записи и, соответственно, удалять какиенибудь из них. Что ж, для начала не так уж и плохо. Но ведь мы знаем, что основное назначение системы управления базами данных — это быстрый поиск и предоставление пользователю тех записей, которые удовлетворяют заданным условиям. Вот именно этому, читая данную главу, мы сейчас и будем учиться. Для того чтобы из таблицы выбрать данные, ее сначала нужно открыть. Каж дая таблица, независимо от того, входит ли она в контейнер базы данных или является свободной таблицей, открывается в своей рабочей области. Принято считать, что в Visual FoxPro имеется 32 627 рабочих областей, в каждой из которых может храниться таблица и соответствующие ей индек сы. И что все эти таблицы можно открыть одновременно. Это так, но на самом деле рабочих областей еще больше. Дело в том, что если мы будем использовать приватные сеансы данных (private data session), то 32 627 рабочих областей будут доступны в каждом сеансе! Открыть таблицу (а сейчас мы говорим о свободных таблицах) можно, ис пользуя команду USE. Например, вот так: USE ROOMS. При этом таблица rooms будет открыта в первой рабочей области. После применения USE FLOORS В первой области у нас окажется таблица floors, a rooms соответственно будет закрыта. А как их использовать одновременно? Для этого в команде USE необходимо указать, в какой именно рабочей области будет открыта таб лица: USE ROOMS IN 1 USE FLOORS IN 2
Вот и все. Теперь для перехода к нужной таблице достаточно использовать уже знакомую нам команду SELECT и указать номер рабочей области:
198
Часть I. Процедурное программирование в Visual FoxPro
SELECT 2 BROWSE
Но гораздо удобнее использовать не номер рабочей области, а псевдоним или алиас (alias) таблицы. Псевдоним всегда совпадает с именем таблицы, а читаемость программного кода при его использовании заметно улучшится. SELECT FLOORS BROWSE
Этот пример полностью идентичен предыдущему. Таблицы, входящие в состав базы данных, открываются так же, но перед их открытием необходимо открыть саму базу данных: OPEN DATABASE OLDFOX USE ROOMS IN 1 USE FLOORS IN 2
Открывать базу данных необходимо потому, что связанные таблицы могут иметь длинные имена, триггеры и тому подобные вещи, присущие базе данных. Ну и конечно, в состав этих команд можно включить указание пути: OPEN DATABASE C:\OLDFOX\OLDFOX USE C:\OLDFOX\ROOMS EXCLUSIVE
А можно и не включать, но в этом случае путь необходимо заранее указать: SET PATH TO C:\OLDFOX
Команда LOCATE. Поиск записей С помощью данной команды мы можем отыскать записи, удовлетворяющие заданному условию. При этом совершенно безразлично, в каком месте таб лицы эти записи расположены, потому что LOCATE всегда начинает поиск с первой записи и последовательно просматривает все записи до конца таб лицы, пока не найдет ту, которая соответствует заданному условию. В на шей экранной форме есть кнопка Найти и поле ввода Поиск по фамилии. Допустим, нам нужно найти всех клиентов, фамилия которых начинается с букв ИВ. В поле ввода заносим соответствующие буквы и нажимаем кнопку, которая в событии click имеет следующий набор команд: SELECT NAMES LOCATE FOR CSECONDNAME=THISFORM.PAGEFRAME1.PAGE1.TEXT1.VALUE THISFORM.REFRESH()
Урок 15. Выборка, упорядочение и просмотр данных
199
Если найдена запись, удовлетворяющая заданному условию, то указатель записей на ней и остановится. Но что делать, если у нас несколько таких записей, например, трое Ивановых, пятеро Ивиных и один Иванченко? Первое, что приходит в голову, — это запустить LOCATE еще раз. Но здесь скрывается небольшая проблема — LOCATE всегда начинает поиск с первой записи и завершает на найденной (а если не найдет, то на последней) и по этому, сколько бы ты раз ее не запускал — столько раз она тебе и покажет того же самого Иванова. Выход следующий: нужно совместно с LOCATE ис пользовать еще одну команду — CONTINUE, которая продолжает поиск не с начала файла, а с уже найденной записи. В нашем случае можно для собы тия Rightciick (Щелчок правой кнопкой мыши) кнопки Найти назначить выполнение этой команды. Теперь, если мы при помощи LOCATE найдем требуемую запись, для проверки наличия остальных достаточно несколько раз щелкнуть правой кнопкой мыши.
Команда SEEK. Поиск по значению индекса Некоторой альтернативой команды LOCATE является команда SEEK, НО ДЛЯ ее использования необходимо наличие индекса. Если открыто несколько ин дексов, то нужно перед использованием данной команды "выбрать" какойто один, т. к. команда работает с одним индексом. Установить индекс мож но при помощи команды SET ORDER TO, использование которой будет рас смотрено далее. Попробуем найти запись в таблице rooms, значение индекса которой равно 202. SELECT ROOMS SET ORDER TO IDROOM SEEK 202
Вот и все. Синтаксис команды очень прост, но необходимо помнить, что тип задаваемого значения должен совпадать с типом данных текущего ин декса. То есть если индексируемое поле имеет тип character, то задаваемое в команде значение нужно заключить в кавычки.
Команда SET FILTER TO. Выбор группы записей Для того чтобы выбрать группу записей, удовлетворяющих заданному усло вию или условиям, можно использовать команду SET FILTER TO. В рассмот ренном ранее примере мы искали тех клиентов, у которых фамилия начи нается на ИВ, и при этом последовательно перебирали записи, используя
200
Часть I. Процедурное программирование в Visual FoxPro
"спарку" LOCATE и CONTINUE. А используя SET FILTER то, мы можем сразу огобразить все необходимые записи: SELECT NAMES SET FILTER TO CFIRSTNAME="MB" BROWSE
Команда SET FILTER TO также позволяет выбрать записи, удовлетворяющие нескольким условиям. Простой пример: отель твой процветает, дела идут "в гору" и тебе просто необходим надежный и верный помощник. В общем, ты решил жениться! И причем невесту ты собираешься выбрать среди по стояльцев своего отеля. Но не бегать же по этажам, в самом деле! Зачем тогда СУБД? Ищем невесту: SELECT NAMES SET FILTER TO UPPER(СЗЕХ)="Ж".AND.DBIRTHDAY<=CTOD("01.01.1986"); .AND.DBIRTHDAY>=CTOD("01.01.1983") BROWSE
Пожалуйста, выбирай — рис. 15.1.
Рис. 15.1. Результат работы команды SET FILTER TO
Сортировка данных в таблицах Прежде чем приступить к сортировке записей, нам необходимо выяснить: какие вообще существуют способы сортировок данных. Основных способа два, и они принципиально отличаются друг от друга. Первый способ — физическая или постоянная сортировка записей. Второй способ — виртуальная сортировка или временная. Постоянная сортировка. Ее суть заключается в том, что данные в таблице располагаются в строго установленном порядке. Для ее выполнения достаточно просто перезаписать существующую таблицу в нужном порядке. А что делать, если требуется другой порядок записей? Ведь очевидно, что в одной таблице нельзя иметь несколько порядков сортировки. В этом случае нужно еще раз перезаписать таблицу, т. е. создать еще одну копию. Да уж, для по-
Урок 15. Выборка, упорядочение и просмотр данных
201
вседневного использования этот способ является, мягко говоря, не совсем удобным. Но, тем не менее, знать и уметь это будет полезно. Создаем по стоянную сортировку, используя команду SORT: USE NAMES SORT TO NEWNAMES ON CFIRSTNAME
После выполнения данной команды будет создана новая копия таблицы names (она будет иметь имя newnames), но записи в этой таблице будут рас полагаться В Отсортированном ВИДе ПО ПОЛЮ cfirstname. Виртуальная сортировка. Для ее выполнения необходимо наличие соответ ствующих индексов. Что такое индексы, мы с тобой уже рассматривали. Допустим, нам нужно отобразить записи из таблицы names отсортирован ными по фамилиям клиентов, то бишь по алфавиту. Для этого необходимо создать соответствующий индекс, используя либо конструктор базы данных для модификации таблицы, либо введя следующую команду: USE NAMES INDEX ON ALLTRIM (CFIRSTNAME) TAG FIRSTN
А теперь достаточно выполнить команду SET ORDER TO FIRSTN И все, записи упорядочены (рис. J 5.2).
Рис. 15.2. Сортировка записей в таблице
А если нам нужно, помимо сортировки по фамилиям, упорядочить записи еще и по именам клиентов? В этом случае необходимо использовать состав ной индекс: INDEX ON ALLTR(CFIRSTNAME)+ALLTR(CSECONDNAME) TAG FIRSTN
202
Часть I. Процедурное программирование в Visual FoxPro
При этом Лис сообщит, что индекс с таким именем уже существует и спросит, не желаем ли мы его перезаписать? Чтобы он не спрашивал, а индекс переписывался автоматически, нужно добавить в нашу команду еще одно ключевое слово ADDITIVE: USE NAMES INDEX ON ALLTRIM (CFIRSTNAME) TAG FIRSTN ADDITIVE
Для отмены сортировки используется команда тельных параметров.
SET ORDER TO
без дополни-
УРОК 16
Создание и использование запросов На твой вопрос: "Что такое запрос?" — отвечаю: "Запрос — это вопрос". Красиво сказано, не правда ли? А ведь в этой шутке есть доля правды, по тому что запрос это действительно вопрос, с которым пользователь обраща ется к базе данных. Применительно к нашему случаю. • Сколько клиентов из России проживало в нашем отеле за период с 1 сентября по 26 октября? • В каком из номеров предпочитали останавливаться клиенты за все время существования отеля? • Сколько клиентов на сегодняшний день живут в номерах третьего этажа, оборудованных телефоном? • Какой номер самый рентабельный? Список, как ты понимаешь, может быть бесконечным. Ты скажешь: "Ну и что? Я только что научился находить, выбирать, сортировать данные и при помощи определенных команд легко отвечу на эти вопросы!" Не спорю, от ветишь. Количество дополнительных условий, используемых в SET FILTER то, LOCATE, SCAN и т. д., практически не ограничено. Но ты ответишь на эти вопросы сегодня, а завтра и послезавтра возникнут другие. Ты захочешь снова переписывать свою программу? Да и вообще, ведь все вопросы преду смотреть нельзя (если ты, конечно, не ясновидящий). Вот для того, чтобы пользователь мог найти ответ практически на любой вопрос, и существуют такие хитрые и очень мощные "штуковины", как запросы (Query). Еще есть п °хожие на них виды или представления данных, но о них разговор будет Позже.
Конструктор запросов (Query Designer) Для создания запросов в среде Visual FoxPro используется конструктор за просов или Query Designer. Запустить этот "механизм" можно так же, как и все остальное: используя соответствующий пункт системного меню. Выбери
204
Часть I. Процедурное программирование в Visual FoxPro
пункты File | New (Файл | Новый). В диалоговом окне New выбери опцию Query (Запрос) и нажми кнопку New file (Новый файл) (рис. 16.1).
Рис. 16.1. Диалоговое окно New
Рис. 16.2. Диалоговое окно Add Table or View
Как видишь, сразу после выполнения команды меню Лис открывает диалоговое окно, в котором спрашивает: "А какие таблицы или представления данных будут добавлены в создаваемый запрос?" (рис. 16.2). Выберем для начала две таблицы, cities и streets, закроем диалоговое окно, используя кнопку Close (Закрыть), и поближе познакомимся с конструктором запро сов (рис. 16.3). Конструктор запросов содержит панель инструментов Query Designer (рис. 16.4), описание кнопок которой приведено в табл. 16.1. Таблица 16.1. Кнопки панели Query Designer Кнопка
Описание Добавляет в запрос новую таблицу
Add Table (Добавить таблицу) Удаляет таблицу из запроса Remove Table (Удалить таблицу) Задает условия объединения таблиц Add Join (Добавить объединение)
Урок 16.
Создание и использование запросов
205 Таблица
Кнопка
16.1
(окончание)
Описание
View SQL (Показать SQL)
Maximize The T^ble View (Максимизировать панель отображения)
Query Destination (Результат запроса)
Открывает окно с SQL-оператором, со ответствующим данному запросу Раскрывает панель отображения таблиц во весь экран
Открывает диалоговое окно, в котором можно указать, куда выводить результа ты запроса
Рис. 16.3. Окно конструктора запросов, вкладка Fields
Рис. 16.4. Панель инструментов Query Designer
Мы видим, что на рис. 16.3 между добавленными таблицами изображена соединительная линия, которая показывает, что между полями этих таблиц существует связь. Связь действительно есть, в базе данных эти таблицы свя-
206
Часть I. Процедурное программирование в Visual FoxPro
заны по полю idcity, и на вкладке Join (Объединение) конструктора запро сов показано условие объединения этих таблиц (рис. 16.5).
Рис. 16.5. Окно конструктора запросов, вкладка Join
Сейчас мы подробно, на примере, разберем, что же это такое — условие объединения. Допустим, цель нашего запроса — отобразить все города на шей базы данных, кроме тех, названия которых начинаются на М. Также мы включим в результат запроса улицы этих городов, да еще и в алфавит ном порядке. Прежде чем начать формировать условия запроса, необходимо выбрать из таблиц те поля, значения записей которых будут включены в результат за проса. Это делается на вкладке конструктора запросов Fields (Поля) (см. рис. 16.3). На этой вкладке мы видим два списка: Availabe fields (Доступные поля) и Selected fields (Выбранные поля). Поначалу список Selected fields пуст. Чтобы добавить в него поле, нужно выделить его в списке доступных полей и нажать кнопку Add (Добавить). А можно просто перетащить его мышью на список выбранных полей. Для добавления сразу всех полей можно щелкнуть кнопку Add All (Добавить все). Действия при удалении по- лей из списка выбранных прямо противоположны указанным ранее кнопки Remove (Удалить) и Remove All (Удалить все). Маленькие кнопочки со стрелками позволяют изменить порядок отображения полей. Для описания условия запроса используется вкладка Filter (Фильтр) (рис. 16.6).
Урок 16. Создание и использование запросов
207
Рис. 16.6. Окно конструктора запросов, вкладка Filter
В раскрывающемся списке Field Name (Имя поля) отображены имена полей из соответствующих таблиц, включенных в запрос, а в списке Criteria (Кри терий) — условие отбора записей: • = — действует так же, как и обычный знак равенства; • Like (Такой как) — посимвольное сравнение выражения, стоящего спра ва от оператора Like, с выражением, стоящим слева; • = = — создает более ограниченное сравнение (точно равно); • < и > — можно определить как "больше чем" и "меньше чем"; • >= и <= — определяется как "больше или равно" и "меньше или равно"; • Between (Между) — выбираются записи, значения которых попадают в указанный диапазон. С помощью кнопки Not (He) можно инвертировать заданное выражение. Не очень понятно, что такое "инвертировать"? Да не расстраивайся, это просто обозначает "наоборот". Вот в нашем примере при помощи этой кнопки мы и задаем условие такого "неравенства". А если бы мы ее не нажали, то на оборот выбрались бы все города, названия которых начинаются на букву М. Нажатие кнопки Case (Регистр) позволяет игнорировать регистр символь ных строк. Следующая вкладка конструктора запросов — Order By (Порядок отображе ния) (рис. 16.7). Именно здесь мы можем задать желаемый порядок отобра жения записей, иначе говоря, произвести их сортировку. На данной вкладке
208
Часть I. Процедурное программирование в Visual FoxPrci\
также отображены два списка: Selected fields (Выбранные поля) и Ordering criteria (Критерий упорядочения). Добавление полей в список Ordering criteria происходит таким же способом, как и на вкладке Fields. Сам же критерии упорядочения задается выбором соответствующих опций переключателя Order options: Ascending — по возрастанию, Descending — по убыванию.
Рис. 16.7. Окно конструктора запросов, вкладка Order By
Рис. 16.8. Результат выполнения запроса
Урок 16. Создание и использование запросов
209
Теперь осталось только запустить наш запрос в "первое плавание" и по смотреть, что из этого выйдет. Запустить запрос на выполнение проще про стого: 1. Выбрать команду Run Query из пункта системного меню Query (Запрос). 2. Нажать кнопку Run на стандартной панели инструментов. 3. ВЫПОЛНИТЬ Команду DO QUERY <имя_запроса>.
Выполнив любое из этих действий, ты увидишь результат своего запроса на экране (рис. 16.8). Ты спросишь: "А как же обещанное разъяснение про условие объединения таблиц?" А я и не забыл про него, мы собственно и выполнили наш первый запрос для того, чтобы понятнее и нагляднее объяснить, что это такое.
Типы внешних объединений Существует четыре типа объединений: внутреннее, левое внешнее, правое внешнее, полное внешнее. Чтобы нагляднее разъяснить тебе разницу между ними, обратимся к нашим таблицам (рис. 16.9 и 16.10).
Рис. 16.9. Таблица Cities
Рис. 16.10. Таблица Streets
Посмотри, в таблице cities имеется несколько записей (например, Екате ринбург и Самара), для которых нет соответствующих записей в таблице s t r e e t s . А В таблице s t r e e t s , наоборот, имеется запись (ул. Цветочная), ДЛЯ
210
Часть I. Процедурное программирование в Visual FoxPro
которой нет соответствующей записи в таблице с названиями городов. Не стоит удивляться, как такое могло случиться — мы специально ввели эти лишние записи в качестве "наглядного пособия". Теперь вернемся к конст руктору запросов и установим на вкладке Join внутреннее объединение (Inner Join). В этом случае результат нашего запроса будет содержать толь ко те записи из двух таблиц, которые отвечают критерию объединения (рис. 16.11).
Рис. 16.11. Результат внутреннего объединения
Действительно видно, что в итоговую таблицу не попали ни Екатеринбург, ни Самара, ни улица Цветочная. Догадался, почему? Совершенно верно, эти записи не соответствуют критерию объединения — у них не совпадает значение поля idcity. Теперь установим в условие объединения как левое внешнее (Left Outer Join). При таком объединении в результат запроса будут включены все записи из таблицы слева и только те записи из таблицы справа, которые отвечают условию объединения (рис. 16.12). Установив правое внешнее объединение (Right Outer Join), мы добьемся следующего результата — в итоговую таблицу попадут все записи из табли цы справа и записи, отвечающие условию объединения из левой таблицы (рис. 16.13). И наконец, рассмотрим полное внешнее объединение (Full Outer Join), при котором в результат запроса попадают все записи из обеих таблиц (рис. 16.14).
Урок 16. Создание и использование запросов
Рис. 16.12. Результат левого внешнего объединения
211
Рис. 16.13. Результат правого внешнего объединения
Рис. 16.14. Результат полного объединения
Вот еще несколько замечаний по поводу работы с конструктором запросов. • В определении критерия фильтра не следует заключать символьные строки в кавычки — они будут добавлены автоматически. • Если критерий имеет логическое значение, его необходимо заключить в точки ( . F . ) , (.т.).
212
Часть I. Процедурное программирование в Visual FoxPro
• Не нужно использовать функцию CTODO при вводе дат. Просто введи дату в обычном формате — например, 01/01/2001.
Использование в запросе фильтров с несколькими условиями В этом примере мы выполним запрос, используя несколько условий в фильтре. Задача следующая: мы знаем, сколько получили прибыли на сего дняшний день — в день отбытия клиент рассчитывается, а данные и о нем самом и о сумме оплаты заносятся в таблицу depciients. Но нам интересно, есть ли среди живущих в нашем отеле клиентов те, которые уже на сегодня "должны" нам с тобой, ну скажем, сумму больше 36 500 руб. Почему имен но такую? Да не важно, это просто для примера. Усложним задание: клиен ты должны быть из России и более того, нам интересно видеть конкретную сумму по каждому. Каким же образом все это узнать, хотя бы про суммы — ведь в таблице с записями о проживающих (names) нет соответствующего поля? Тем не менее конструктор запросов позволяет легко решить данную задачу, потому что помимо использования фильтра с несколькими условиями, у нас еще есть возможность создавать с помощью построителя выражений вычисляемые поля и включать их в итоговую таблицу. Для построения нашего нового запроса нам потребуются три таблицы с записями о проживающих в данный момент (names), с записями о стоимо сти проживания в номере (rooms), справочник стран (countries). (Хотя справочник стран в данном случае можно и не использовать, ведь записи стране есть и в таблице names.) Для того чтобы узнать сумму по каждому клиенту, воспользуемся построи телем выражений. Чтобы его открыть, нужно щелкнуть на области поля Fields Name вкладки Fields и перейти к его самому последнему элементу Ex- pression. При щелчке на данном элементе откроется построитель выражений (Expression Builder) — а с помощью этой "хитрой штуки" можно создать лю бое выражение на языке программирования Visual FoxPro (рис. 16.15). Что ж, приступим. Чтобы узнать сумму оплаты, нам сначала необходимо знать, сколько дней человек пребывал в нашем отеле — от сегодняшней да ты отнимаем дату приезда. Затем умножаем полученное значение на стои мость проживания в номере за сутки. Практически все изложенное ранее выполняется следующим образом: в раскрывающемся списке From table (Из таблицы), в котором перечислены все "участвующие" в запросе таблицы, выбираем необходимую — в данном случае это таблица names. При этом в списке Fields (Поля) будут отображены поля указанной таблицы. Для того чтобы перенести их в поле Expression (Выражение), где собственно и проис ходит построение выражения, необходимо дважды щелкнуть по выбранном» полю. Если в выражении участвуют какие-либо функции, то их можно писать как вручную, так и выбирать из раскрывающихся списков в областя
Урок 16. Создание и использование запросов
213
Functions (Функции). После построения выражения его необходимо прове рить, щелкнув по кнопке Verify, и сохранить, нажав кнопку ОК. Сохранив полученное выражение, его можно добавить в список Selected fields конст руктора запросов. Построим еще одно выражение — объединим в одном поле фамилию, имя и отчество клиента (рис. 16.16).
Рис. 16.15. Окно построителя Expression Builder
Рис. 16.16. Мы построили еще одно выражение, которое также будет включено в запрос
214
Часть I. Процедурное программирование в Visual FoxPro
Рис. 16.17. Определение условий фильтра
Теперь обратимся к вкладке Filter, на которой и определим условия фильтра] (рис. 6.17). В данном случае мы установили значение логического оператора (Logical) как AND (Логическое И). Смысл показанного на рисунке выражения можно объяснить так: показать записи, для которых результат первого выражения будет больше 36 500, и те записи, для которых значение второго выражения совпадет с условием фильтра. Результат запроса показан на рис. 16.18. А что будет, если мы изменим значение логического оператора, и вместо AND поставим OR? Давай посмотрим — рис. 16.19. Здесь видно, что в результат запроса попали как клиенты, прибывшие из России, так и те люди, что проживают в других странах. Более того, мы ви дим записи, как удовлетворяющие первому условию (сумма больше 36 500), так и записи, не "прошедшие" проверку. Почему так произошло? А все дело в том, что при добавлении оператора OR В набор условий происходит разделение выражения на две части: до OR И после. Они выполняются независимо друг от друга, и что самое интересное, оба работают правильно. Посмотри повнимательней — результатом работы первого выражения являются все записи с суммами больше указанной. Верно? Верно. Ты спросишь, а почему попали "иностранцы"? А где в первом условии упоминание о стране? ТаМ ведь речь идет только о суммах, вот наш дядюшка Лис их аккуратно и выбрал. Но опять же, есть запись с меньшей суммой. А это уже результат paботы второго условия. Страну "заказывали"? Заказывали. Есть записи с этой страной? Есть. Вот и ладненько. Примерно так рассуждает наш изворотлив
Урок 16. Создание и использование запросов
215
вый Лис, и он прав, потому что для него главное синтаксис критериев, а смысл этих критериев ему безразличен. За смыслом выражений должны следить, естественно, мы с тобой. Вот еще один наглядный пример, на этот раз с использованием логического оператора AND (рис. 16.19а).
Рис. 16.18. Результат запроса с AND
Рис. 16.19. Результат запроса с OR
216
Часть I. Процедурное программирование в Visual FoxPro
Рис. 16.19а. Установка значения AND
Что мы видим? С первого взгляда все выглядит вполне нормально. Но дан ный запрос никогда не даст результата, потому то не может быть в одной записи двух указанных значений. В данном случае необходимо использовать логический оператор OR. Ну и как тебе работа с конструктором запросов? Возможности действитель но впечатляют. Помнишь, как мы вычисляли сумму счета для выбывших клиентов? Писали программный код, использовали SCAN, REPLACE И другие команды... А здесь мы обошлись без каких-либо вычислений и легко полу чили желаемый результат. Но на этом возможности конструктора запросов не ограничиваются, в чем мы и убедимся, изучив следующие разделы дан ной главы.
Вывод результатов запроса То, в каком виде результаты запроса предстанут перед пользователем, мож но определить, воспользовавшись диалоговым окном Query Destination (На значение запроса) (рис. 16.20). Всего имеется семь различных режимов для вывода результатов (табл. 16.2)По умолчанию стоит режим BROWSE И именно его мы использовали в преды дущих примерах. Данный режим применяется в основном при разработке приложений, для быстрого просмотра данных.
Урок 16. Создание и использование запросов
217
Таблица 16.2. Режимы отображения результата Режим отображения результата
Описание
BROWSE (Окно просмотра Browse)
Результат выводятся в режиме BROWSE
CURSOR (Временная таблица)
Результат помещается во временную таблицу
TABLE (Таблица)
Результат помещается в постоянную таблицу
GRAPH (График)
Результат используется для построения графика
SCREEN (Экран)
Результат выводится на экран
REPORT (Отчет)
Результат представляется в виде отчета
LABEL (Этикетка)
Результат представляется в виде этикетки
Рис. 16.20. Диалоговое окно Query Destination
Курсор Курсор — это не только указатель мыши. В Visual FoxPro курсором называется временная таблица, которая будет создана для хранения резуль татов запроса. Данные в курсоре можно только просматривать, нельзя их ни Добавлять, ни модифицировать, ни удалять. Курсор "живет" только в теку щем сеансе, при завершении работы Visual FoxPro он будет удален. Знаешь, почему он так интересно называется? Да потому, что его название как нель зя точно определяет его суть — CURSOR (Current Set Of Records, текущий набор записей).
Таблица Результаты запроса записываются в новую таблицу. Это обычная таблица, записи которой можно удалять, добавлять, модифицировать. В отличие от
218
Часть I. Процедурное программирование в Visual FoxPro
своего временного собрата курсора таблица остается на диске и после за вершения сеанса работы Visual FoxPro.
График Результаты запроса можно отобразить в графическом виде. Для построения графиков у Лиса имеется свой "чертежник" — Graph Wizard (Мастер графи ков). Чтобы наглядно проследить за его работой, давай запустим на выпол нение наш запрос, предварительно установив опцию Graph в диалоговом окне Query Destination.
Рис. 16.21. Выбор данных для графика
На данном этапе мастер предлагает выбрать данные, которые будут отобра жены в виде графика (рис. 16.21). Мы будем использовать значения нашего» вычисляемого поля в рядах данных, а поле с фамилией клиента — в катего риях диаграммы. На следующем шаге будет предложено выбрать стиль диаграммы (рис. 16.22). И наконец, последний шаг (рис. 16.23), на котором предлагается задать за головок для будущего графика (Type a title for your graph), выбрать режим отображения нулевых значений (Show null values) и легенды (Add a legend to the graph). Воспользовавшись кнопкой предварительного просмотра Preview, мы можем посмотреть на результат работы мастера (рис. 16.24). После просмотра можно вернуться назад и выбрать другой стиль диаграмм мы. Определившись со стилем окончательного варианта, график необходи-
Урок 16. Создание и использование запросов
219
мо сохранить. Сохранен он будет в виде экранной формы, которую затем можно использовать в приложении. Более того, форму можно модифициро вать (в данном случае это не помешало бы, видишь, как отобразились надписи в легенде (см. рис. 16.24)).
Рис. 16.22. Третий шаг работы мастера
Рис. 16.23. Заключительный этап работы мастера
220
Часть I. Процедурное программирование в Visual FoxPro
Рис. 16.24. Просмотр результата работы мастера графиков
Экран При выборе данного режима результат запроса будет выводиться просто над экран Visual FoxPro, но, используя некоторые дополнительные опции, мож-| но указать еще и дополнительный "пункт назначения" (рис. 16.25).
Рис. 16.25. Диалоговое окно Query Destination, р е ж и м SCREEN
Для назначения дополнительного способа вывода используются переключа-j тели в области Secondary output (Вторичный вывод):
Урок 16. Создание и использование запросов
221
• None — вторичный вывод отсутствует; • To printer — происходит вывод как на экран, так и на принтер; • То text file — вторичный вывод в текстовый файл. Имя файла можно как задать в поле ввода, так и выбрать из созданных ра нее, воспользовавшись кнопкой с таким же названием. Ниже расположена группа флажков: • Suppress column headings — не выводить заголовки столбцов; • Pause between screens — приостанавливать вывод по мере заполнения эк рана. С первым флажком все ясно, а зачем нужен второй? Затем, что если данных много, а второй флажок не установлен — все, пиши пропало: записи проне сутся по экрану так, что ты и моргнуть не успеешь!
Отчет При выборе этого режима результаты запроса будут представлены в виде отчета (рис. 16.26).
Рис. 16.26. Диалоговое окно Query Destination, режим REPORT
Используя данный режим, мы можем поместить данные как в созданный Ранее макет отчета, так и создать совершенно новый. Для вывода результа тов в уже существующий отчет необходимо щелкнуть на кнопке Open
222
Часть I. Процедурное программирование в Visual FoxPro
Report (Открыть отчет). Если же имя отчета известно, то достаточно просто указать его в поле ввода. При этом диалоговое окно Open открыто не будет. Расположенная справа от поля ввода кнопка с изображением волшебной палочки предназначена для вызова Report Wizard (Мастер отчетов). Распо ложенные ниже флажки имеют следующее назначение: • Page preview — предварительный просмотр отчета; • Console on — позволяет разрешить/отменить вывод результатов запроса в текущее окно; • Eject page before report — прогон страницы перед печатью. Также можно указать и вторичный приемник результатов запроса (см. ранее).
Этикетка (почтовая наклейка) Этикетка, или почтовая наклейка, может использоваться как по своему, прямому назначению, так и для других целей — например, для рассылки информации рекламного характера и т. д. Допустим, мы решили подготовить и отправить кое-кому из наших клиентов приглашения на праздничный вечер. Используя данный режим вывода, мы можем без особых хлопот это проделать. Далее представлено диалоговое окно Query Destination с опциями, используемыми для вывода этикеток (рис. 16.27).
Рис. 16.27. Диалоговое окно Query Destination, режим LABEL
Так как опции данного диалогового окна аналогичны опциям для вывода отчетов, мы не будем останавливаться на этом вопросе, а сразу обратимся к Label Wizard — мастеру почтовых наклеек (в "арсенале" у Лиса и такое чудо
Урок 16. Создание и использование запросов
223
имеется). В первом диалоговом окне мастера предлагается выбрать источ ник данных (рис. 16.28).
Рис. 16.28. Первый шаг работы мастера
Рис. 16.29. Второй шаг работы мастера
На втором шаге (рис. 16.29) мастер предлагает выбрать из списка готовых этикеток наиболее подходящую. В столбце Avery (Наименование) отобра-
22Л
Часть I. Процедурное программирование в Visual FoxPro
жаются наименования этикеток, а в столбце Dimensions (Размерность) пока заны размеры этикетки. Количество колонок, помещаемых на одной стра нице, указано в столбце Columns (Колонки). Размеры указаны в дюймах, но их легко можно перевести в миллиметры, включив опцию Metric (Метри ческая). Щелкнув на кнопке New Label (Новая этикетка), мы можем задать свои раз меры для этикетки (рис. 16.30).
Рис. 16.30. Диалоговое окно Custom Labels
После нажатия кнопки New (Новая) мы можем приступить к процессу oпределения размеров нашей будущей этикетки, в чем нам поможет соответ--] ствующее диалоговое окно (рис. 16.31). Для изменения ранее созданной пользователем почтовой наклейки исполь зуется кнопка Edit (Редактирование) диалогового окна Custom Labels (Поль зовательские этикетки). На третьем шаге работы мастера (рис. 16.32) необходимо перенести соответствующие поля из списка Available fields (Имеющиеся поля) в список Selected fields (Выбранные поля). Но здесь, в отличие от других диалоговых окон, необходимо сразу задать тип разделителя между полями. Типы разде лителей изображены на кнопках, расположенных между этими двумя списками. Для вставки между полями пробела используй кнопку Space (Про бел), а для расположения поля на следующей строке необходимо нажать кнопку с изображением кривой стрелки (как на клавиатуре клавиша <Enter>). Размер и стиль шрифта можно изменить, щелкнув на кнопке Font (Шрифт). Разместив необходимые поля, переходим к следующему этапу, на которому определим порядок сортировки записей (рис. 16.33). Созданную этикетку можно модифицировать в окне Label Designer (Конст руктор этикеток) (рис. 16.34).
Урок 16. Создание и использование запросов
Рис. 16.31. Диалоговое окно для определения размеров и прочих параметров создаваемой этикетки
Рис. 16.32. Третий шаг работы мастера
I002
225
226
Часть I. Процедурное программирование в Visual FoxPro
Рис. 16.33. Четвертый шаг работы мастера
Рис. 16.34. Наша этикетка в окне конструктора этикеток
Урок 16.
Создание и использование запросов
227
Обрати внимание на выражение, расположенное выше выбранных нами полей. Там используется незнакомый тебе оператор IIF. Синтаксис этого выражения следующий: IIF(Names.cSex= " м " ,
"Уважаемый",
"Уважаемая")
т. е. если первое выражение возвращает логическую истину (верно) — вы полняется следующее за запятой выражение. Если же нет — выполняется последнее выражение. Этот оператор очень удобен потому, что в нем можно использовать любые команды, а также поддерживается выполнение не скольких вложенных условий IIF. Полюбовавшись на творение рук своих (рис. 16.35), нам остается только удовлетворенно вздохнуть и рассмотреть еще один способ сохранения ре зультатов запросов — в формате HTML.
Рис. 16.35. Наша этикетка в окне предварительного просмотра
HTML Visual FoxPro может сохранять некоторые файлы в данном формате, и таб лицы не являются исключением. Для представления результатов запроса в формате HTML, их (результаты) сначала нужно представить в табличной фор ме (CURSOR или BROWSE). После этого необходимо в системном меню File (Файл) выбрать пункт Save As HTML (Сохранить как HTML) (рис. 16.36).
228
Часть I. Процедурное программирование в Visual FoxPro
Рис. 16.36. Диалоговое окно Save As HTML
В открывшемся диалоговом окне можно выбрать любую из трех опций: • Save file for later use — сохранить файл для последующего использо вания; • Save and edit file — сохранить файл и открыть окно для его редактиро вания; • Save file and view in web browser — сохранить файл и открыть браузер для просмотра данного файла. При выборе второго пункта диалогового окна Save As HTML (Сохранить как HTML) мы получим возможность просмотреть и отредактировать HTML-код нашего файла (рис. 16.37).
Рис. 16.37. Окно редактирования
При выборе последнего пункта диалогового окна мы можем просмотреть результаты запроса в окне Web-браузера (рис. 16.38). Рассмотрев режимы вывода результатов запросов, перейдем на последнюю вкладку конструктора запросов — Miscellaneous (Разное), которая содер жит опции для задания дополнительных критериев для выборки записей (рис. 16.39).
Урок 16. Создание и использование запросов
Рис. 16.38, Результат запроса в окне Opera
Рис. 16.39. Окно конструктора запросов, вкладка M i s c e l l a n e o u s
229
230
Часть I. Процедурное программирование в Visual FoxPro
Флажок No duplicates (Без дубликатов) позволяет предотвратить или, наобо рот, разрешить вывод в результирующий запрос повторяющихся значений. Установка флажка Cross tabulate (Перекрестная таблица) позволяет предста вить результаты запроса в виде перекрестной таблицы. Счетчик Number of records (Количество записей) позволяет указать количество выводимых в результат запроса записей. При установленном флажке All (Все) будут выве дены все записи. На этом мы на время оставим конструктор запросов и пeрейдем к следующему разделу.
SQL-инструкция SELECT или как все это сделать "вручную"? Что такое SQL-инструкция SELECT? ЭТО как раз то, написанием чего мы за нимались всю предыдущую главу. Ты спросишь: "Как же так? Ведь мы за нимались построением запросов с помощью Query Designer, и никаких таких непонятных инструкций видеть не видели, и знать не знаем..." Про "знать не знаем" пока согласен, а вот насчет остального... Щелкни-ка мышью по кнопке SQL, которая расположена на панели инструментов Query Designer (рис. 16.40).
Рис. 16.40. SQL-инструкция SELECT
Вот это и есть SQL-инструкция SELECT. А кто написал весь этот программ-) ный код? Да ты сам, кто же еще. Вернее не ты, а Лис, но с твоей помощью. А вот прочитав эту главу, ты вполне сможешь научиться писать SQLинструкции самостоятельно и затем использовать их как подпрограммы или фрагменты программ в своих приложениях.
Урок 16. Создание и использование запросов
231
Что же это такое? Очевидно, что SQL-инструкция SELECT представляет со бой набор операторов, предназначенных для выборки из таблиц определен ных данных, удовлетворяющих заданным условиям. Простыми словами — эта "штука" используется для создания запросов. Простейший запрос может иметь такой вид: USE C:\OLDFOX\OLDFOX SELECT * FROM OLDFOX!NAMES
В данном случае в наш запрос попадут все поля и все записи из таблицы names, входящей в состав базы данных oidfox, и все это будет отображено в окне Browse. А где в приведенном примере команда BROWSE? А нигде — режим отображения BROWSE установлен по умолчанию. Если нам нужны не все поля, можно просто указать необходимые: SELECT Cfirstname, Csecondname, Dbirthday FROM OLDFOX!NAMES
В любом случае инструкция всегда начинается с ключевого слова SELECT, за которым следует перечисление включаемых в результат запроса полей. Если используется таблица, входящая в состав базы данных (как в нашем случае), то перед именем таблицы необходимо указать имя базы данных и разделить их восклицательным знаком. Если же таблица не входит в состав базы дан ных, т. е. является свободной, — указывается только ее имя. На рис. 16.40 видно, что перед именами полей стоят псевдонимы таблиц. В принципе, псевдонимы можно и не указывать, но для улучшения "читаемости" всетаки лучше их использовать. Более того, псевдонимы просто необходимы в том случае, если таблицы, включаемые в запрос, имеют одинаковые имена. Разобравшись с самыми основными понятиями, переходим к практическим занятиям: помнишь, мы искали с помощью команды LOCATE фамилии, кото рые начинаются на ИВ? Попробуем сделать то же самое с использованием SQL-инструкции: SELECT * FROM OLDFOX!NAMES WHERE Cfirstname="MB"
Вот даже на этом простейшем примере ты можешь оценить возможности SQL: вспомни-ка код, написанный для использования LOCATE. А здесь всего одна строка, в которой оператор WHERE действует точно так же, как FOR В других командах. Для того чтобы отобразить записи в упорядоченном виде, в SQL-инструкЦию SELECT необходимо включить ключевое слово ORDER BY (аналог коман ды SET ORDER TO <имя_ПОЛЯ>) SELECT * FROM OLDFOX! NAMES WHERE Cfirstname="MB"; ORDER BY Cfirstname
Теперь вернемся к вопросу о твоей невесте — ты ведь все еще не женился (рис. 16.41)?
232
Часть I. Процедурное программирование в Visual FoxPro
SELECT Cfirstname AS Фамилия, Csecondname AS Имя; DBIRTHDAY AS День_Рождения; YEAR (DATE ()) -YEAR(Dbirthday) AS Возраст; FROM OLDFOX! NAMES WHERE Csex=")K".AND. YEAR(Dbirthday) <«1986; .AND. YEAR (Dbirthday) >=1983 ORDER BY Cfirstname
Рис. 16.41. Мы изменили заголовки полей в результате запроса
Здесь мы включили в нашу инструкцию еще несколько ключевых слов и сейчас проанализируем, как это все работает. Ключевое слово AS позволяет изменить имя поля, причем кавычки ставить не нужно. Единственное усло вие — название должно состоять из одного слова. Функция YEAR о возвращает значение года из выражения, имеющего формат Date. Используя две этих функции, мы вычисляем возраст твоей невесты. (Правда приблизи тельно, потому что для точного вычисления возраста используется несколько другой алгоритм.) Затем, опять же используя функцию YEARO, задаем критерий отбора записей. Данную инструкцию можно упростить, применив еще одно ключевое сло во — BETWEEN, которое позволяет выделить диапазон значений: SELECT CFIRSTNAME AS ФАМИЛИЯ, CSECONDNAME AS ИМЯ; DBIRTHDAY AS ДЕНЬ_ РОЖДЕНИЯ; YEAR(DATE(>) -YEAR(DBIRTHDAY) AS ВОЗРАСТ; FROM OLDFOX!NAMES WHERE CSEX=">K"; .AND.YEAR(DBIRTHDAY) BETWEEN 1983 AND 1986 ORDER BY CFIRSTNAME
Для фильтрации отбираемых значений можно применить ключевое слово| IN. Допустим, нужно показать записи о всех клиентах, прибывших из горо-| дов Москва, Красноярск и Санкт-Петербург. Без использования члена IN инструкция может выглядеть таким образом: SELECT * FROM OLDFOX!NAMES; WHERE ССГГС="Санкт-Петербург"; OR CCITY="MocKBa"; OR CCITY="Красноярск"
А вот та же инструкция с использованием слова IN: SELECT * FROM OLDFOX!NAMES; WHERE CCITY IN ("Красноярск","Москва","Санкт-Петербург")
Урок 16. Создание и использование запросов
233
Для того чтобы запретить вывод повторяющихся значений, необходимо до бавить в SQL-инструкцию еще одно ключевое слово — DISCTINCT (аналог флажка No duplicates на вкладке Miscellaneous). Если мы захотим узнать, какие города есть в таблице names, нам достаточно написать простенькую инструкцию: SELECT CCITYAS ГОРОД FROM OLDFOX! NAMES
и посмотреть результат — рис. 16.42.
Рис. 16.42. Список городов из таблицы names
Рис. 16.43. Результат запроса с использованием слова DISCTINCT
Мы видим, что в этом случае значения записей повторяются. На рис. 16.43 показан результат работы инструкции SELECT DISCTINCT CCITY AS ГОРОД FROM OLDFOX!NAMES
Единственное условие — DISCTINCT в инструкцию нужно включать перед именами выбранных полей.
Подзапросы Применяя SQL-инструкции, разрешается использовать до десяти вложен ных запросов. Конструкция, имеющая вложенные запросы, называется под запросом. Допустим, нам понадобилось узнать, какой была максимальная заплаченная сумма за проживание в нашем отеле, а также выбрать клиенI
234
Часть I. Процедурное программирование в Visual FoxPro
тов, которые заплатили больше половины от максимальной. Зачем нам это нужно в реальной жизни, я не знаю, но в данном случае инструкция SQL будет иметь следующий вид: SELECT Cfirstname AS ФАМИЛИЯ; Csecondname AS ИМЯ; Ncost AS СУММА; FROM OLDFOX! DEPCLIENTS; WHERE Ncost > (SELECT MAX (Ncost) * 0,5
FROM DEPCLIENTS)
Результат выполнения этого подзапроса показан на рис. 16.44.
Рис. 16.44. Результат подзапроса 1
Изменив условие отбора WHERE NCOST < (SELECT MAX (NCOST) * 0,5
FROM DEPCLIENTS)
получим прямо противоположный результат — рис. 16.45. При построении данной инструкции мы использовали функцию МАХ(), КОторая определяет максимальное значение поля. В SQL-инструкциях можно применять некоторые математические функции (табл. 16.3). Все эти функции можно использовать как при написании SQL-инструкции, так и при работе с конструктором запросов — в этом случае они находятся в раскрывающемся списке Math (Математические) в группе Function (Функции) окна построителя выражений (Expression Builder).
Урок 16. Создание и использование запросов
235
Таблица 16.3. Математические функции, доступные в SQL-инструкциях
Функция
Описание
COUNT()
Подсчитывает количество записей
SUM()
Суммирует значения
AVG()
Вычисляет среднее значение
MIN()
Определяет минимальное значение
МАХО
Определяет максимальное значение
COUNT(DISTINCT)
Подсчитывает количество неповторяющихся записей
SUM(DISTINCT)
Суммирует значения неповторяющихся записей
AVG(DISTINCT)
Вычисляет среднее значение среди неповторяющихся записей
Рис. 16.45. Результат подзапроса 2
При использовании сложных выражений в инструкции необходимо указы вать тип объединения между таблицами: SELECT (DATE()-NAMES.DARRDATE)*ROOMS.NPRICE; NAMES.CFIRSTNAME; FROM OLDFOX!COUNTRIES INNER JOIN OLDFOX!NAMES; INNER JOIN OLDFOX!ROOMS; ON ROOMS.IDROOM = NAMES.IDROOMS; ON COUNTRIES.IDCOUNTRY = NAMES.IDCOUNTRY;
236
Часть I. Процедурное программирование в Visual FoxPro
WHERE (DATE()-NAMES.DARRDATE)*ROOMS.NPRICE > 36500; AND COUNTRIES.CCOUNTRY = "Россия"
Так как в данном примере условие выборки состоит из двух условий, необ ходимо дважды указать тип объединения: INNER JOIN OLDFOX'NAMES; INNER JOIN OLDFOX!ROOMS; ON ROOMS.IDROOM = NAMES.IDROOMS; ON COUNTRIES.IDCOUNTRY - NAMES.IDCOUNTRY;
Использование HAVING Ключевое слово HAVING имеет тот же смысл, что и слово WHERE, но в то вре мя как WHERE используется для выборки отдельных строк, удовлетворяющих условию, HAVING "работает" с группами записей. Определим города, из которых в наш отель прибыло по два постояльца: SELECT CCITY FROM OLDFOX!NAMES; GROUP BY CCITY; HAVING COUNT (*)>2
Использование переменных в SQL-инструкциях SELECT До сих пор мы сами задавали условия для выборки тех или иных данных из таблиц. Но для того чтобы значения критериев отбора мог задавать конеч ный пользователь, необходимо использовать переменные: nMYCOST=12000 SELECT CFIRSTNAME, CSECONDNAME, NCOST FROM OLDFOXiDECLIENTS; WHERE NCOST=NMYCOST
Рассмотрев данный пример, нетрудно догадаться, каким образом можно ор ганизовать работу пользователя с запросом. Правильно, можно использо вать экранную форму, в полях ввода которой пользователь и будет задавать те или иные значения для формирования критерия отбора записей. А как будет выполняться запрос? Да запросто: сохраняем нашу инструкцию в виде файла с расширением prg и назначаем команду DO <имяг_нашей_программы>
для события click какого-нибудь элемента экранной формы. По умолчанию результат работы SQL-инструкции SELECT выводится в окно. Browse. "Пункт назначения" можно изменить, добавив в инструкцию кля чевое слово INTO:
Урок 16. Создание и использование запросов
237
nMYCOST=12000 SELECT CFIRSTNAME, CSECONDNAME, NCOST FROM OLDFOX!DECLIENTS; WHERE NCOST=NMYCOST; INTO CURSOR MYQWERY
В данном случае результат будет помещен в курсор MYQWERY. А вот и таблица с допустимыми значениями оператора INTO — табл. 16.4. Таблица 16.4. Значения оператора INTO Значение
Описание
INTO ARRAY <имя_массива>
Результат запроса выводится в массив
INTO CURSOR <имя_курсора>
Результат запроса выводится в курсор
INTO TABLE <имя_таблицьО
Результат запроса выводится в таблицу
TO PRINTER
Результат запроса выводится на принтер
TO SCREEN
Результат запроса выводится на экран
TO FILE <имя_файла>
Результат запроса выводится в указанный файл
Построение перекрестых таблиц В некоторых случаях удобнее просматривать данные в виде перекрестной таблицы. Например, нам необходимо провести небольшой анализ— в ка ком из номеров нашего отеля чаще всего предпочитали останавливаться клиенты и от каких клиентов (имеется в виду город постоянного прожива ния), мы получили наибольшую прибыль — во как закрутили, скоро дейст вительно аудиторами станем! Нам не составит труда "соорудить" соответствующий запрос и получить же лаемый результат (рис. 16.46). Как говорится, что хотели, то и получили. Действительно, мы видим и го рода, и номера апартаментов, и уплаченные суммы. Но для проведения ана лиза такой режим отображения данных не совсем удобен, и поэтому мы примем решение вывести результат нашего запроса в виде перекрестной таблицы. Но сначала дадим определение — что же это такое? Перекрестная таблица (Cross-Tab) представляет собой такой вид запроса, в котором определяются заголовки столбцов и строк таблицы, а затем вы числяются результаты ячеек, находящихся на пересечении соответствующих столбцов и строк. Для представления данных в виде перекрестной таблицы сохраним резуль тат нашего запроса в отдельной таблице:
238
Часть I. Процедурное программирование в Visual FoxP,
SELECT DEPCLIENTS.CCITY, DEPCLIENTS.NCOST, DEPCLIENTS.IDROOMS; FROM OLDFOX! C I T I E S , OLDFOX!DEPCLIENTS; INTO TABLE QUERY2.DBF
Рис. 16.46. Результат запроса
Существует два способа для построения перекрестной таблицы — использование мастера Cross-Tab Wizard и использование соответствующей SQLинструкции. Рассмотрим процесс создания перекрестной таблицы с по мощью мастера, который можно вызвать следующим образом: 1. Любым из уже известных нам способов вызываем диалоговое окно New Query (Новый запрос) (рис. 16.47). 2. Нажав кнопку Query Wizard, выбираем мастер перекрестных таблиц. (рис. 16.48).
Рис. 16.47. Диалоговое окно New Query
Рис. 16.48. Диалоговое окно Wizard Selection
Урок 16. Создание и использование запросов
239
На первом этапе работы мастера необходимо указать поля, значения кото рых будут выведены в перекрестную таблицу (рис. 16.49).
Рис. 16.49. Первый шаг работы мастера перекрестных таблиц
Выбрав необходимые поля, переходим ко второму шагу работы мастера (рис. 16.50).
Рис. 16.50. Второй шаг работы мастера перекрестных таблиц
240
Часть I. Процедурное программирование в Visual FoxPro
На данном этапе предлагается определить строки, столбцы и значения по лей (необходимые поля просто перетаскиваются мышью).
Рис. 16.51, Третий шаг работы мастера перекрестных таблиц
На третьем шаге работы мастера (рис. 16.51) можно установить опции позволяющие вычислять групповые значения по полю (табл. 16.5). Таблица 16.5. Возможное итоговое значение Опция
Назначение
Sum
Итоговые значения равны сумме значений
Count
Итоговые значения равны количеству значений
Average
Итоговые значения равны среднему значению
Max
Итоговые значения равны максимальному значению
Min
Итоговые значения равны минимальному значению
В перекрестную таблицу можно добавить итоговый столбец и установить для него определенное значение (табл. 16.6). Таблица 16.6. Значения итогового столбца Опция
Назначение
Sum of data
В итоговом столбце — сумма значений текущей строки
Урок 16. Создание и использование запросов
241 Таблица 16.6 (окончание)
Опция
Назначение
Number of cells containing data
В итоговом столбце — количество ячеек текущей строки, содержащих данные
Percentage of the table total
В итоговом столбце — процент значений текущей строки по отношению к итоговой сумме
None
Итоговый столбец отсутствует
Рис. 16.52. Заключительный этап работы мастера
На заключительном этапе (рис. 16.52) мастер спрашивает, что делать с по лученным результатом — табл. 16.7. Таблица 16.7. Назначение опций мастера перекрестных таблиц Опция
Назначение
Save cross-tab query
Сохранить созданный запрос
Save and run cross-tab query
Сохранить созданный запрос и запустить его на выполнение
Save cross-tab query and modify in the Query Designer
Сохранить созданный запрос и открыть его в окне конструктора запросов для модифика ции
242
Часть I. Процедурное программирование в Visual FoxPro
Флажок Display null values позволяет отображать или, наоборот, скрывать нулевые значения. Что же, пора посмотреть, чего мы там натворили — рис. 16.53.
Рис. 16.53. Перекрестная таблица
Теперь посмотрим, как будет выглядеть код для инструкции SQL. Самый простой способ — модифицировать полученный запрос в конструкторе и "подсмотреть" SQL-оператор, сгенерированный Visual FoxPro (рис. 16.54).
Рис. 16.54. Этот SQL-оператор — результат работы мастера перекрестных таблиц
Урок 16. Создание и использование запросов
243
Этот фрагмент кода можно скопировать в буфер обмена и затем использо вать в своих приложениях. Обрати внимание, каким образом происходит построение перекрестной таблицы: DO (_GENXTAB) WITH. .. Для этого используется специальная про грамма _GENXTAB, входящая в состав Visual FoxPro. Для ее корректной рабо ты необходимо определение специальных параметров — табл. 16.8. Таблица 16.8. Параметры, передаваемые программе _GENXTAB Номер параметра
Назначение
Значение по умолчанию
1
Имя выходного файла или курсора
Xtab.dbf
2
Создание только курсора
.Т.
3
Закрывать таблицу при выходе из программы
.Т.
4
Отображать индикатор работы программы
.т.
5
Номер поля, являющегося строкой перекрестной таблицы
1
б
Номер поля, являющегося столбцом перекрестной таблицы
2
7
Номер поля, являющегося полем данных для пере крестной таблицы
3
8
Будет формироваться итоговое поле
.F.
Тип вычислений в итоговом поле: 0 — сумма, 1 — количество, 3 — процент
0
9
Изменяя эти параметры, можно менять режим отображения перекрестной таблицы.
Использование SQL-инструкций в программах Так как инструкция сохраняется в виде файла с расширением qpr, для ее выполнения достаточно использовать простую команду: DO <имя файла>.qpr
УРОК 17
Использование представлений данных (видов) Как всегда, возникает самый главный вопрос — а что это такое? Отвечаем — почти то же, о чем мы читали в предыдущей главе. Почему почти? А вот это и есть самый важный вопрос, потому что между этими двумя почти эквивалентными понятиями есть различия и они принципиальны. • Запросы хранятся в отдельных файлах с расширением qpr, а представления данных — в самой базе данных. • Самое главное — представления позволяют обновлять данные. • С помощью представления можно обновлять данные, сохраняемые в нескольких связанных файлах. • Созданное представление данных можно использовать как обычную таб-) лицу в отчетах, формах, запросах. • С помощью представления данных можно ограничить доступ пользователя к отдельным записям.
Создание нового представления данных Создание нового представления в принципе не отличается от создания любого нового элемента приложения: • выберите в системном меню команду File J New | View (Файл | Новый ) Вид); • в окне диспетчера проекта: вкладка Data (Данные), элемент Local Views (Представление локальных данных); • в окне Command (Команда): команда Create View (Создать представление данных). Независимо от того, какой способ выбран, на экране появится диалоговое окно New Local View (Новое представление данных) (рис. 17.1).
Урок 17. Использование представлений данных (видов)
245
Рис. 17.1. Диалоговое окно New Local View
Как всегда в таких случаях, Лис предлагает воспользоваться либо услугами мастера, либо построить новый вид самостоятельно, используя конструктор. Мы с тобой трудностей не боимся, поэтому выбираем конструктор (рис. 17.2).
Рис. 17.2. Диалоговое окно View Designer
Конструктор данных почти полностью идентичен конструктору запросов (за исключением новой вкладки Update Criteria), поэтому мы не будем подроб но останавливаться на его описании, а сразу перейдем к делу. Задача следующая: нам необходимо знать, на каком этаже живет тот или иной клиент, а также сумму, которую он должен уплатить на сегодняшнюю дату. Для создания данного представления нам потребуются три таблицы: Floors.dbf, Rooms.dbf и Names.dbf. Воспользовавшись кнопкой Add Table
246
Часть I. Процедурное программирование в Visual FoxPro
(Добавить таблицу), расположенной на панели управления View Designer (Конструктор представлений данных), добавим в наше представление ука занные таблицы (рис. 17.3).
Рис. 17.3. Добавление таблиц в представление данных
Теперь необходимо указать поля, которые будут "участвовать" в представлении данных. Здесь нет ничего сложного, и как это сделать — описано ранее при изучении конструктора запросов. Единственное, что может вызвать за труднение, — это создание вычисляемого поля (с суммами оплаты). Но ин здесь, оказывается, никаких проблем не возникает: в конструкторе можно воспользоваться построителем выражений, в котором можно написать любое выражение на языке FoxPro. Вот и напишем: rooms.nprice*(date() - names.arrdate)
и включим это выражение в наше представление. Как и в конструкторе запросов, в конструкторе представлений можно задать условия объединения таблиц — вкладка Join (Объединение) (рис. 17.4). А для задания условий выборки данных можно воспользоваться вкладкой Filter (Фильтр) (рис. 17.5). За порядок отображения записей "отвечает" вкладка Order By (Сгруппиро вать по) (рис. 17.6). А теперь запустим наше представление в "первое плавание" (рис. 17.7).
урок 17. Использование представлений данных (видов)
Рис. 17.4. Условия объединения таблиц
Рис 17.5. Условие выборки данных
247
248
Часть I. Процедурное программирование в Visual FoxPro
Рис. 17.6. Порядок отображения записей
Рис. 17.7. Представление данных
Таким образом, созданные представления можно просматривать, как обыч ные таблицы, использовать их в качестве источника данных для экранных форм, отчетов и т. д. Как и при работе с обычными таблицами, при работе
Урок 17. Использование представлений данных (видов)
249
с представлениями вполне допустимо использование соответствующих команд: USE, BROWSE И т. д. Более того, сами записи в представлении данных можно редактировать — в этом-то и состоит главное отличие представления от запроса. В конструкторе представлений имеется вкладка Update Criteria (Критерии обновления), которая и содержит опции, связанные со способностью пред ставлений обновлять (редактировать) входящие в них данные (рис. 17.8).
Рис. 17.8. Опции вкладки Update Criteria
По умолчанию, изначально, обновление данных в таблицах, входящих в со став представления, запрещено. Чтобы разрешить обновление записей, не обходимо указать таблицу, к которой эти записи принадлежат — это делает ся с помощью раскрывающегося списка Tables (Таблицы). При выборе необходимой таблицы ее поля (не все, а только те, которые включены в представление данных) будут отображены в списке Field name (Имя поля). Если таблица имеет первичный ключ (индекс), то в первой ко лонке, где изображен ключик, появится галочка. Мы можем изменить зна чение первичного ключа только в том случае, если поле, содержащее его, входит в набор полей, включенных в наше представление данных. Кнопка Reset Key (Сброс ключа) позволяет вернуть первоначальное значе ние ключа. Кнопка Update All (Обновить все) позволяет установить, какие именно поля будут обновляться. Но даже если указать, что разрешено обновление всех
250
Часть I. Процедурное программирование в Visual FoxPro
полей, все равно никакого обновления не получится, если ты забудешь при этом отметить галочкой флажок Send SQL updates (Отправлять обновления). Так что отметь его, не забудь. Разрешив обновления, нужно выбрать одну из четырех опций, перечисленных в табл. 17.1. Таблица 17.1. Опции вкладки Update Criteria Опция
Описание
Key fields only (Только ключевые поля)
В поиске записей, которые следует обновить в исходных таблицах, используется только значение ключевого поля
Key and updatable fields (Ключи и обновляемые поля)
В поиске записей, которые следует обновить в исходных таблицах, используются значения ключевого поля и всех обновляемых полей
Key and modified fields (Ключи и модифицированные поля)
В поиске записей, которые следует обновить в исходных таблицах, используются значения ключевого поля и модифицированных полей
Key and timestamp (Ключи и временная метка)
На локальных станциях эта опция недоступ на. А вообще это — запрет всех обновлений, если было изменено ключевое поле или вре менная метка. Используется в сетевых вер сиях
Рис. 17.9. Пример критерия отбора записей
Урок 17. Использование представлений данных (видов)
251
Последние две опции на этой вкладке позволяют определить, каким же именно способом обновить записи: либо удалить исходные и затем вставить новые (SQL DELETE then INSERT), либо просто обновить существующие (SQL UPDATE). Ну вот, более или менее разобрались с представлениями данных, но возни кает одно но: а как сделать так, чтобы пользователь мог сам определять ус ловия для отбора записей? Простой пример — рис. 17.9. В данном случае в представление данных войдут те фамилии из таблицы names, которые начинаются на букву А — рис. 17.10.
Рис. 17.10. Результат отбора записей — вид
Но мы можем позволить пользователю самому определить условия выборки, и делается это с использованием параметров представления.
Параметры представления данных Если задать эти самые параметры, то они будут запрашиваться при откры тии представления. Для определения параметров используется команда View Parameters (Параметры представления) из меню Query (Запрос) (рис. 17.11). В открывшемся диалоговом окне мы можем задать список параметров, оп ределив для каждого тип и имя. Теперь для определения условия выборки Данных достаточно на вкладке Filter (Фильтр) указать имя необходимого параметра (рис. 17.12).
252
Часть I. Процедурное программирование в Visual FoxPro
Рис. 17.11. Диалоговое окно для определения параметров
Рис. 17.12. Использование параметра для определения условия выборки данных
Имя параметра указывается в поле ввода Example (Пример) и перед ним ставится знак вопроса, который является признаком использования napaметра. Параметров может быть несколько, и при этом для задания значения каж, дого из них будет открываться отдельное окно. А вот так будет работать на ше модифицированное представление: 1. Задаем значение параметра (рис. 17.13). 2. Получаем результат (рис. 17.14). Но очевидно, что использование данной технологии не очень удобно для конечного пользователя — не будет он разбираться во всяких меню, команд-
Урок 17. Использование представлений данных (видов)
253
дах и т. п.! Это я тебе точно говорю. А выход очень простой — использовать в качестве параметров все те же переменные памяти, значения которым пользователь может присваивать с помощью полей ввода в экранной форме. Вот и все. Все довольны! Более того, при этом окна для ввода значения па раметров открываться не будут.
Рис. 17.13. Значение параметра
Рис. 17.14. Результат Замечание В представление данных, помимо обычных полей, можно включать и поля типа Memo. Включать-то можно, да вот беда — обновляться (см. ранее) они не будут ни при каких условиях. Се ля ви, что тут поделать.
Использование представления данных в отчете Как уже было сказано, представления могут быть использованы при созда нии отчетов. Например, нам нужно получить отчет, содержащий данные
254
Часть I. Процедурное программирование в Visual FoxPro
всех трех указанных ранее таблиц. Можно, воспользовавшись конструкто ром отчетов, назначить в качестве источника данных сами таблицы, но то гда придется конструировать многотабличный отчет со связями между таб лицами типа "один-ко-многим". Можно воспользоваться мастером (One-ToMany Report Wizard), но этот мастер работает только с двумя связанными таблицами. Наиболее рациональным вариантом является именно использо вание представления в качестве источника данных. Давай попробуем создать такой отчет в конструкторе. Как обычно, назначаем источник данных для нашего отчета, указав в диа-| логовом окне опцию Views (Представления данных) (рис. 17.15).
Рис. 17.15. В качестве источника данных мы выбираем не таблицы, а наше представление
Для группировки данных в нашем отчете воспользуемся соответствующим пунктом меню Report (Отчет) (рис. 17.16). На экране появится диалоговое окно Data Grouping (Группировка данных) (рис. 17.17). В данном окне мы можем задать условие группировки данных, причем можно как просто указать поле, так и написать какое-нибудь выражение (на языке Visual FoxPro, естественно). В нашем случае данные будут представлены в виде групп, заголовком которых будет являться номер этажа. Более того, мы можем получить итоговые значения как по каждому этажу (поместив соответствующее выражение в область отчета Group Footer), так и итоги по всему отчету, воспользовавшись командой Report | Title | Summary. В конструкторе наш отчет будет выглядеть примерно так, как на рис. 17.18. При запуске данного отчета на выполнение появится окно для ввода параметров, после чего отчет будет выполнен (рис. 17.19).
Урок
17.
Использование представлений данных (видов)
Рис. 17.16. Группировка данных
Рис. 17.17. Диалоговое окно Data Grouping
255
256
Часть I. Процедурное программирование в Visual FoxPro
Рис. 17.18. Макет нашего отчета в окне конструктора
Рис. 17.19. Наш отчет в режиме предварительного просмотра
Ну и как, удобно использовать представления? За три минуты мы получили отчет с данными из трех таблиц, да еще и возможность самим задавать условия отображения записей. Что ж, перейдем к следующему уроку.
УРОК 18
Внедрение OLE-объектов Для начала короткая справка, дающая ответ на твой вечный вопрос: "А это еще что такое?!" В твоем приложении может быть сколь угодно этих самых OLE-объектов, и несмотря на то, что созданы они не средствами Visual FoxPro, они являются полноценными членами твоего приложения. В об щем, можно дать такое "примитивное" определение для OLE-объекта — эта штука создана в какой-либо программе Windows (не Visual FoxPro), но так же может использоваться в другой, не "родной" программе, например в Visual FoxPro. В таблицах Visual FoxPro могут храниться как сами OLEобъекты, так и связи с этими объектами. И вот именно от этого будет зави сеть, каким образом будет запоминаться и обновляться информация о дан ном объекте после того, как он будет помещен в таблицу. При внедрении объекта в таблице Visual FoxPro хранится сам объект. Если дважды щелкнуть на таком объекте, то откроется приложение, в котором данный объект был создан. При этом, используя данное приложение, объ ект можно редактировать, после чего все внесенные в него изменения будут сохранены в таблице. Несколько иная ситуация возникает при связывании объекта — в таблице хранится только ссылка о месте расположения исходного файла, а сами данные хранятся в этом файле. Данные будут обновлены только в случае обновления исходного файла. Приложение, в котором объект был создан, называется приложение-сервер, а приложение, в которое данный объект внедряется — приложение-клиент. Так что же мы можем назвать OLE-объектом? Я думаю, что в свете изло женного ранее нетрудно догадаться, что этим самым объектом может быть практически любой объект, созданный в приложениях Windows, поддержи вающих технологию OLE. Например, документ Word или электронная таб лица Excel. Файл звукозаписи или видеоизображение. Точечный рисунок, наконец. Вот в качестве примера использования OLE-объектов мы и рас смотрим внедрение и связывание рисунков в наши таблицы. В качестве ри сунков у нас будут выступать фотографии постояльцев отеля Old Fox Hotel.
258
Часть I. Процедурное программирование в Visual FoxP.
OLE-объекты в таблицах хранятся в полях типа General и только там. Если мы откроем такую таблицу в режиме просмотра, мы увидим, что в полях данного типа стоит пометка gen или Gen. Что сие означает? Очень просто — если поле пусто, то при просмотре стоит gen, а если поле содержит OLEобъект, то метка будет выглядеть как Gen (рис. 18.1).
Рис. 18.1. Таблица, содержащая поля G e n e r a l
Для вставки нового объекта в поле General необходимо дважды щелкнуть мышью на пометке gen, после чего откроется окно редактирования данного поля (рис. 18.2). Для вставки нового объекта необходимо выбрать пункт Insert Object (Встав ка объекта) из меню Edit (Редактирование), после чего откроется вот такое диалоговое окно — рис. 18.3. Как видно, данное окно содержит две опции: Создать новый и Создать из файла. При установке Создать новый необходимо в списке Тип объекта указать сервер, который мы хотим использовать для создания объекта, и нажать кнопку ОК. После этого будет запущено указанное приложение, с помощью которого мы и создадим наш новый объект. При установке Выбрать из файла внешний вид диалогового окна изменится, и мы можем найти уже готовый файл для использования его в качестве OLE-объекта. Все это теория, а вот теперь переходим к практике.
Урок 18. Внедрение OLE-объектов
Рис. 18.2. Окно редактирования поля типа G e n e r a l
Рис. 18.3. Диалоговое окно Вставка объекта
259
260
Часть I. Процедурное программирование в Visual FoxPro
Внедрение нового OLE-объекта Открываем таблицу, содержащую поля типа General, в режиме просмотра Browse. Ставим курсор на необходимую запись и дважды щелкаем мышью на пометке gen. После открытия диалогового окна укажем в нем Paintbrush Picture (Рисунок Paint) и выполним команду Insert Object (Вставить объект). После этого откроется указанное приложение, в котором можно создать изображение. Чтобы никого не обидеть, проведем данный эксперимент на авторе (рис. 18.4).
Рис. 18.4. Это автор
Чтобы отредактировать изображение, а в данном случае это просто необ ходимо, нужно выбрать команду Точечный рисунок Object из меню Editj (рис. 18.5). Эта команда имеет подменю, в котором есть два пункта: Изменить и Открыть. Какой выбрать? Да любой, вся разница в том, что при выборе пункта Изменить системное меню приложения-сервера (в нашем случае Paint) будет| встроено в меню Visual FoxPro, а при выборе Открыть откроется приложение-сервер. Мы рассмотрели процесс создания нового объекта, а как быть, если объекты уже существуют (созданы ранее)? В этом случае в диалоговом окне
Урок 18. Внедрение OLE-объектов
261
Вставка объекта нужно вместо опции Создать новый указать опцию Создать из файла. При этом диалоговое окно Вставка объекта примет такой вид — рис. 18.6.
Рис. 18.5. Редактировать объект
Рис. 18.6. Диалоговое окно Вставка объекта при установленной опции Создать из файла
262
Часть I. Процедурное программирование в Visual FoxPro
Рис. 18.7. Диалоговое окно Обзор
Урок 18. Внедрение OLE-объектов
263
Для выбора необходимого файла необходимо воспользоваться кнопкой Об зор, после чего откроется одноименное диалоговое окно, в котором можно выбрать необходимый файл (рис. 18.7). А вот и результат — рис. 18.8.
Связывание OLE-объекта При связывании объекта в таблице Visual FoxPro хранится только ссылка на данный объект, а сам объект располагается в другом месте. Для того чтобы связать OLE-объект с его основной копией, можно воспользоваться уже знакомой командой Insert Object или Paste Special (Специальная вставка). Рассмотрим оба варианта, а ты уж сам решай, какой предпочтительней. Открой приложение-сервер и выполни для связываемого объекта команды Выделить все и Копировать. Этим самым ты поместишь объект в буфер об мена. Теперь открой в таблице окно редактирования для поля General и вы полни команду Paste Special (Специальная вставка) (рис. 18.9).
Рис. 18.9. Диалоговое окно Специальная вставка
Ссылка на указанный объект будет запомнена в соответствующем поле General. При изменении файла-источника будет автоматически обновлен и объект в Visual FoxPro. Для связывания объекта с помощью команды Insert Object необходимо в диалоговом окне Вставка объекта установить флажок Связь (рис. 18.10). Если объект размещен со связью, то связь можно отредактировать или вовсе Удалить с помощью диалогового окна Связи (рис. 18.11). Кнопки, расположенные в данном окне, описаны в табл. 18.1.
264
Часть I. Процедурное программирование в Visual FoxPro
Рис. 18.10. Установка связи в диалоговом окне Вставка объекта
Рис. 18.11. Диалоговое окно Связи
Таблица 18.1. Кнопки окна Связи Кнопка
Описание
Обновить сейчас
Обновляет связь
Открыть источник
Открывает исходный файл
Сменить источник
Заменяет исходный файл
Разорвать связь
Разрывает связь. После этой процедуры, естественно, ни о каком обновлении объекта не может быть и речи
Урок 18. Внедрение OLE-объектов
265
Удаление OLE-объекта Ну, как говорится, ломать — не строить. Единственная команда меню Edit (Редактирование) — Clear (Очистить) и все, объект "приказал долго жить".
Использование функций GETDIR(), GETFILE() и команда APPEND GENERAL Вот опять перед нами возникает та же проблема: как все это растолковать конечному пользователю? Да в принципе, это ему и не нужно: я имею в виду Insert Object, Paste Special и т. д. Тем более, вряд ли у него будет воз можность при работе с готовым приложением "проникнуть" в системное меню Visual FoxPro. А пользователь требует, чтобы все было легко и понят но. Что же, пользователя надо любить, и поэтому мы предоставим ему воз можность самостоятельно выбирать и вставлять в приложение OLEобъекты. Применительно к нашему случаю, рассмотрим внедрение изобра жений. Создадим новую экранную форму с двумя кнопками: Выбрать и Вставить (рис. 18.12).
Рис. 18.12. Экранная форма для выбора графического файла
Для кнопки Выбрать напишем следующий код в событии click: PUBLIC Myfile GETDIR () Myfile=GETFILE ("BMP")
А для кнопки Вставить напишем следующее: APPEND GENERAL Gphoto FROM SMyfile
Вот и все. Запускаем на выполнение и обсуждаем, как вся эта система будет Работать. При нажатии кнопки Выбрать происходят следующие процессы: создается глобальная переменная Myfile — в ней будет храниться имя вы бранного файла. Далее "срабатывает" функция GetDirO, которая позволяет выбрать каталог (рис. 18.13).
266
Часть I. Процедурное программирование в Visual FoxPro
Рис. 18.13. Диалоговое окно Select Directory
После выбора каталога в работу включается функция GetFileO, которая позволяет выбрать необходимый файл. У данной функции есть несколько параметров, один из них — расширение файла. В нашем примере мы указа ли bmp, и поэтому данная функция будет отображать только файлы с ука занным расширением (рис. 18.14).
Рис. 18.14. Диалоговое окно Open
Урок 18. Внедрение OLE-объектов
267
Если применить данную функцию без параметров, в диалоговом окне будут отображены все имеющиеся в данном каталоге файлы. Файлы выбраны, и остается только вставить их в соответствующую таблицу с помощью следующей команды: APPEND GENERAL Gphoto FROM SMyfile
После команды APPEND GENERAL следует указать имя поля General, а после ключевого слова FROM пишут имя файла, можно с указанием пути. Но мы в данном случае не стали явно прописывать имя, а, воспользовавшись макро подстановкой (&), передали в данную команду значение переменной &Myfile.
Конечно, здесь еще нужно предусмотреть, чтобы объект "попал" в нужную таблицу и в нужную запись, но это, как говорится, уже "дело техники".
УРОК 19
Использование компонентов ActiveX и библиотек классов До сих пор мы использовали только те элементы управления, которые дос тупны из различных панелей управления Visual FoxPro. Это, так сказать, стандартные элементы управления, входящие в состав Visual FoxPro. Но, как часто бывает в жизни, здесь мы с тобой видим только надводную часть "айсберга", а все остальное пока от нас скрыто... Улавливаешь, о чем это я?! Правильно, кроме уже известных нам элементов управления существует множество других, как входящих в состав Visual FoxPro, так и разработан ные сторонними фирмами. Те элементы управления, которые входят в со став Visual FoxPro, находятся в специальных каталогах, которые называются библиотеками классов. В Visual FoxPro эти библиотеки объединены под об щим названием — Visual FoxPro Foundation Classes (Основные классы Visual FoxPro). Для чего это вообще все нужно? Для того чтобы облегчить нам с тобой процесс создания приложений, и сейчас мы разберем, каким же обра зом это происходит.
Использование библиотек классов Чтобы добраться до необходимой нам библиотеки, воспользуемся уже хо рошо знакомой нам панелью инструментов Form Controls, а именно кноп кой View Classes (Просмотр классов) (рис. 19.1). При нажатии этой кнопки мы увидим меню, содержащее три пункта: Add (Добавить), Standard (Стандартные), ActiveX Controls (Элементы управления ActiveX).
Рис. 1 9 . 1 . Нам нужна ЭТА кнопка!
Урок 19. Использование компонентов ActiveX и библиотек классов
269
По умолчанию галочкой отмечен пункт Standard (Стандартные), и на пане ли Form Controls отображены стандартные элементы управления, которыми мы уже пользовались. Чтобы добавить внешнюю библиотеку классов, необ ходимо выбрать пункт меню Add (Добавить). При этом откроется диалого вое окно Open (Открыть), в котором нам нужно указать файл необходимой библиотеки. Библиотеки классов имеют расширение vex. В данном случае нас будет интересовать каталог classes, в котором "лежат" четыре библиотеки классов Visual FoxPro (рис. 19.2).
Рис. 19.2. Диалоговое окно Open. Именно в нем мы можем выбрать необходимую библиотеку
Укажем библиотеку buttons.vcx. Она содержит кнопки, которые могут ис пользоваться для перемещения по записям таблиц. После выбора необхо димой библиотеки в меню кнопки View Classes (Просмотр классов) на па нели Form Controls (Элементы управления формы) будет добавлен пункт с названием выбранной библиотеки, а стандартные элементы управления бу дут заменены на элементы управления данной библиотеки (рис. 19.3).
Рис. 19.3. Измененная панель Form Controls
Часть I. Процедурное программирование в Visual FoxPro
270
Рассмотрим элементы управления, входящие в состав библиотеки классов buttons.vcx — табл. 19.1. Таблица 19.1. Элементы управления библиотеки buttons.vcx Элемент mailbtn
Описание С помощью этой кнопки можно отправить данные по электрон ной почте Группа кнопок для перемещения по записям таблицы
vcr cmdok cradhelp
Кнопка ОК Кнопка Help Кнопка Cancel
cmdcancel
Все эти элементы можно размещать в экранных формах точно так же, как и стандартные элементы управления (рис. 19.4).
РИС. 19.4. Фрагмент нашей экранной формы
Все, элемент управления добавлен в форму, и что самое интересное, он полностью "готов к употреблению". Попробуй, пощелкай по кнопкам. Все работает, происходит перемещение по записям таблицы и обновление эк ранной формы. И ничего выдумывать не надо! Еще один способ использования внешних библиотек и элементов управле ния — применение галереи компонентов, в которой "собраны" все эти са мые основные классы (Foundation Classes). Открыть галерею компонентов можно, воспользовавшись пунктом систем ного меню Tools | Component Gallery (рис. 19.5). Для добавления необходимого элемента в экранную форму нужно нажать правую кнопку мыши и выбрать пункт контекстного меню Add To Form
Урок 19. Использование компонентов ActiveX и библиотек классов
271
(Добавить в форму). Можно также просто "ухватить" его мышью и перета щить на экранную форму. ' Еше одним способом размещения в форме элементов управления из внеш них библиотек классов является использование Class Browser (Браузер клас-
Рис. 19.5. Диалоговое окно Component Gallery
Рис. 19.6. Диалоговое окно Class Browser
272
Часть I. Процедурное программирование в Visual FoxPro
сов) (рис. 19.6). Открыть его можно, воспользовавшись одноименным пунк том меню Tools (Инструменты). Перенести выбранный элемент в экранную форму можно точно так же, как и при использовании галереи компонентов.
Компоненты ActiveX Компоненты ActiveX представляют собой объекты, включающие в себя данные и код. Их можно использовать так же, как и элементы управления Visual FoxPro. Единственное их отличие от базовых компонентов Visual FoxPro состоит в том, что они создаются не в среде FoxPro, а с помощью других средств разработки, например Visual C++. А главным преимуществом является то, что их много] Их разработкой занимаются все, кому не лень — как коммерческие организации, так и программисты. Точное количество существующих компонентов ActiveX, наверное, одному Богу из вестно... Ладно, лирику в сторону, переходим к практике. Для выбора необходимых компонентов ActiveX необходимо воспользоваться пунктом ActiveX Controls (Элементы управления ActiveX) из контекстного меню кнопки View Classes (Просмотр классов) панели Form Controls (Элементы управления), после чего появится вот такое сообщение — рис. 19.7.
Рис. 19.7. Предупреждающее сообщение
Ничего страшного, просто наш Лис просит указать, какие именно элементы управления мы собираемся использовать, и просит воспользоваться пунктом Options (Опции) из системного меню Tools (Инструменты) для выбора ком понентов. Что ж, так и поступим — рис. 19.8. В списке Selected мы видим все доступные на нашем компьютере компо ненты ActiveX. Для того чтобы подключить дополнительные компоненты, скажем, с компакт-диска, необходимо воспользоваться кнопкой Add (Доба вить). А для выбора уже имеющихся элементов достаточно отметить их кре стиками в списке Selected и нажать кнопку ОК. После этой процедуры мы без хлопот можем добавить наши элементы на панель Form Controls. Вот и давай выберем несколько наиболее часто при-
Урок 19. Использование компонентов ActiveX и библиотек классов
273
меняемых в приложениях компонентов ActiveX. В качестве примера будем использовать следующие компоненты (рис. 19.9): • Точечный рисунок; • Документ Word; • Презентацию Power Point; • Microsoft Slider Control; • Microsoft ProgressBar Control; • Calendar Control.
Рис. 19.8. Диалоговое окно Options. Вкладка Controls
Рис. 19.9. Мы разместили необходимые элементы на панели Form Controls
Начнем с первых трех. Для этого создадим новую экранную форму с тремя вкладками (рис. 19.10). Разместив на первой вкладке компонент точечный рисунок, вызовем контек стное меню, в котором выберем пункт Точечный рисунок Object, а затем оп цию Открыть или Изменить
274
Часть I. Процедурное программирование в Visual FoxPro
Рис. 19.10. Форма стремя элементами ActiveX
При выборе пункта Открыть запустится приложение-сервер (в данном слу чае Paint), в котором откроется созданный рисунок. Если же выбрать опцию Изменить, то к панелям инструментов Visual FoxPro добавятся панели инст-| рументов Paint, и можно приступить к редактированию или созданию ри сунка. Точно такие же манипуляции можно проделать и с остальными элементами на вкладках нашей формы (рис. 19.11, 19.12). Теперь рассмотрим использование остальных объектов ActiveX. Элемент ProgressBar предназначен для визуального отображения какогонибудь процесса. Например, происходит сканирование большой таблицы, в ходе которого с данными выполняются какие-либо действия. Процесс мо жет занимать довольно долгий промежуток времени, и для того чтобы поль зователь мог следить за ходом выполнения данного процесса, можно использовать этот элемент. Создадим новую таблицу с одним полем и запол ним ее следующим образом: SELECT Table1 FOR 1=1 ТО 10000 APPEND BLANK REPLACE Nnumeric WITH RECNO() ENDFOR
Урок 19. Использование компонентов ActiveX и библиотек классов
Рис. 19.11. Работа с Word
Рис. 19.12. Работа с PowerPoint
275
276
Часть I. Процедурное программирование в Visual FoxPro
Теперь создадим новую экранную форму и назначим эту таблицу в качестве источника данных. Разместим в форме наш элемент ActiveX и обычную командную кнопку (рис. 19.13).
Рис. 19.13. Пример использования элемента P r o g r e s s B a r
Если щелкнуть на данном элементе правой кнопкой, откроется контекстное меню, в котором можно настроить некоторые свойства данного компонента (рис. 19.14, 19.15).
Рис. 19.14. Контекстное меню для настройки свойств элемента P r o g r e s s B a r
В окне свойств элемента ProgressBar мы можем установить такие парамет ры, как: максимальное и минимальное значения, вид указателя мыши| стиль отображения объекта и т. д. В событии click для кнопки Сканировать напишем следующее: SELE TABLE1 THISFORM.OLEC0NTROL1.MAX=RECCOUNT() SCAN REPLA NNUMERIC WITH NNUMERIC+1 THISFORM.OLECONTROL1.VALUE=RECNO() ENDSCAN
Нетрудно догадаться, что oiecontroii не что иное, как имя нашего объекта ProgressBar. На этом простом примере видно, каким образом можно использовать данный компонент для визуализации тех или иных процессов.
Урок 19. Использование компонентов ActiveX и библиотек классов
Рис. 19.15. Диалоговое окно настройки свойств элемента P r o g r e s s B a r
277
Рис. 19.16. Форма с элементом
Slider
Компонент ActiveX, именуемый как slider, представляет собой шкалу с двигающимся маркером. Обычно он используется в различных программахплеерах для регулировки уровня громкости, в эквалайзерах и т. д. Но, тем не менее, мы также можем использовать его в своих формах. Давай обра тимся к нашей новой форме, удалим из нее предыдущий компонент и доба вим элемент slider и объект Grid (рис. 19.16). Теперь обратимся непосредственно к самому ActiveX-компоненту: в свойст ве mit данного объекта пропишем: THIS.MIN-1 THIS.MAX=RECCOUNT() В СОбыТИИ CHANGE: MYREC=THIS.VALUE SELE TABLE1 GO MYREC THISFORM.REFRESH()
Запускаем форму (рис. 19.17). А вот еще один (шуточный) пример использования slider — мы располо жим на форме три таких элемента и будем с их помощью изменять пара метры отображения объекта Grid (рис. 19.18). В данном случае в событии change мы пишем следующий код: • для первого: THIS FORM.GRIDl.BACKCOLOR=RGB(THIS.VALUE,THIS.VALUE,THIS.VALUE)
278
Часть I. Процедурное программирование в Visual FoxPro
• для второго: THISFORM.GRID1.FORECOLOR=RGB(THIS.VALUE,THIS.VALUE, THIS.VALUE)
• для третьего: THISFORM.GRIDl.FONTSIZE=THIS.VALUE
Более того, для двух первых объектов необходимо установить свойство Мах=255, а ДЛЯ т р е т ь е г о Мах=70, Min=8.
Рис. 19.17. Перемещение по записям с помощью элемента S l i d e r
Рис. 19.18. С помощью компонентов ActiveX пользователь настраивает параметры отображения данных
Урок 19. Использование компонентов ActiveX и библиотек классов
279
Использование календаря Одним из интересных примеров применения объектов ActiveX является ис пользование календаря. С помощью данного элемента мы можем вводить даты в наши таблицы. Создадим новую форму, источником данных для ко торой будет являться таблица names, и добавим в нее указанный компонент ActiveX (рис. 19.19).
Рис. 19.19. Форма со встроенным календарем
Указав в качестве источника данных соответствующее поле, можно вводить даты с помощью календаря.
УРОК 20
Экспорт и импорт данных В современном делопроизводстве широчайшее распространение получили такие офисные приложения, как Word и Excel. Наш приятель Лис также шагает в ногу со временем и умеет передавать данные из своих таблиц в другие приложения, а также принимать данные из некоторых приложений. I
Лис и Excel Самый простой способ передать данные из Visual FoxPro в Excel — восполь зоваться командой Export (Экспорт) из системного меню File (Файл) (рис. 20.1).
Рис. 20.1. Для передачи данных используется соответствующий пункт системного меню
После выполнения данной команды мы увидим диалоговое окно Export (Экспорт) (рис. 20.2).
Урок 20. Экспорт и импорт данных
281
Рис. 20.2. Диалоговое окно Export
В раскрывающемся списке Туре (Тип данных) следует указать, в какой тип файлов будет осуществляться передача данных. В нашем случае мы выбрали следующее — см. рис. 20.2. В поле ввода То (Куда) необходимо указать местоположение и имя файла, который будет "принимать" данные. Здесь можно как просто вписать имя будущего файла, так и воспользоваться расположенной справа кнопкой, которая открывает диалоговое окно Save As (Сохранить как) (рис. 20.3).
Р и с . 20.3. Диалоговое окно Save As позволяет задать имя файла
Далее, в поле ввода From (Откуда) необходимо указать имя таблицы, из ко торой будут переданы данные. °се, да не все... По умолчанию в файл-приемник будут переданы все записи и все поля указанной таблицы. Иногда такое "изобилие" просто ни к чему, и для задания условий передачи мы воспользуемся кнопкой Options (Опции) (рис. 20.4).
282
Часть I. Процедурное программирование в Visual FoxPro
Рис. 20.4. Диалоговое окно Export Options
В данном диалоговом окне мы видим четыре кнопки, которые позволяют задать условия для экспорта исходного файла. При нажатии кнопки Scope (Диапазон) появляется еще одно диалоговое окно, которое позволяет вы брать диапазон передаваемых записей (табл. 20.1). Таблица 20.1. Параметры окна Scope Параметр
Описание
АН (Все)
Все записи таблицы
Next (Следующие)
Следующие после текущей. Число указывается в поле ввода
Record (Запись)
Запись номер...
Rest (Оставшиеся)
Все записи после текущей
При нажатии кнопок For (Для) и While (Пока) появится уже хорошо знаков мое нам окно Expression Builder (Построитель выражений), в котором можно задать необходимые условия. Кнопка Fields (Поля) позволяет выбрать те поля исходной таблицы, кото рые будут переданы (рис. 20.5).
Рис. 20.5. Диалоговое окно Field Picker
Урок 20. Экспорт и импорт данных
283
В окне Field Picker находится два списка. В левом отображены все поля ис ходной таблицы, в правом — те, которые будут передаваться в файлприемник. Для переноса полей в правый список используется кнопка Move (Перенести). Наконец, когда все "формальности" улажены, можно нажать кнопку ОК и посмотреть, что там у нас из всего этого получилось (рис. 20.6).
Рис. 20.6. Данные экспортированы в Excel
Да, все хорошо, но опять возникает проблема с нашим пользователем... Ему-то, бедняге, как это все проделать? А для него мы создадим поле ввода и кнопочку — пусть себе спокойно работает! 1. Создаем новую форму с источником данных names.dbf (рис. 20.7). 2. Пишем код для события click кнопки Экспорт (листинг 20.1). Листинг20.1. Кнопка Экспорт IF
EMPTY(Thisform.Text1.Value)
=MESSAGEBOX("УКАЖИТЕ ИМЯ ФАЙЛА","СШИБКА") ELSE SELE Names
284
Часть I. Процедурное программирование в Visual FoxPro
My_File=ALLTR(Thisform.Textl.Value) EXPORT TO &My_File TYPE XLS ENDIF
Рис. 20.7. Экранная форма для экспорта данных
Вот и все. Чем хорош данный способ? В отличие от предыдущего, здесь по мимо таблиц можно использовать и представления данных. Да и вообще удобнее для пользователя. Ты скажешь, а как же ограничить число переда ваемых полей и записей? Да элементарно — добавь в форму еще несколько элементов управления (например, раскрывающийся список с наименованиями полей, поле ввода для установки фильтра и т. д.), используй макроподстановки и все получится! Это, как говорится, дело техники... Но при данном способе передачи мы просто получаем книгу Excel и все. А если нам нужен "красивый" отчет? Например, такой — рис. 20.8. Чтобы получить такую "красоту", нам необходимо воспользоваться для пе редачи данных механизмом OLE. Код для кнопки Экспорт будет следующим — листинг 20.2. Листинг 20.2. Кнопка Экспорт ("красивый" отчет) Omyexcelreport=CREATEOBJECT("EXCEL.SHEET"; Qmyexcelreport.Application.Visible=.T. Omyexcelreport=Omyexcelreport.Sheets[1] SELE Names WITH Omyexcelreport WITH .Range("Al") .Value="СПИСОК КЛИЕНТОВ"
Урок 20. Экспорт и импорт данных
285
WITH .Font .Bold-.т. .Size=14 ENDWITH ENDWITH ENDWITH Nrow=5 SCAN Nrow=Nrow+l Qmyexcelreport.Cells(Nrow,1).Value=ALLTR(Names.Cfirstname)+; " "+ALLTR(Names.Csecondname); +" "+ALLTR(Clastname) WITH Omyexcelreport WITH .Cells(Nrow,1) WITH .Font IF Names.Csex="M" .Bold-.T. .Colorindex=4 ELSE .Bold=.F. .Colorindex=5 ENDIF ENDWITH ENDWITH ENDWITH ENDSCAN Qmyexcelreport.Visible=.T. RELEASE Omyexcelreport
Но есть и еще один способ. Для этого создадим "еще более красивый" отчет и заполним его значениями из нашей таблицы. Отчет будем создавать в Excel, после чего обязательно сохраним его под каким-либо именем (рис. 20.9). Изменим код кнопки Экспорт таким образом, чтобы данные "попадали" в только что созданный нами новый файл (листинг 20.3). Листинг 20.3. Кнопка Экспорт ("еще более красивый" отчет) Oexcel=CREATEOBJECT("EXCEL.APPLICATION") Oexcel.Workbooks.Open("C:\OLDFOX\MYREPORT") WITH Oexcel • C e l l s (2, ID .Value=DTOC(DATE() ) ENDWITH
286
Часть I. Процедурное программирование в Visual FoxPro
SELE Names Nrow=ll SCAN Nrow=Nrow+l Oexcel.Cells(Nrow,1).Value=ALLTR(Names.Cfirstname)+" "+ALLTR (Names. Csecondname) ; +" "+ALLTR(Names.Clastname) Oexcel.Cells(Nrow,2).Value=Names.Idrooms Oexcel.Cells(Nrow,3).Value=DTOC(Names.Darrdate) Oexcel.Cells(Nrow,4).Value=DTOC(Names.Ddepdate) ENDSCAN Oexcel.Visible=.T.
Результат — на рис. 20.10.
Рис. 20.8. "Красивый" отчет
Таким образом, Visual FoxPro предоставляет нам широкий выбор возможно стей передачи данных из своих таблиц в электронные таблицы Excel. Более того, мы можем решать и обратную задачу — принимать в таблицы Visual FoxPro данные из других приложений. Рассмотрим это на примере Excel.
Урок 20.
Экспорт и импорт данных
Рис. 20.9. Мы создали шаблон будущего отчета
Рис. 20.10. Мы поместили данные из таблицы в заранее созданный файл Excel
287
288
Часть I. Процедурное программирование в Visual FoxPro
Допустим, имеется электронная таблица, данные из которой необходимо перенести в таблицу Лиса. (А у нас она есть, это таблица my_excei, которую мы создали на предыдущем занятии.) Для решения данной задачи восполь зуемся пунктом Import (Импорт) системного меню File (Файл). После выбо ра данной команды мы увидим диалоговое окно Import (Импорт) (рис. 20.11).
Рис. 20.11. Диалоговое окно Import
В раскрывающемся списке Туре (Тип файла) указываем, из файла какого! типа мы будем импортировать данные, а в поле ввода From (Откуда) задаем] имя файла. Поле ввода То (Куда) доступно только для чтения и по умолча-j нию там указан путь к каталогу Visual FoxPro. При работе с данным окном удобнее воспользоваться услугами мастера (Import Wizard), что мы и сдела-| ем (рис. 20.12).
Рис. 20.12. Первый шаг работы мастера
Урок 20. Экспорт и импорт данных
289
На данном этапе мастер просит указать тип импортируемых данных в спи ске File Type (Тип файла), источник данных Source File, а также файл, в который будет произведен импорт данных (Destination File). Причем этот самый Destination File можно как выбрать, включив опцию Existing table (Существующая таблица), так и создать новый — опция New table (Новая таблица). В данном случае будет открыто диалоговое окно Save As (Сохра нить как), в котором нужно задать имя создаваемого файла. На следующем этапе (рис. 20.13) мастер просит указать, будет ли наша таб лица включена в состав базы данных (опция Add my table to the following database), или это будет свободная таблица (Create my table as a stand-alone free table).
Р и с . 20.13. Определение типа таблицы
На втором шаге (рис. 20.14) мы можем указать, с какой строки начать им порт данных (Begin import at row) и на какой строке расположить наимено вания полей (Field names in row). А зачем нам в таблице их наименования? Ставим ноль. В списке Worksheet можно указать конкретный лист элек тронной таблицы, в нашем случае он один-единственный. Также можно задать формат данных (опция Data Format). На третьем шаге работы мастера (рис. 20.15) мы можем задать типы полей нашей таблицы и определить заголовки, которые будут отображены при Просмотре таблицы. 10 ч»..
290
Часть I. Процедурное программирование в Visual FoxPro
Рис. 20.14. Второй шаг работы мастера
Рис. 20.15. Третий шаг работы мастера
Далее можно определить дополнительные параметры (рис. 20.16): • Code Page — это кодовая страница (Для Windows — 1251); • Currency Symbol — "денежный" символ, будет отображаться с полями ти па Currency;
ч
Урок 20. Экспорт и импорт данных
291
• 1000 Separator — разделитель тысяч; • Decimal Separator — разделитель между целой и дробной частью чисел; • Date Format — формат отображения дат. И наконец, долгожданный финиш (рис. 20.17).
Рис. 20.16. Определение дополнительных параметров
Рис. 20.17. Последний этап работы мастера
292
Часть I. Процедурное программирование в Visual FoxPro
После нажатия кнопки Finish (Готово) произойдет импорт данных, в чем мы можем легко убедиться, открыв для просмотра нашу таблицу (рис. 20.18).
Рис. 20.18. Эти данные получены из электронной таблицы Excel
А что это мы все про Excel? Кроме Excel существует множество других приложений, с которыми Лис может обмениваться данными. Вот, например, его младший братец FoxPro for DOS наотрез отказывается воспринимать таблицы, созданные в Visual FoxPro! Ну, вроде все нормально, обычная таблица, dbf, все как положено — ан нет! "Ругается", пишет что это "Not a database file". Вот тут-то и приходят на помощь экспортно-импортные oпeрации. (Хотя в данном конкретном случае экспорт и не нужен — "визуаль ный" Лис вполне адекватно воспринимает таблицы, созданные "Досов ским" Лисом.) Более того, чтобы передать таблицу в формат DOS, доста точно такой команды: COPY My_Table TO My_Dos_Table TYPE FOXPLUS AS 886
УРОК 21
Наборы форм В Visual FoxPro можно объединить несколько форм в набор форм FormSet, поведение которого можно контролировать как для единого объекта. При этом у нас появляется возможность одновременного отображения на экране всех входящих в набор форм, их перемещение, обновление и т. д. Самое главное, весь этот "комплект" может работать с единой средой дан ных. Создадим три экранных формы. В каждой из них расположим объект Grid и назначим источники данных. Для первой — countries.dbf (рис. 21.1).
Рис. 21.1. Первая экранная форма будущего набора форм
Теперь выполним команду Create FormSet (Создать набор форм) из меню Form (Форма). Наша форма стала не просто формой, а формой, входящей в состав набора FormSet. Для того чтобы добавить в набор новые экран ные формы, необходимо выполнить команду Add New Form (Добавить но вую форму) из системного меню Form (Форма). Так и поступим, указав
294
Часть I. Процедурное программирование в Visual FoxPro
в качестве источника данных для новой формы таблицу городов cities.dbf (рис. 21.2).
Рис. 21.2. Мы добавили еще одну форму
Таким же образом добавим еще одну форму, назначив ей в качестве источ ника данных таблицу depclients.dbf (рис. 21.3).
Рис. 21.3. Набор форм в окне конструктора
Обрати внимание на то, что у всего набора форм общий источник данных. . Сохраним наш набор под любым именем и запустим на выполнение (рис. 21.4).
Урок 21. Наборы форм
295
Рис. 21.4. Использование набора форм
УРОК 22
Создание меню приложения Графический интерфейс — это то, что пользователь видит в первый момент после запуска какого-нибудь приложения, и наша с тобой задача состоит в том, чтобы сделать этот самый интерфейс как можно более функциональ-; ным, красивым и удобным для пользователя. Встречают-то по одежке... А т. к. современный пользователь работает с приложениями Windows, он просто не может представить свою работу без системы меню. Как и все другие компоненты приложения Visual FoxPro, меню можно соз дать как программно (написать код "вручную"), так и воспользоваться соот ветствующим набором инструментов. Но сначала давай определим, что не посредственно входит в понятие системы меню. Система меню включает в себя линейку меню, состоящую из пунктов линей ки меню (другое их название — заголовки подменю), самих подменю или всплывающих меню (popup-menu) и пунктов меню (рис. 22.1). Для того чтобы понять, как вся эта конструкция будет работать, мы сейчас попробуем написать программный код для генерации простейшего меню. Сразу оговорюсь, что в среде Visual FoxPro обычно для создания меню ис пользуется соответствующий конструктор (Menu Designer), а код, написан ный "вручную", встречается довольно редко. Но, тем не менее, мы научимся это делать. Основных команд для создания меню не так уж и много: DEFINE PAD — ДЛЯ создания линейки меню, DEFINE BAR — для определения заголовков подме ню и DEFINE POPUP — для создания самих подменю (листинг 22.1). Листинг 22.1. Создание меню * Определим главное меню DEFINE MENU Mymenu BAR && ЗДЕСЬ Mymenu - ИМЯ НАШЕГО МЕНЮ DEFINE PAD Padone OF Mymenu PROMPT "ФОРМА"&& определяем пункты линейки DEFINE PAD Padtwo OF Mymenu PROMPT "ОТЧЕТ"
Урок 22.
Создание меню приложения
297
ON PAD Padone OF Mymenu ACTIVATE POPUP Popone && определяем действия при && выборе пункта линейки ON PAD Padtwo OF Mymenu ACTIVATE POPUP Poptwo DEFINE POPUP Popone && определяем первое всплывающее меню DEFINE BAR 1 OF Popone PROMPT "ЗАПУСК ЭКРАННОЙ ФОРМЫ" && определяем && заголовки пунктов всплывающего меню DEFINE BAR 2 OF Popone PROMPT "ВЫХОД" ON SELECTION BAR 1 OF Popone DO FORM Main && определяем действия && при выборе пункта всплывающего меню ON SELECTION BAR 2 OF Popone QUIT DEFINE POPUP Poptwo && определяем второе всплывающее меню, пункты подменю && и действия при их выборе DEFINE BAR l OF Poptwo PROMPT "ПЕЧАТЬ ОТЧЕТА" DEFINE BAR 2 OF Poptwo PROMPT "ПРОСМОТР ОТЧЕТА" ON SELECTION BAR 1 OF Poptwo DO Procl ON SELECTION BAR 2 OF Poptwo REPORT FORM Myreport PREVI ACTIVATE MENU Mymenu && активируем линейку меню PROCEDURE Procl && а это внешняя процедура SELE Mytab SET ORDER TO Myorder REPORT FORM Myreport TO PRINTER
Рис. 22.1. Пример системы меню
Часть I. Процедурное программирование в Visual FoxPro
298
Как видишь, ничего сложного: сначала определяем линейку меню с по-: мощью команды DEFINE MENU <Имя_Меню> BAR
Затем определяем количество пунктов линейки и их заголовки: DEFINE PAD
<Имя_Пункта>
OF <Имя_Меню> PROMPT " З а г о л о в о к _ п у н к т а "
Теперь следует определить действия, которые могут происходить при выбо ре П у н к т а М е н ю : ON PAD <Имя__Пункта> OF <Имя__Меню>
После этого следует какая-нибудь команда Visual FoxPro. Например, вызов всплывающего подменю, как в нашем примере: ON PAD PADONE OF MYMENU ACTIVATE POPUP POPONE
Если указан вызов подменю, то его (подменю), естественно, нужно создать: DEFINE
POPUP
<Имя_Всплывакщего_Меню>
и определить его пункты: DEFINE BAR l OF Poptwo PROMPT "ИМЯ_ПУНКТА1" DEFINE BAR 2 OF Poptwo PROMPT "ИМЯ_ПУНКТА2"
После этого определяем действия для пунктов всплывающего меню: ON SELECTION BAR 1 OF <Имя_Всплывающего_Меню>
...
<КОМАНДА>
Можно как просто написать команду, так и подключить какую-нибудь| внешнюю процедуру или функцию: ON SELECTION BAR 1 OF Poptwo DO Procl
После этого необходимо активировать созданную систему меню, выполнив команду ACTIVATE MENU <Имя_Меню>
Получившееся меню представлено на рис. 22.2. Если выполнение нашей программы для генерации меню происходит в главном окне Visual FoxPro, то наше меню заменит системное меню. Чтобы вернуться обратно в системное меню Visual FoxPro, необходимо деактивировать наше меню, выполнив команду: DEACTIVATE MENU <Имя_Меню>
затем удалить его: RELEASE MENUS <Имя_Меню> EXTENDED
и выполнить команду, которая восстановит прежнее системное меню: SET SYSMENU TO DEFAULT
Урок 22. Создание меню приложения
299
Рис. 22.2. Мы только что создали свое меню
Использование конструктора меню Конструктор меню запускается так же, как и все остальные конструкторы Visual FoxPro, поэтому не будем повторяться. Каким бы способом его не запустили, на экране появится диалоговое окно New Menu (Новое меню) (рис. 22.3).
Рис. 22.3. Диалоговое окно New Menu
300
Часть I. Процедурное программирование в Visual FoxPro
Здесь нам предлагается два варианта меню: Menu — обычное меню в виде строки и Shortcut — всплывающее контекстное меню. Начнем с обычного (рис. 22.4).
Рис. 22.4. Конструктор меню
Конструктор меню включает в себя область, предназначенную для форми рования меню (это где написано Prompt (Наименование), Result (Результат) и Options (Опции)), раскрывающийся список Menu level (Уровень меню) и четыре командные кнопки. В поле Prompt (Наименование) вводятся названия пунктов меню, раскрывающийся список Result (Результат) предназначен для определения действий, происходящих при выборе пункта меню, а с помощью диалогового ок на Prompt Option (Опции наименования), которое открывается при нажатии кнопки Option, можно задать дополнительные параметры для данного эле мента меню. Кнопки, расположенные в правой части конструктора, имеют следующее назначение — табл. 22.1. Таблица 22.1. Кнопки конструктора меню Кнопка
Описание
Insert (Вставить)
Добавляет в меню новый пункт
Insert Bar (Вставить команду системного меню)
Позволяет разместить в пользовательском меню команды системного меню Visual FoxPro
Delete (Удалить)
Удаляет указанный пункт меню
Preview (Предварительный просмотр)
Предварительный просмотр внешнего вида меню
Что ж, начнем потихоньку. Создаваемое нами меню не будет иметь отношения к нашему проекту с отелем — это будет полностью абстрактная сис-
Урок 22. Создание меню приложения
301
тема, используемая только в качестве примера. Определяем пункты линейки меню — рис. 22.5.
Рис. 22.5. Определение пунктов меню
Мы определили пункты линейки меню, а заодно и "горячие" клавиши. "Го рячая" клавиша используется для активизации соответствующего пункта меню — нажимаем
Описание
Command (Команда)
Выполняется определенная команда
Pad Name (Наименование строки меню)
Никаких действий. Может использоваться в качестве дополнительного пояснения
Submenu (Подменю)
Раскрывается связанное с данным пунктом Рорирменю
Procedure (Процедура)
Выполняется определенная процедура
Command (Команда) При выборе данного пункта с правой стороны появится поле ввода для записи команды (рис. 22.6).
Часть I. Процедурное программирование в Visual FoxPro
302
Рис. 22.6. Поле для ввода команд
Submenu (Подменю) При выборе данного пункта справа появится кнопка Create (Создать), при нажатии которой откроется диалоговое окно для создания соответствующе го подменю (рис. 22.7).
Рис. 22.7. Создание подменю
Для определения дополнительных параметров пункта меню используется диалоговое окно Prompt Options (Опции наименования) (рис. 22.8) — см. табл. 22.3. Таблица 22.3. Параметры окна Prompt Options Параметр
Описание
Skip for (Пропустить)
Блокировка пункта меню
Message (Сообщение)
Сообщение, отображаемое в строке состояния
Pad Name (Имя пункта)
Имя пункта меню
Comment (Комментарий)
Комментарий для пункта меню
В области Shortcut можно задать клавиши быстрого вызова, а область Negotiate содержит два раскрывающихся списка: • Container (Контейнер) — определяет расположение меню при редактиро вании OLE-объекта;
Урок 22.
Создание меню приложения
303
• Object (Объект) — определяет расположение меню при выполнении при ложений Active Document.
Рис. 22.8. Диалоговое окно Prompt Options
Определение клавиш быстрого доступа Клавиши быстрого доступа похожи на "горячие" клавиши, но между ними есть и отличия. Например, при назначении "горячих" клавиш используются только символы, входящие в текст пункта меню, а при назначении клавиш быстрого доступа можно использовать функциональные клавиши, клавиши символов и комбинации клавиш. "Горячие" клавиши работают в сочетании с клавишей
304
,
Часть I. Процедурное программирование в Visual FoxPro
Рис. 22.9. Определение клавиши быстрого доступа
Рис. 22.10. Вставка разделителей пунктов меню
Рис. 22.11. Меню с разделителями
Урок 22. Создание меню приложения
305
В поле ввода Pad Name (Имя пункта) можно ввести желаемое наименование для данного поля ввода. Делается это для улучшения читаемости программ ного кода, сгенерированного конструктором отчетов. Для блокировки пунктов меню используется поле ввода Skip For (Пропус тить для). При нажатии расположенной справа кнопки откроется диалого вое окно Expression Builder (Построитель выражений), в котором можно за дать условие для блокировки пункта меню. Для разделения пунктов меню по определенным категориям можно использовать символы \-. Как это де лается, отображено на рис. 22.10, 22.11.
Определение параметров меню После создания меню можно определить те процедуры, которые будут вы полняться перед запуском меню, после выхода из него, а также указать рас положение строки меню. Для этого нужно вызвать диалоговое окно General Options (Основные параметры) из системного меню View (Вид) (рис. 22.12).
Рис. 22.12. Диалоговое окно General Options
В поле ввода Procedure (Процедура) можно ввести фрагмент программы, который будет выполняться при запуске меню. Флажок Setup позволяет от крыть окно для редактирования той программы, которая будет выполняться при запуске меню, а флажок Cleanup — для редактирования программы, выполняемой при выходе из меню. При установленном флажке Top-Level Form (Форма верхнего уровня) меню будет располагаться в форме верхнего Уровня, в противном случае — в главном окне Visual FoxPro. Группа переключателей Location (Расположение) позволяет выбрать вариан ты расположения строки меню (табл. 22.4).
306
Часть I. Процедурное программирование в Visual FoxPro Таблица 22.4. Варианты расположения строки меню
Параметр
Описание
Replace (Заместить)
Меню замещает системное меню
Append (Добавить)
Меню добавляется в системное меню
Before (Вставить перед)
Меню вставляется перед пунктом системного меню
After (Вставить после)
Меню вставляется после пункта системного меню
Генерация меню Чтобы меню можно было использовать в приложении, сначала его нужно сгенерировать. Для этого используется пункт системного меню Menu (Ме ню) и диалоговое окно Generate Menu (Генерация меню) (рис. 22.13).
Рис. 22.13. Диалоговое окно Generate Menu
После нажатия кнопки Generate (Генерация) произойдет процесс генерации меню и... все, наше меню готово!
Запуск меню Существует несколько способов запустить меню на выполнение: • в окне проекта приложения установить курсор на наименования нашего меню и нажать кнопку Run; • в командном меню написать следующую команду: DO <имя_меню>. mpr
Запускаем наше меню и... сталкиваемся с "сюрпризом" — рис. 22.14. В чем дело? А все дело в назначении "горячих" клавиш. Лис почему-то не желает работать с "горячими" клавишами, назначенными кириллицей, т. е. русскими буквами. Ему, видите ли, латиницу подавай. Ну и подадим — дос таточно переопределить заново "горячие" клавиши. А еще более прос той способ — вообще закомментировать использование "горячих" клавиш (рис. 22.15). И все в порядке (рис. 22.16).
Урок 22.
Создание меню приложения
Рис. 22.14. При запуске меню происходит ошибка
Рис. 22.15. Мы "слегка" поправили код меню
307
308
Часть I. Процедурное программирование в Visual FoxPro
Рис. 22.16. Теперь наше меню вполне работоспособно
Запуск меню в экранной форме В рассмотренном примере мы запускали наше меню в главном окне Visual FoxPro, а теперь рассмотрим работу меню с экранной формой. Создадим произвольную экранную форму и установим для нее свойство showwindow равным 2 — As top level form (Как форма верхнего уровня). В методе i n i t пропишем: DO MENU1.MPR WITH T H I S , . T .
Меню также надо немного "подправить", а именно установить флажок TopLevel Form (Форма верхнего уровня) в диалоговом окне General Options (Основные опции) и снова запустить процесс генерации меню. После этих манипуляций можно запустить нашу форму (рис. 22.17).
Урок 22. Создание меню приложения
309
Рис. 22.17. Меню выполняется в экранной форме
Создание Shortcut-меню Shortcut-меню по сути очень похоже на контекстное меню, вызываемое на жатием правой кнопки мыши. Мы уже не раз с ними встречались в процес се разработки приложения, а теперь и сами научимся создавать нечто по хожее. В диалоговом окне New Menu (Новое меню) нажмем кнопку Shortcut (см. рис. 22.3). Запустится конструктор меню (рис. 22.18).
Рис. 22.18. Создание меню типа Shortcut
Как видно, процесс создания меню типа Shortcut практически ничем не отличается от создания обычного меню. После определения всех пунктов меню необходимо запустить процесс генерации (рис. 22.19).
310
Часть I. Процедурное программирование в Visual FoxPro
Рис. 22.19. Готовое Shortcut-меню
Для того чтобы меню такого типа выполнялось при нажатии правой кнопки мыши, необходимо использовать событие Right Click Event (Щелчок пра вой кнопкой), для которого написать следующую команду: DO <имя меню>.mpr
УРОК 23
Создание справочной системы Для создания справочной системы нашего приложения мы воспользуемся программным продуктом HTML HELP Workshop, который поставляется вместе с Visual FoxPro. С помощью данного приложения, разработанного корпорацией Microsoft, практически любой программист, не прилагая осо бых усилий, сможет создать справочную систему для своего приложения. Если по какой-либо причине у тебя нет данного приложения (хотя оно должно быть на установочном диске Visual FoxPro) — не беда, его можно скачать с сайта производителя: www.microsoft.com/workshop/autor/htnilhelp. Для установки данной системы необходимо дважды щелкнуть мышью на файле самораспаковывающегося архива HTMLHELP.EXE и следовать даль нейшим инструкциям. Главное окно HTML HELP Workshop представлено на рис. 23.1. Посмотрели — теперь закроем. Сейчас мы займемся созданием самих фай лов нашей будущей справки. Как видно из названия, данная система рабо тает с файлами формата HTML. Где их взять? Естественно, нужно создать самостоятельно. Для этого можно использовать любой HTML-редактор (простенький редактор имеется в самой системе HTML Help Workshop). Но гораздо более удобный способ — использовать обычный Word, в котором создать файлы тем справочной системы и сохранить их в формате HTML. Так и поступим — рис. 23.2. После создания всех файлов тем справки запускаем HTML Help Workshop и в меню File (Файл) выбираем пункт New (Новый). В диалоговом окне New (рис. 23.3) можно указать тип создаваемого компо нента справочной системы: Project (Проект), Text (Текст), HTML File (Файл в формате HTML), Table of Contents (Таблица содержания), Index (Индексы). Так как мы создаем новое приложение, нам необходимо вы брать пункт Project (Проект) — рис. 23.4.
312
Часть I. Процедурное программирование в Visual FoxPro
Рис. 23.1. Главное окно HTML HELP Workshop
Рис. 23.2. Мы создаем темы справки в редакторе Word
Урок 23. Создание справочной системы
313
Рис. 23.3. Диалоговое окно New
Р и с . 23.4. Диалоговое окно N e w P r o j e c t
Данный инструмент предназначен для преобразования существующего про екта справочной системы в формате Win Help в формат HTML Help Workshop, а также для включения в проект ранее созданных файлов. Так как у нас пока нет никакого проекта, а есть только отдельные файлы тем, мы не будем отмечать флажок Convert WinHelp Project (Преобразовать про ект WinHelp), а просто нажмем кнопку Далее. На экране появляется сле дующее диалоговое окно (рис. 23.5). На данном этапе необходимо указать имя создаваемого проекта и путь к нему. Для этой цели удобно воспользоваться кнопкой Browse (Обзор). Если у нас есть ранее созданные файлы таблицы содержания, индексов или тем справочной системы, мы можем включить их в состав проекта. А у нас на данный момент есть именно файлы тем (мы их создали в Word) — вот их то и включим, отметив соответствующий флажок (рис. 23.6).
314
Часть I. Процедурное программирование в Visual FoxPro
Рис. 23.5. Диалоговое окно Destination
Рис. 23.6. Диалоговое окно Existing Files
"Укажите, где расположены Ваши файлы тем?" — вот что спрашивает мас тер на данном этапе создания проекта (рис. 23.7). Для добавления файлов в проект используется кнопка Add (Добавить), а для удаления — соответст венно, Remove (Удалить). В результате перед нами появится окно нашего проекта (рис. 23.8). Слева расположены кнопки, назначение которых описано в табл. 23.1.
Урок 23.
Создание справочной системы
Рис. 23.7. Диалоговое окно HTML Files
Рис. 23.8. Диалоговое окно нашего проекта
315
316
Часть /. Процедурное программирование в Visual FoxPro Таблица 23.1. Кнопки вкладки Project
Кнопка
Описание Изменение опций проекта
Change project options Добавление или удаление файлов разделов справки Add / Remove topic files Установка опций Windows Windows definition Информация API API information Просмотр текстов HTML View HTML source Сохранение файлов проекта Save project files
Save project and file compile
Сохранение файлов проекта и их последующая компиляция
Теперь нам необходимо создать таблицу содержания (Table of Contents). Что это такое, понятно из самого определения — данный файл включает в себя наименования тем справочной системы, т. е. содержание. Количество пунктов в данной таблице может быть любым, сколько надо — столько и включаем. Создать эту таблицу можно, воспользовавшись вкладкой Contents (Содержание) — рис. 23.9.
Рис. 23.9. Диалоговое окно создания таблицы содержания
Урок 23. Создание справочной системы
317
Данное диалоговое окно содержит две опции: Create a new contents file (Создать новую таблицу содержания) и Open an existing contents file (От крыть существующую таблицу). Так как никакой таблицы у нас пока нет, выбираем первый пункт. В открывшемся диалоговом окне Save As (Сохранить как) необходимо ука зать имя таблицы, например MY-TABLE.hhc. Имя может быть любым, а вот расширение — только hhc. После этого откроется вкладка Contents (Содер жание) (рис. 23.10).
Рис. 23.10. Вкладка Contents
Слева расположены одиннадцать кнопок, назначение которых пояснено в табл. 23.2. Таблица 23.2. Кнопки вкладки Contents Кнопка
Описание Свойства содержания
Contents properties
318
Часть I. Процедурное программирование в Visual FoxPr Таблица 23.2 (окончание)
Кнопка
Описание Вставка заголовка
Insert a heading Вставка страницы Insert a page Редактирование выделенного Edit selection Удаление выделенного Delete selection Перемещение выделенного вверх Moving selection up Перемещение выделенного вниз Moving selection down Перемещение выделенного вправо Moving selection right Перемещение выделенного влево Moving selection left Просмотр текста HTML View HTML source Сохранение файла Save file
Вставка заголовка добавляет в таблицу строку с пиктограммой — рис. 23.11. В поле ввода Entry title (Введите заголовок) вводим текст заголовка, а с по мощью кнопки Add (Добавить) подключаем соответствующий файл справкиВид пиктограммы можно задать, открыв вкладку Advanced (Дополнитель но) — рис. 23.12. После создания заголовка можно включить и соответствующие данному разделу справки страницы, воспользовавшись кнопкой Insert a page (Вста вить страницу) — рис. 23.13.
Урок 23. Создание справочной системы
Рис. 23.11. Диалоговое окно для вставки заголовка
Рис. 23.12. Вид пиктограммы заголовка можно задать на этой вкладке
319
320
Часть I. Процедурное программирование в Visual FoxPro
Рис. 23.13. Вставка страницы
Рис. 23.14. Диалоговое окно после компиляции файла
Урок 23. Создание справочной системы
321
Теперь мы уже можем скомпилировать наш файл и посмотреть, что из этого получится. Для компиляции воспользуемся кнопкой Save project and file compile, после чего выведется окно отчета о компиляции файла — рис. 23.14. Для просмотра компилированного файла можно воспользоваться пунктом Compiled file (Компилированный файл) из меню View (Просмотр) — рис. 23.15.
Рис. 23.15. Окно нашей справочной системы
Создание предметного указателя Для включения в проект предметного указателя существует два способа: • при создании нового проекта отметить пункт Index (Индекс) в диалого вом окне New (Новый); • в открытом окне проекта перейти на вкладку Index, что мы и сделаем. После определения имени индекса и его расположения откроется соответ ствующая вкладка, содержащая одиннадцать кнопок с пиктограммами (табл. 23.3). П " W 1ПП-)
322
Часть I. Процедурное программирование в Visual FoxPro Таблица 23.3. Кнопки вкладки Index
Добавляем ключевое слово — рис. 23.16. Ключевым словом может быть обычный текст, но его необходимо связать с соответствующим файлом справки, воспользовавшись кнопкой Add (Доба вить), иначе при компиляции возникнет ошибка. Если ключевое слово
Урок 23.
Создание справочной системы
Рис. 23.16. Добавление ключевого слова
Рис. 23.17. В справку добавлен предметный указатель
323
324
Часть I. Процедурное программирование в Visual FoxPro
связано с несколькими страницами — ничего страшного, связать его можно с любым количеством тем справки (как в нашем случае). После компиля ции наша справочная система примет примерно такой вид — рис. 23.17. Так как наше ключевое слово связано с двумя файлами, при нажатии кноп ки Показать появится вот такое диалоговое окно — рис. 23.18.
Рис. 23.18. Диалоговое окно выбора раздела справки
Создание контекстно-зависимых разделов справки Допустим, есть некая экранная форма (рис. 23.19).
Рис. 23.19. Пример формы
Для того чтобы при вызове справочной системы сразу открывалась страни ца, связанная только с этой формой, необходимо выполнить указанные далее действия. У экранной формы есть свойство HeipContextiD. Присвоим данному свойству уникальное числовое значение, например 50. В метод init экранной формы вставим следующий код: This.SetAll ("HeipContextiD",50). В ме тоде обработки события click для кнопки Справка пропишем: Help ID This.HeipContextiD.
Урок 23. Создание справочной системы
325
.
Создадим еще одну HTML-страницу, содержащую раздел справки, связан ный с данной формой, пусть она будет сохранена как Helpform.htm. В лю бом текстовом редакторе, например в Блокноте, создадим новый файл, который будет включать следующую строку: #define iDH_HeipButton 50. iDH_HelpButton — это символьное обозначение для HeipContextid. Сохраним этот файл под любым именем, но с обязательным расширением h, напри мер Formhelp.h Открываем наш проект справочной HTMLHelpAPI information (рис. 23.20).
системы
и
нажимаем
Рис. 23.20. Диалоговое окно HtmlHelpAPI information
Рис. 23.21. Диалоговое окно Alias
кнопку
326
Часть I. Процедурное программирование в Visual FoxPro
С помощью кнопки Header file (Файл заголовка) подключаем наш файл, который мы создали в Блокноте. Теперь нужно указать системе, какой именно раздел справки мы свяжем с нашим HeipContextid. Для этого пере ходим на вкладку Alias и щелкаем кнопку Add (Добавить). Открывается диа логовое окно, в котором мы и указываем путь к нашему файлу — рис. 23.21. В первом поле ввода мы указываем символьное обозначение, во втором — имя нашего файла с разделом справки. После чего заново компилируем файл и "испытываем" нашу форму — рис. 23.22. Такой же результат получится, если нажать клавишу
Рис. 23.22. Пример контекстно-зависимой справки
Кнопка What's This? При таком способе вызова справки на экранной форме должна располагать ся кнопка со знаком вопроса. При щелчке на этой кнопке мышиный указа тель превращается в знак вопроса, и если щелкнуть на каком-либо объекте формы — в отдельном окне появится раздел справки, связанный с данным объектом. Чтобы она там появилась, необходимо присвоить некоторым свойствам экранной формы следующие значения: whatThisHeip=.T., WhatThisButton =.T., MaxButton =.F., MinButton =
.F., WhatThisHelpId —
уникальное значение, например 7. (Это свойство нужно установить не для формы, а для объекта, для которого мы будем создавать раздел справки.) В данном примере будем "препарировать" кнопку Выход. Если ты ничего не перепутал, то форма примет такой вид — рис. 23.23. Теперь опять возвращаемся к проекту справки и связываем соответствующий раздел справки с данной кнопкой. Для этого включаем в заголовочный файл formhelp.h еще одну директиву (рис. 23.24).
Урок 23. Создание справочной системы
227
Рис. 23.23. Форма с кнопкой What's This?
Рис. 23.24. Директива в Блокноте
После этого, перейдя на вкладку Alias (Псевдоним) в окне проекта справки, связываем всю эту систему с конкретным разделом справки. Теперь можно заново выполнить компиляцию проекта справки и все будет работать!
УРОК 2 4
Создание ЕХЕ-приложения В предыдущих главах мы уже кратко познакомились с окном диспетчера проекта и даже попытались создать АРР-приложение. Теперь мы продол жим знакомство и создадим исполняемый файл с расширением ехе.
Параметры проекта При создании проекта можно задать дополнительные параметры, такие как фамилия разработчика, пиктограмма для исполняемого файла и т. д. Для этого необходимо воспользоваться пунктом Project Info (Информация о проекте) меню Project (Проект). Появится диалоговое окно, содержащее дополнительную информацию о проекте — рис. 24.1.
Рис. 24.1. Диалоговое окно Project Information
Урок 24. Создание ЕХЕ-приложения
329
Окно имеет три вкладки: Project (Проект), Files (Файлы) и Servers (Сер веры). В поля ввода вкладки Project заносится информация о разработчике; Author (Ф.И.О. автора), Company (Наименование компании разработчика), Address (Адрес), City (Город), Country (Страна), State (Штат, область), Postal code (Почтовый индекс). Ноте (Домашний каталог) позволяет указать месторасположение проекта, флажок Attach icon (Определить значок) и кнопка Icon (Значок) создать значок (иконку), при щелчке на котором будет запускаться наше приложе ние. Флажок Debug info (Информация об отладке) позволяет включить в исполняемый код отладочную информацию, а флажок Encrypted (Шифро вание) включает механизм шифрования исполняемого кода проекта. На вкладке Files (Файлы) (рис. 24.2) отображены все файлы, входящие в наш проект. Файлы представлены в табличном виде, и чтобы упорядочить их, например по имени, достаточно щелкнуть на заголовке Name (Имя). Таким же образом файлы можно упорядочить по типу (Туре) или по дате последнего редактирования (Last Modified). Файлы, включенные в проект (Included), отмечены крестиком.
Рис. 24.2. Вкладка Fifes
Установка основной программы В любом проекте обязательно должен быть файл, который будет запускать приложение. Эта штука и называется основной программой, ею может быть
330
Часть I. Процедурное программирование в Visual FoxPro
все, что угодно — экранная форма, меню, программа и т. д. Для установки файла в качестве основного нужно открыть диспетчер проекта, установить мышь на нужный файл, нажать правую кнопку и в контекстном меню вы брать пункт Set Main (Установить основным) — рис. 24.3. Файл при этом будет выделен жирным шрифтом.
Рис. 24.3. Выбор основной программы
Опция Exclude Такие компоненты приложения, как экранные формы, меню, программы называются выполняемыми и должны быть включены в состав проекта при помощи команды контекстного меню Include (Включить), что, кстати, и происходит по умолчанию. С другой стороны, такие объекты, как индексы и таблицы, являются компонентами невыполняемыми, и если их включить в приложение, то они будут доступны только для чтения. Поэтому для таб лиц необходимо использовать команду Exclude (Исключить) из того же кон текстного меню (см. рис. 24.3). В принципе, включить или исключить из приложения можно любой компонент. После исключения рядом с таким компонентом появится перечеркнутый кружок (посмотри на наши таблицы...). Но при исключении компонента он не удаляется, просто ставится пометка о его удалении. Для того чтобы окончательно очистить проект от "ненужных" файлов, необходимо выполнить команду Clean Up Project (Упаковать проект) из системного меню Project (Проект).
Построение исполняемого файла Для того чтобы сделать исполняемый файл с расширением ехе, необходимо выбрать опцию Build Executable (Построить исполняемый файл) в диалого-
Урок 24. Создание ЕХЕ-приложения
331
вом окне Build Options (Опции построения) (рис. 24.4), которое вызывается при нажатии кнопки Build (Построить) в окне диспетчера проекта.
PMC. 24.4. Диалоговое окно Build Options
В данном окне имеется две группы переключателей: Action (Действие) и Options (Опции), их назначение описано далее. Пункты группы Action (Действие): • Rebuild Project (Перестроить проект) — проверяет наличие необходимых файлов и собирает проект; • Build Application (Построить приложение) — создает исполняемое прило жение с расширением арр. Работает в среде Visual FoxPro; • Build Executable (Построить исполняемый файл) — создает исполняемое приложение с расширением ехе. Работает как в среде Visual FoxPro, так и вне ее (при наличии соответствующих библиотек); • Build COM DLL (Построить COM DLL) — создает динамическую биб лиотеку с расширением dll. Пункты группы Options (Опции): • Recompile All Files (Обновлять все файлы) — по умолчанию обновляются только те компоненты, которые были изменены после последнего по строения. А при установке данного флажка будут обновлены все файлы, входящие в проект; • Display Errors (Показывать ошибки) — если в процессе построения при ложения возникнут ошибки, то они будут отображены в отдельном окне; • Run After Build (Запускать после построения) — если тебе не терпится запустить свое приложение сразу после построения, смело отмечай дан ный флажок;
332
Часть I. Процедурное программирование в Visual FoxPro
• Regenerate Component IDs (Заново генерировать идентификаторы Auto mation-серверов) — применяется в случае, если необходимо установить и регистрировать содержащиеся в проекте Automation-серверы. Еще в данном диалоговом окне имеется кнопка Version (Версия), при нажа тии которой можно указать версию продукта, а также некоторые дополни тельные параметры (внутреннее имя и т. д.) — рис. 24.5.
Рис. 24.5. Диалоговое окно EXE Version
После настройки всех параметров можно приступить к "строительству", на жав кнопку ОК. Но в случае с исполняемым файлом ЕХЕ, особенно если он будет выпол-j няться вне главного окна Visual FoxPro, тебя может поджидать мелкая не приятность — твое приложение мелькнет на экране и исчезнет в "неизвест ном направлении". Знаешь, почему так происходит? Потому что мы не включили в основную программу обработчик READ EVENTS. А надо бы... На пример, вот так: *основная программа
DO FORM MAIN READ EVENTS
Это, как ты догадался, текст основной программы. Более того, если при за вершении работы не отключить эту штуку, то возникнет еще более непри ятная вещь — при завершении работы Windows появится сообщение "Cannot quit Visual FoxPro" (Невозможно завершить работу Visual FoxPro)-
Урок 24. Создание ЕХЕ-приложения
333
Что теперь делать? Есть два способа. Первый — использовать всеми "люби мое" сочетание клавиш . Второй, менее экзотиче ский — обязательно включить строку CLEAR EVENTS перед командой QUIT, которая завершает работу Visual FoxPro:
CLEAR EVENTS QUIT
УРОК 25
Создание установочных дисков Теперь, когда приложение практически полностью готово, осталась самая малость — каким-то образом предоставить его конечному пользователю. Проблема частично решается, если у пользователя имеется Visual FoxPro — достаточно переписать все необходимые файлы на дискеты и с торжествен ным видом вручить их пользователю — работайте. А если Visual FoxPro не установлен? В этом случае можно вместе с файлами приложения передать и дискеты с файлами необходимых динамических библиотек Visual FoxPro, на в этом случае придется долго растолковывать пользователю: как, куда и что за чем ставить. Все это конечно, хорошо, но как говорится — "а ларчик просто открывался..." Дело в том, что в состав Visual FoxPro входит замеча тельное средство для создания дистрибутива — Setup Wizard (Мастер установки). Запускается этот хитрый механизм из меню Tools | Wizards | Setup Wizard (Инструменты | Мастера | Мастер установки). На первом шаге (рис. 25.1) необходимо указать, в каком каталоге находятся файлы, включаемые в комплект поставки. Для выбора каталога необходимо воспользоваться кнопкой, расположенной справа от поля ввода — при этом откроется уже знакомое нам диалоговое окно Select Directory (Выбор папки). На этом этапе (рис. 25.2) нужно указать, какие компоненты приложения будут включены в комплект поставки. Если на компьютере пользователя отсутствует среда Visual FoxPro, необходимо отметить флажок Visual FoxPro runtime — при этом в комплект поставки будут включены необходимые библиотеки. Если твое приложение использует элементы управления Microsoft Graph 8.0, отметь соответствующий флажок. Если в приложений используются компоненты ActiveX, файлы HTML-справки или доступ к данным осуществляется с использованием драйверов ODBC, необходимо отметить и эти флажки. Причем при установке данных флажков будут вы ведены соответствующие диалоговые окна для выбора конкретных компо нентов. Например, в случае использования элементов ActiveX появится та кое окно — рис. 25.3.
Урок 25. Создание установочных дисков
335
Рис. 25.1. Первый шаг Setup Wizard
Рис. 25.2. Второй шаг Setup Wizard
На третьем шаге (рис. 25.4) мастер создаст каталоги установки и поместит их в указанную в поле ввода папку. Далее предлагается выбрать один из трех вариантов типа установки: на дискетах (1.44 MB 3.5-inch) (понадобит ся минимум четыре дискеты), через сеть Web (Websetup (compressed)) или через локальную сеть (Netsetup (uncompressed)).
336
Часть I. Процедурное программирование в Visual FoxPro
Рис. 25.3. Диалоговое окно для добавления компонентов ActiveX
Рис. 25.4. Третий шаг Setup Wizard
На четвертом шаге (рис. 25.5) мастер предложит указать текст заголовка диалогового окна установочной программы, информацию об авторских пра вах, а также имя исполняемого файла, который будет запущен сразу по окончании процесса установки. Последнее, впрочем, указывать и не обяза тельно. На пятом шаге (рис. 25.6) необходимо указать имя корневого каталога на компьютере пользователя, которое по умолчанию будет предлагать npoграмма установки. Также указывается имя программной группы, в которую будет добавлено наше приложение. Расположенные ниже переключатели определяют, может ли пользователь менять эти установки.
Урок 25. Создание установочных дисков
337
Рис. 25.5. Четвертый шаг Setup Wizard
Рис. 25.6. Шаг пятый Setup Wizard
Задание каталогов для специальных файлов происходит на шестом шаге ра боты мастера установки (рис. 25.7). Здесь можно изменить подкаталоги для размещения любого файла и отме тить файлы ActiveX для их регистрации на компьютере пользователя.
338
Часть I. Процедурное программирование в Visual FoxPro
Рис. 25.7. Шестой шаг Setup Wizard
И наконец, последний шаг — рис. 25.8. Флажок Generate a web executable file позволяет создать исполняемый файл Web, а флажок Create a dependency (.DEP) file — файл взаимных связей. Все, ФИНИШ!
Рис. 25.8. Завершающий этап создания установочной программы
Урок 25. Создание установочных дисков
339
После нажатия этой заветной кнопки начинается процесс создания устано вочной программы, что мы и можем наблюдать на экране (рис. 25.9).
Рис. 25.9. Отображение процесса создания установочной программы
Но в некоторых случаях мы можем наблюдать и такое — рис. 25.10.
Рис. 25.10. Ошибка при создании установочной программы
Рассказать секрет? Ладно, все очень просто — нужно перед созданием про граммы и запуском мастера закрыть окно диспетчера проекта. После по вторного запуска все пройдет успешно и мы увидим окно статистики (рис. 25.11). В данном окне мы видим количество дискет, необходимых для распростра нения нашего приложения. Для получения более подробной информации нажмем кнопку Preview Report (Просмотр отчета) и в результате получим подробнейший отчет — какой файл на каком диске и т. д. (рис. 25.12). Программа установки Setup находится в каталоге Diskl (рис. 25.13). А чтобы окончательно убедиться, что эта штука способна работать, мы про сто запустим ее на выполнение (рис. 25.14—25.16).
340
Часть I. Процедурное программирование в Visual FoxPro
Рис. 25.11. Диалоговое окно статистики
Рис. 25.12. Фрагмент файла отчета
Урок 25. Создание установочных дисков
Рис. 25.13. Программа установки нашего приложения
Рис. 25.14. Фрагмент работы программы установки
341
342
Часть I. Процедурное программирование в Visual FoxPro
Рис. 25.15. Идет процесс установки
Рис. 25.16. Установка успешно завершена!
ЧАСТЬ II Объектно-ориентированное программирование Вот мы и добрались до части II нашей книги, в которой я тебе расскажу о принципиально новых понятиях технологии программирования. Дело в том, что Visual FoxPro представляет собой гибридный язык программирования, который позволяет создавать приложения как с использованием старой тех нологии модульного программирования, так и применяя современную тех нологию объектно-ориентированного программирования. В чем их отличие? Модульное, или процедурное программирование — это то, чем мы с тобой занимались, изучая первую часть нашей книги. Наше приложение состояло из набора отдельных модулей (экранных форм, процедур, программ), кото рые в совокупности и решали поставленную задачу. Именно такая техноло гия использовалась в FoxPro for DOS, в FoxPro for Windows и других языках программирования. Как мы уже видели, ее же можно успешно применять и при создании приложений в Visual FoxPro. А зачем, спросишь ты, от нее отказываться? Да никто и не заставляет от нее отказываться — огромное количество программистов (особенно те, кто "перешел" в Visual со старых версий FoxPro) до сих пор так и создают свои приложения. Но... Представь
такую ситуацию: мы разработали некое приложение, которое успешно рабо тает в какой-то компании. И оно настолько всем нравится, что к нам при ходит представитель другой компании и говорит: "О-кей, ребята, мы хотим то же самое. Правда, требования у нас немного другие..." А мы что, мы не против. Мы с тобой берем кучу дискет, компакт-дисков и двигаемся в эту фирму. Там мы устанавливаем свое приложение, но, т. к. у них "требования немного другие", мы корректируем программный код наших модулей, под гоняя его под условия данного заказчика. А потом к нам приходит еще один клиент и... все повторяется. Естественно, на все эти манипуляции уходит время, деньги и нервы. Принципиально другой подход к обновлению и адаптации приложений н различным условиям предлагает технология объектно-ориентированного программирования. Применяя данную технологию, можно создавать приложение не столько как набор отдельных профаммных модулей, сколько как совокупность объектов. Допустим, нам нужно смоделировать, т. е. профаммно разработать объект "Организация". А для этого нам необходимо знать, что же такое организация? И не конкретная фирма, а организация вообще. Что она "знает" о себе, что "умеет" делать? Очевидно, что любая организация "знает" свое наименование, юридический адрес и т. д. Любая ор ганизация имеет счет в банке, у любой организации есть руководитель и т. д. Любая организация "умеет" сохранять сведения о самой себе, сооб щать сведения о самой себе и т. д. Исходя из этого, можно понять, что те перь вместо профаммного модуля для обработки, скажем, исходящей документации мы можем включить в приложение такие объекты, как "Организация", "Документы" и т. д. И теперь, если возникнет необходимость адаптировать наше приложение к новым условиям, "подогнать" его под требования нового пользователя — нам достаточно внести эти отличия в новые объекты, которые будут созданы на основе уже имеющихся. Все те функциональные возможности, свой ства и методы, заложенные в "основной", уже имеющийся объект, будут ав томатически перенесены во вновь созданный и при необходимости могут быть изменены в нем. Теперь, я думаю, более или менее понятно, для чего разработана технология объектно-ориентированного профаммирования. В двух словах: упрощение сопровождения приложений и возможность повторного использования про фаммного кода, который кто-то (необязательно ты), когда-то (необязатель но сегодня) уже создал.
УРОК 26
Объекты А теперь, дружок, я тебя буду пугать страшными словами, без знания кото рых у тебя ничего не получится, если ты вздумаешь заняться объектноориентированным программированием. Слова следующие: объект или сущ ность (entities), наследование (inheritance), инкапсуляция (encapsulation), поли морфизм (polymorphism). Вот. Я думаю, ты уже привык к шуткам автора и пугаться даже не собирался. И правильно сделал, потому что сейчас я тебе постараюсь объяснить смысл этих "страшных" терминов и все станет ясно и прозрачно. Начнем с понятия самого объекта. Объект представляет собой всего-навсего совокупность данных и функций. То есть он содержит как данные, так и функции — способы или методы выполнения каких-то действий. Теперь отвлекись от монитора и посмотри на обычный телевизор — чем не объект? Он имеет свойства (например, уровень громкости, число принимаемых каналов, цвет корпуса, размер ки нескопа и т. д.), он имеет свой интерфейс для "общения" с внешним ми ром — это кнопки управления, а также он умеет выполнять некоторые дей ствия — переключать каналы, увеличивать или уменьшать уровень яркости изображения и т. д. Примерно такие же качественные характеристики имеет и программный объект. Но внутри телевизора есть много чего такого, о чем нам с тобой и знать не нужно: например, зачем нам в повседневной жизни знать, каким образом происходит переключение каналов или на какой угол отклоняется пучок электронов из пушки кинескопа? Работает, и ладно. Для нас имеет значение только его средства общения с нами — кнопки, пере ключатели, пульт дистанционного управления — в общем, все то, с по мощью чего мы можем "заставить" объект выполнить те или иные действия. Вот так незаметно мы и поняли суть сразу двух "страшных" слов — объекта и инкапсуляции. Про объект ясно, а инкапсуляция? А про инкапсуляцию ты только что прочитал — объект инкапсулирует, т. е. включает в себя (или содержит в себе) всю необходимую информацию и набор функций, которые и определяют его поведение.
346
Часть II. Объектно-ориентированное программирование
Данные, инкапсулированные в объекте, называются свойствами. Например, одно из свойств экранной формы — backcoior, определяет цвет фона фор мы. С точки зрения нашего Лиса, данное свойство представляет собой все го-навсего переменную памяти, которая может принимать определенные значения и которая присоединена к объекту и имеет область видимости только в пределах своего объекта. В свою очередь, процедуры, присоединенные к объекту, называются мето дами. А что такое процедуры? Это программный код, с помощью которого объект может выполнять какие-либо действия. А вот действия, которые происходят во "внешнем" мире и на которые объ ект должен реагировать, называются событиями. Классическим примером может служить такое событие, как щелчок мышью. Оно происходит по инициативе пользователя. А еще событие может наступить по инициативе самой программы, например: IF BOF () =MESSAGEBOX("ПОСЛЕДНЯЯ ЗАПИСЬ", "КОНЕЦ ФАЙЛА") ENDIF
Теперь, чтобы уяснить суть оставшихся "страшных" слов, мы введем новое понятие, которое именуется как классы.
Классы Прочитав предыдущий раздел, ты уяснил следующее: в Visual FoxPro можно создавать объекты. А вот какой в этом практический смысл, наверное, пока непонятно. Действительно, в чем преимущества нового метода — ведь если для каждого приложения придется каждый раз создавать новые объекты — где же тут обещанные комфорт, экономия времени и нервов? А вот именно для этого и существуют такие штуки, как классы. Именно они и являются той основой, при помощи которой создаются различные объекты. Например, возьмем обычную тарелку. Ясно, что каждую тарелку никто не делает индивидуально. На заводе существует какая-то пресс-форма или шаблон, с помощью которой можно изготовить миллион одинаковых таре лок. Улавливаешь аналогию? Правильно, точно так же никто не собирается писать программный код для однотипных программных объектов — доста точно создать класс (этакую пресс-форму), а затем "наштамповать" сколько угодно объектов на основе данного класса. Причем все вновь созданные объекты будут являться экземплярами этого класса. И эти вновь созданные объекты унаследуют все методы, события и свойства, присущие классуродителю. Вот это и называется наследованием. Чтобы лучше понять, как это происходит, рассмотрим наглядный пример.
Урок 26. Объекты
347
В Visual FoxPro для создания классов используются две команды: DEFINE CLASS И ENDDEFINE.
Синтаксис
первой
команды
следующий:'
DEFINE CLASS Имя_Класса AS Имя_Класса_Родителя
Классом-родителем (superclass) называется тот базовый класс, на основе ко торого будет создан новый. Давай создадим класс на основе класса обычной формы: DEFINE CLASS Myform AS FORM Autocenter = .T. Caption = "MYFORM" Backcolor = RGB(0,255,0) Name - "MYFORM" ENDDEFINE
Вот и все, создана обычная форма да еще и зеленого цвета. Теперь, чтобы посмотреть, как происходит процесс наследования, создадим объект на ос нове вновь созданного класса: Oform=CREATEOBJECT ("Myform") Oform.SHOW(l) DEFINE CLASS Myform AS FORM Autocenter = .T. Caption = "MYFORM" Backcolor = RGB(0,255,0) Name = "Myform" ENDDEFINE
Для создания экземпляра класса используется функция CREATEOBJECT (): Oform = CREATEOBJECT("Myform")
To есть создается некоторая переменная типа object на основе указанного класса. Теперь представь, что мы создали очень много каких-то объектов на основе какого-то класса и по какой-то причине приходится изменить у них У всех какое-то свойство. Можно сделать "по-старинке", вручную установив для каждого необходимое значение свойства. А объектов-то этих самых ты уже сотворил 15 487 шт! Как быть? Применяя новую технологию объектноориентированного программирования, мы делаем это проще простого — меняем значение необходимого свойства у класса-родителя. Попробуй из мени значение цвета фона в классе нашей формы и ты увидишь, как изме нится цвет и нашего объекта. Вот это и есть наследование. А вот полиморфизмом называется возможность объектов по-разному реаги ровать на одни и те же события. Таким образом, мы уяснили, что в Visual FoxPro можно создавать новые классы на основе уже имеющихся. А что такое "уже имеющиеся"? Это так
348
Часть II. Объектно-ориентированное программирование
называемые базовые классы или суперклассы, которые поставляются вместе с данным программным продуктом. В табл. 26.1 перечислены базовые клас сы Visual FoxPro.
Имя класса
Назначение
Визуальный (видимый)
Для создания подклассов
Классконтейнер
Доступен из
FormControls
Таблица 26.1. Базовые классы Visual FoxPro
ActiveDoc
Активный документ
Нет
Да
Нет
Нет
CheckBox
Флажок
Да
Нет
Нет
Да
Column
Столбец элемента управления G r i d
Да
Нет
Да
Да
ComboBox
Раскрывающийся список
Да
Нет
Нет
Да
CommandButton
Кнопка
Да
Нет
Нет
Да
CommandGroup
Группа командных кнопок
Да
Нет
Да
Да
Container
Контейнер
Да
Да
Да
Да
Control
Базовый визуальный класс. "Похож" на Container, но извне можно обра щаться только к этому классу, а не к содержащимся в нем объектам
Да
Да
Да
Нет
Cursor
Определение курсора в среде дан ных
Нет
Нет
Нет
Нет
Custom
Базовый невизуальный класс. Можно использовать в качестве суперкласса для создания собственных
Нет
Да
Нет
Нет
DataEnvironment
Совокупность курсоров и отношений
Нет
Нет
Да
Нет
EditBox
Поле редактирования
Да
Да
Нет
Да
Form
Экранная форма
Да
Да
Да
Да
FormSet
Набор экранных форм
Нет
Да
Да
Да
Grid
Таблица
Да
Да
Да
Да
Header
Заголовок столбцов таблицы
Да
Нет
Нет
Нет
HyperLynk Object
Гиппересылка
Да
Да
Нет
Да
Image
Изображение
Да
Да
Нет
Да
Label
Надпись (Этикетка)
Да
Да
Нет
Да
Урок 26. Объекты
349
Имя класса
Назначение
Визуальный (видимый)
Для создания подклассов
Классконтейнер
Доступен из ForrnControls
Таблица 26.1 (окончание)
Line
Линия
Да
Да
Нет
Да
ListBox
Список
Да
Да
Нет
Да
decontrol
Элемент управления
Нет
Да
Да
Да
OptionButton
Переключатель
Да
Нет
Нет
Да
OptionButton
Группа переключателей
Да
Да
Да
Да
Page
Вкладка формы
Да
Нет
Да
Нет
PageFrame
Набор вкладок
Да
Да
Да
Да
ProjectHook
Проект
Нет
Нет
Да
Нет
Relation
Отношение между курсорами
Нет
Нет
Нет
Нет
Separator
Разделитель
Да
Нет
Нет
Да
Shape
Контур
Да
Нет
Нет
Да
Spinner
Счетчик
Да
Нет
Нет
Да
TextBox
Поле ввода
Да
Нет
Нет,
Да
Timer
Таймер
Нет
Нет
Нет
Да
ToolBar
Панель инструментов
Да
Да
Да
Нет
Единственным недостатком указанных классов является то, что их нельзя изменить. Но зато ничто не мешает создавать на их основе свои, пользова тельские классы, которые будут полностью в твоей "власти".
Композитные классы Композитными называются такие классы, которые содержат в себе объекты, созданные на основе других классов. Иначе их называют классыконтейнеры. Наша зеленая экранная форма также является классомконтейнером, и сейчас мы рассмотрим, каким образом можно добавить в этот класс объект из другого класса. Один из способов — использование команды ADD OBJECT, которая имеет следующий синтаксис: ADD OBJECT имя_объекта AS имя__класса WITH переменная=зиачение
350
Часть II. Объектно-ориентированное программирование
Применительно к нашему случаю: Of orm=CREATEOBJECT ("Myf orra") Oform.SHOW(l) DEFINE CLASS Myform AS FORM Autocenter = .T. Caption = "Myform" Backcolor - RGB(0,255,0) Name = "Myform" ADD OBJECT Mylabel AS LABEL; WITH Caption="ripMMep композитного класса",; Autosize=.T.,; Top=40,; Left=100 ENDDEFINE
И вот что получилось — рис. 26.1.
Рис. 26.1. Пример добавления в класс объекта из другого класса
Другой способ — использование метода ADDOBJECTO. Применяя данный ме-| тод, мы получим аналогичный результат: Oform=CREATEOBJECT ("Form") Oform.Autocenter=.T. Oform.Caption="Myform" Oform.ADDOBJECT("Mylabel","LABEL") Oform.Mylabel.Caption="Пример Композитного Класса" Oform.Mylabel.Autosize=.T. Oform.Mylabel.Top=40
Урок 26. Объекты
351
Oform.Mylabel. Lef t=100 Oform.Mylabel.Visible=.T. Oform.SHOW(l)
Ясно видно различие между ADD OBJECT И ADDOBJECTO- При использовании ADD OBJECT свойства объекта можно задать в одном операторе, а при исполь зовании ADDOBJECT( ) это придется делать отдельно. Применяя ADDOBJECT(), нужно не забывать устанавливать свойство visible — .т. (для визуальных объектов).
УРОК 27
Создание классов в Class Designer Для создания классов в Visual FoxPro можно использовать два способа: писать программный код (что мы делали ранее) или (что гораздо удобнее) воспользоваться услугами специального конструктора — Class Designer. Этот инструмент очень похож на уже знакомый нам Form Designer (Конструктор форм), но он имеет некоторые отличия — в частности, в меню до бавлен пункт Class (Класс) — рис. 27.1.
Рис. 27.1. Окно Class Designer
Урок 27. Создание классов в Class Designer
353
Ну а теперь приступим к практическим занятиям и первое, что мы сдела ем — создадим командную кнопку, которая будет закрывать экранную форму. 1. В окне диспетчера проекта перейдем на вкладку Classes (Классы) и на жмем кнопку New (Новый). 2. В открывшемся диалоговом окне New Class (Новый класс) (рис. 27.2) в поле ввода Class Name (Имя класса) необходимо ввести имя создавае мого класса, а используя раскрывающийся список Based On (Основан на), указать тот базовый класс Visual FoxPro, на основе которого мы бу дем создавать наш новый класс. Далее необходимо указать имя библио теки классов, в которой он будет сохранен. Можно как выбрать уже существующую библиотеку классов, так и создать новую, свою собст венную.
Рис. 27.2. Диалоговое окно New Class
3. После этого, в окне Class Designer производим настройку свойств, мето дов и событий для нашего класса — точно так же, как мы это делали ра нее при работе с обычными объектами (рис. 27.3). Меняем название кнопки (caption = выход) и пишем код для события click: THIsFORM.RELEASE (), после чего сохраняем результат наших действий. Все, класс готов! Его код представлен в листинге 27.1. Листинг 27.1. Класс E x i t B u t t o n DEFINE CLASS EXITBUTTON AS COMMANDBUTTON HEIGHT - 27 WIDTH = 8 4 CAPTION = "ВЫХОД" NAME - "EXITBUTTON" PROCEDURE CLICK THISFORM.RELEASE() ENDPROC ENDDEFINE
354
Часть II. Объектно-ориентированное программирование
Рис. 27.3. Создание класса
Это самый простой пример, а чтобы окончательно убедить тебя в удобности использования классов, мы продолжим знакомство с классами одиночных элементов управления. В качестве "подопытного кролика" будем использо вать все ту же командную кнопку, на основе которой создадим еще не сколько классов.
Пример 1 — калькулятор Сейчас мы попробуем сделать простейший калькулятор. Итак, нам понадо бятся: экранная форма, поле ввода и два класса кнопок. После того, как мы должным образом сгруппируем эти объекты, у нас получится симпатичный и даже более или менее работающий калькулятор. На экранной форме мы останавливаться не станем — можешь сделать ее какую хочешь, только раз мести на ней два поля ввода. А вот на кнопочках остановимся подробнее: все-таки новые классы создаем... Для начала создадим класс цифровых кнопок и назовем его DigitButto (рис. 27.4). Сам класс DigitButton довольно "примитивен" (листинг 27.2).
Урок 27. Создание классов в Class Designer
355
Рис. 27.4. Мы создаем новый класс
Листинг 27.2. Класс DigitButton DEFINE CLASS DIGITBUTTON AS COMMANDBUTTON HEIGHT = 27 WIDTH = 4 8 FONTBOLD = .T. CAPTION = "1" NAME = "DIGITBUTTON" PROCEDURE CLICK THISFORM. TEXT1 .VALUE==THISFORM.TEXTl .VALUE+THIS. CAPTION THISFORM.TEXT2.VALUE=THISFORM.TEXT2.VALUE+THIS.CAPTION ENDPROC ENDDEFINE
Теперь вернемся к нашей экранной форме и создадим для нее новое свой ство орег. Как это делается, мы еще не "проходили", вот заодно и научимся. Дело в том, что, помимо базовых свойств (это те, которые отображены в диалоговом окне Properties (Свойства)), практически для любого объекта можно задать новые свойства и методы. Для этого нужно выбрать пункт
356
Часть II. Объектно-ориентированное программирование
New Property (Новое свойство) меню Form (Форма) в окне Form Designer (Конструктор форм). На экране появится окно New Property (Новое свойст во) — рис. 27.5.
Рис. 27.5. Диалоговое окно New Property
В данном окне необходимо указать имя нового свойства и при необходимо сти установить флажки Access Method и Assign Method. При установке флажка Access Method для данного свойства будет автоматически установ лен метод Access (Доступ), а при установке флажка Assign Method для свой ства будет автоматически создан метод Assign (Назначение). Ну а в том, что наша экранная форма действительно обрела новое свойство, можно легко убедиться, посмотрев на окно свойств (Properties) — рис. 27.6.
Рис. 27.6. Мы видим новое свойство в окне свойств
Урок 27. Создание классов в Class Designer
357
Теперь создадим еше один класс кнопок, по нажатию которых будет произ водиться то или иное математическое действие, и назовем его OperButton. Код такой кнопки представлен в листинге 27.3. Листинг 27.3. Класс OperButton DEFINE CLASS OPERBUTTON AS COMMANDBUTTON TOP - 5 3 LEFT = 147 HEIGHT = 27 WIDTH = 3 6 FONTBOLD = . T . CAPTION = " + " NAME = " 0 P E R 1 " PROCEDURE CLICK THISFORM.OPER=THIS.CAPTION
LASTVALUE=THISFORM.TEXT1.VALUE THISFORM.TEXTl.VALUE="" THISFORM.TEXT2.VALUE=THISFORM.TEXT2.VALUE+THISFORM.OPER ENDPROC ENDDEFINE
Все, теперь остается разместить наши кнопки на экранной форме. Для это го нужно нажать кнопку View Classes (Просмотр классов) на панели инст рументов Form Controls (Элементы управления экранной формы) и в рас крывшемся меню выбрать пункт Add (Добавить). После чего в открывшемся диалоговом окне указать нашу библиотеку классов — рис. 27.7. Получится следующее — рис. 27.8. Теперь дело за малым — расположить наши объекты на форме, да в методе init формы прописать следующее: PUBLIC LASTVALUE — рис. 27.9. А как же получить результат? Придется поработать над событием click для соответствующей кнопки "=" (листинг 27.4). Листинг 27.4. Событие c l i c k кнопки "=" IF THISFORM.OPER="+" THISFORM.TEXTl.VALUE=STR(VAL(THISFORM.TEXTl.VALUE)+VAL(LASTVALUE),20,2) THISFORM.TEXT2.VALUE=THISFORM.TEXT2.VALUE+"="+ ALLTR(THISFORM.TEXTl.VALUE) ENDIF IF THISFORM.OPER="-" THISFORM.TEXTl.VALUE=STR(VAL(LASTVALUE)-VAL(THISFORM.TEXTl.VALUE),20,2)
Часть II. Объектно-ориентированное программирование
358
THISFORM.TEXT2.VALUE=THISFORM.TEXT2.VALUE+"="+ ALLTR(THISFORM.TEXT1.VALUE) ENDIF I F THISFORM.OPER="*" THISFORM.TEXT1.VALUE=STR(VAL(LASTVALUE)* VAL(THISFORM.TEXT1.VALUE),20,2) THISFORM.TEXT2.VALUE=THISFORM.TEXT2.VALUE+"="+ ALLTR(THISFORM.TEXT1.VALUE) ENDIF IF THISFORM.OPER='7" THISFORM.TEXT1.VALUE=STR(VAL(LASTVALUE)/VAL(THISFORM.TEXT1.VALUE),20,2) THISFORM.TEXT2.VALUE=THISFORM.TEXT2.VALUE+"="+ ALLTR(THISFORM.TEXT1.VALUE) ENDIF
Все, запускаем наш "агрегат" — рис. 27.10. А что нам с тобой калькулятор, хочешь, сделаем игру? Легко!
G J ^ H H H I ШЯШШШШШЯШ^ШШШШШШЧШ Папка: | iQ calc
д|. : Ф3 IS & Ш"
Рис. 27.7. Добавление собственной библиотеки классов
Рис. 27.8. Наши классы расположились на панели Form Controls
Урок 27. Создание классов в Class Designer
Рис. 27.9. Наш суперкалькулятор почти готов!
359
Рис. 27.10. Ура! Получилось!
Пример 2 — Puzzle Когда-то, давным-давно, в FoxPro for DOS имелась встроенная простенькая игрушка Puzzle (Пазл), более известная в нашей стране как "Пятнашки". Смысл был такой: щелкая мышью, расположить цифры в порядке возраста ния от 1 до 15. Не знаю, почему, но в Visual FoxPro такой игры нет. Зато мы можем, опираясь на только что полученные знания, соорудить нечто подобное самостоятельно. Например, игрушку вот с таким игровым по лем — рис. 27.11. Или вот с таким — рис. 27.12.
Рис. 27.11. "Классический" Puzzle
Рис. 27.12. А это уже наша самодельная игрушка
Часть II. Объектно-ориентированное программирование
360
Мне кажется, ты не станешь думать, что я обе эти экранные формы "сотво рил" в Form Designer (Конструктор форм), расставил кнопки (81 шт!), напи сал для каждой кнопки обработчик щелчка мыши и т. д.? Правильно, все это делает одна-единственная программка, размером 4 Кбайта! Сейчас по смотрим ее код (листинг 27.5), а затем подробно разберем, как там все ра ботает. Листинг 27.5. Puzzle ***************************** *pn2ZLE************************** **********************ди>рр}Орч. DMITRY SHAPOREV***************** STARTPUZZLE=CREATEOBJECT("STARTPUZZLE") STARTPUZZLE.SHOW(1) DEFINE CLASS STARTPUZZLE AS FORM HEIGHT = 82 WIDTH = 175 DOCREATE - .T. AUTOCENTER - ,T. CAPTION = "НАЧАЛО ИГРЫ" CLOSABLE = .F. MAXBUTTON = .F. MINBUTTON = .F. NAME = "FORM1" ADD OBJECT LABEL1 AS LABEL WITH; AUTOSIZE = .Т., ; CAPTION = "УРОВЕНЬ СЛОЖНОСТИ (ОТ 4 ДО 9)",; HEIGHT = 17,; LEFT = 1,; TOP = 4,; WIDTH - 172,; NAME = "LABEL1" ADD OBJECT TEXT1 AS TEXTBOX WITH; HEIGHT = 23, ; LEFT = 37,; TOP = 24, ; WIDTH = 100, ; NAME = "TEXT1" ADD OBJECT COMMAND1 AS COMMANDBUTTON WITH; TOP - 51,; LEFT = 12,;
Урок 27. Создание классов в Class Designer HEIGHT = 27,; WIDTH = 60, ; CAPTION = "ВЫХОД",; NAME = "COMMANDl" ADD OBJECT C0MMAND2 AS COMMANDBUTTON WITH; TOP = 51, ; LEFT = 93,; HEIGHT = 27,; WIDTH = 60, ; CAPTION - "ЗАПУСК",; NAME - "C0MMAND2" PROCEDURE TEXT1.ERRORMESSAGE =MESSAGEBOX("БУДЬТЕ ВНИМАТЕЛЬНЕЙ!","ОШИБКА") ENDPROC PROCEDURE TEXT1.VALID IF EMPTY(THIS.VALUE) RETURN it. END IF IF VAL(THIS.VALUE)<4 RETURN .F. ENDIF IF VAL(THIS.VALUE)>9 RETURN .F. ENDIF ENDPROC PROCEDURE C0MMAND2.CLICK PUBLIC NLEVEL NLEVEL=VAL(THISFORM.TEXT1.VALUE) ********************** ********************** #DEFINE COUNT_OF_ITEMS NLEVEL*NLEVEL LOCAL ARRAY LARAND[COUNT_OF_ITEMS] LOCAL ARRAY LATEMP[COUNT_OF_ITEMS] LOCAL I,J, N RAND(-l) N=COUNT_OF_ITEMS FOR 1=1 TO COUNT_OF_ITEMS LATEMP[I]=1-1 ENDFOR FOR 1=1 TO COUNT_OF_ITEMS J=INT(RAND()*N)+1 LARAND[I]=LATEMP[J]
361
=ADEL(LATEMP,J) N=N-1 ENDFOR FOR 1=1 TO COUNT_OF_ITEMS ENDFOR ********************** ********************** ************************************************************************ PUZZLE=CREATEOBJECT("FORM") PUZZLE.CAPTION="FOXPUZZLE" DL=30 WT=30 FOR F = l TO NLEVEL FOR D=l TO NLEVEL PUZZLE.ADDOBJECT("PZ"+ALLTR(STR(D))+ALLTR(STR(F)), "PUZZLEBUTTON") M1="PZ"+ALLTR(STR(D))+ALLTR(STR(F))+".VISIBLE" M2="PZ"+ALLTR(STR(D))+ALLTR(STR(F))+".LEFT"
M3="PZ"+ALLTR(STR(D))+ALLTR(STR(F))+".WIDTH" M4="PZ"+ALLTR(STR(D))+ALLTR(STR(F))+".TOP" M5="PZ"+ALLTR(STR(D))+ALLTR(STR(F))+".CAPTION" PUZZLE.&M4=(F)*WT PUZZLE.&M2=DL*(D-1) PUZZLE.&M1=.T. PUZZLE.&M3=DL PUZZLE.WIDTH=DL*D PUZZLE.HEIGHT=WT*(F+2) ENDFOR ENDFOR 1=0 FOR R = l TO NLEVEL FOR K=l TO NLEVEL M5="PZ"+ALLTR(STR(R))+ALLTR(STR(K))+".CAPTION" 1=1+1 PUZZLE.&M5=ALLTR(STR(LARAND(I))) ENDFOR ENDFOR PUZZLE.AUTOCENTER=.T. PUZZLE.SHOW(1) ENDPROC
Урок 27. Создание классов в Class Designer
363
PROCEDURE COMMANDl.CLICK THISFORM.RELEASE() ENDPROC ENDDEFINE *— ENDDEFINE: PUZZLE *********************************************************************** DEFINE CLASS PUZZLEBUTTON AS COMMANDBUTTON HEIGHT = 2 7 WIDTH = 84 CAPTION = "" NAME = "PUZZLEBUTTON" PROCEDURE CLICK THISNAME=THIS.CAPTION DIGIT_PART=INT(VAL(RIGHT(THIS.NAME,2))) IF TYPE("THISFORM."+"PZ"+ALLTR(STR(DIGIT_PART+1))+".NAME")="C" NEXTNAME="THISFORM."+"PZ"+ALLTR(STR(DIGIT_PART+1))+".CAPTION" IF &NEXTNAME="0" THIS.CAPTION=&NEXTNAME &NEXTNAME=THISNAME ENDIF ENDIF ************************************************************************ IF TYPE("THISFORM."+"PZ"+ALLTR(STR(DIGIT_PART1))+".NAME")="C" NEXTNAME="THISFORM."+"PZ"+ALLTR(STR(DIGIT_PART-1))+".CAPTION" IF &NEXTNAME="0" THIS.CAPTION=&NEXTNAME &NEXTNAME=THISNAME ENDIF ENDIF ******************** IF TYPE("THISFORM."+"PZ"+ALLTR(STR(DIGIT_PART+10))+".NAME")="C" NEXTNAME="THISF0RM."+"PZ"+ALLTR(STR(DIGIT_PART+10))+".CAPTION" IF &NEXTNAME="0" THIS.CAPTION=&NEXTNAME &NEXTNAME=THISNAME ENDIF ENDIF
364
Часть II. Объектно-ориентированное программирование
******************** IF TYPE("THISFORM."+"PZ"+ALLTR(STR(DIGIT_PART-10))+".NAME")="C" NEXTNAME="THISFORM."+"PZ"+ALLTR(STR(DIGIT_PART-10))+".CAPTION" IF &NEXTNAME="0" THIS.CAPTION=&NEXTNAME &NEXTNAME=THISNAME ENDIF ENDIF ENDPROC ENDDEFINE
Вот и вся программка. Теперь давай разбираться, чего мы тут с тобой насо чиняли. Для этого разобьем текст программы на несколько блоков. "Блок 1" — создаем объект на базе класса, производного от класса формы (листинг 27.6). Листинг 27.6. Блок 1 STARTPUZZLE=CREATEOBJECT("STARTPUZZLE") STARTPUZZLE.SHOW(1) DEFINE CLASS STARTPUZZLE AS FORM HEIGHT = 82 WIDTH = 175 DOCREATE = .T. AUTOCENTER = .T. CAPTION = "НАЧАЛО ИГРЫ" CLOSABLE - .P. MAXBUTTON = ,F. MINBUTTON = .F. NAME = "FORM1" ADD OBJECT LABEL1 AS LABEL WITH; AUTOSIZE = .T.,; CAPTION = "УРОВЕНЬ СЛОЖНОСТИ (ОТ 4 ДО 9 ) " , ; HEIGHT = 17,; LEFT = 1,; TOP = 4, ; WIDTH = 172,; NAME = "LABEL1" ADD OBJECT TEXT1 AS TEXTBOX WITH; HEIGHT = 23,;
Урок 27. Создание классов в Class Designer LEFT = 37,; TOP - 24, f • WIDTH = 100,; NAME = "TEXT1" ADD OBJECT COMMAND1 AS COMMANDBUTTON WITH; TOP = 51,; LEFT = 12,; HEIGHT - 27, ; WIDTH = 60, ; CAPTION = "ВЫХОД",; NAME = "COMMAND1" ADD OBJECT COMMAND2 AS COMMANDBUTTON WITH; TOP = 51, ; LEFT = 93,; HEIGHT = 27,; WIDTH = 60,; CAPTION = "ЗАПУСК",; NAME - "COMMAND2" PROCEDURE TEXT1.ERRORMESSAGE =MESSAGEBOX("БУДЬТЕ ВНИМАТЕЛЬНЕЙ!","ОШИБКА") ENDPROC
PROCEDURE TEXT1.VALID IF EMPTY(THIS.VALUE) RETURN .F. ENDIF IF VAL(THIS.VALUE)<4 RETURN .F. ENDIF IF VAL(THIS.VALUE)>9 RETURN .F. ENDIF ENDPROC PROCEDURE COMMAND2.CLICK PUBLIC NLEVEL && Это - уровень сложности, а если проще количество кнопок NLEVEL=VAL(THIS FORM.ТЕХТ1.VALUE)
ENDDEFINE
365
366
Часть II. Объектно-ориентированное программирование
"Блок 2" — на данном этапе мы создаем массив со случайной и, более того, неповторяющейся последовательностью чисел (листинг 27.7). Размер масси ва определяется значением переменной NLEVEL. Листинг 27.7. Блок 2 ;
£
#DEFINE COUNT_OF_ITEMS NLEVEL*NLEVEL LOCAL ARRAY LARAND[COUNT_OF_ITEMS] LOCAL ARRAY LATEMP[COUNT_OF_ITEMS] LOCAL I , J , N RAND(-l) N=COUNT_OF_ITEMS FOR 1=1 TO COUNT_OF_ITEMS LATEMP[I]=1-1 ENDFOR FOR 1=1 TO COUNT_OF_ITEMS J=INT(RAND()*N)+1 LARAND[I]=LATEMP[J] =ADEL(LATEMP, J) N=N-1 ENDFOR FOR 1=1 TO COUNT_OF_ITEMS ENDFOR
"Блок 3" — создаем непосредственно игровое поле, размещаем на нем необ ходимое количество кнопок и случайным образом размещаем надписи на них (листинг 27.8). Листинг 27.8. Блок 3 PUZZLE=CREATEOBJECT("FORM") PUZZLE.CAPTION="FOXPUZZLE" DL=30 WT=30 FOR F=l TO NLEVEL FOR D=l TO NLEVEL PUZZLE.ADDOBJECT("PZ"+ALLTR(STR(D))+ALLTR(STR(F)) , "PUZZLEBUTTON") M2="PZ"+ALLTR(STR(D) ) +ALLTR(STR(F) J +".LEFT" M1="PZ"+ALLTR(STR(D))+ALLTR(STR(F))+".VISIBLE" M3="PZ"+ALLTR(STR(D))+ALLTR(STR(F))+".WIDTH" M4="PZ"+ALLTR(STR(D))+ALLTR(STR(F))+".TOP" M5="PZ"+ALLTR(STR(D) )+ALLTR(STR(F) )+".CAPTION"
Урок 27. Создание классов в Class Designer
367
PUZZLE.&M4=(F)*WT PUZZLE.&M2=DL*(D-1) PUZZLE.&M1=.T. PUZZLE.&M3=DL PUZZLE.WIDTH=DL*D PUZZLE.HEIGHT=WT*(F+2) ENDFOR ENDFOR 1=0 FOR R * l TO NLEVEL FOR K=l TO NLEVEL M5=-"PZ"+ALLTR (STR(R))+ALLTR(STR(K))+".CAPTION" 1=1+1 PUZZLE.&M5=ALLTR(STR(LARAND(I))) ENDFOR ENDFOR PUZZLE.AUTOCENTER=.T. PUZZLE.SHOW(1) ENDPROC PROCEDURE COMMAND1.CLICK THISFORM.RELEASE() ENDPROC ENDDEFINE
"Блок 4" — самое интересное — мы размещаем на игровом поле не просто командные кнопки, а объекты, созданные на основе собственного класса. Код этого класса представлен в листинге 27.9. Листинг 27.9. Блок 4 DEFINE CLASS PUZZLEBUTTON AS COMMANDBUTTON HEIGHT = 27 WIDTH = 84 CAPTION =
""
NAME = "PUZZLEBUTTON" PROCEDURE CLICK THISNAME=THIS.CAPTION DIGIT_PART=INT(VAL(RIGHT(THIS.NAME,2))) I F TYPE("THISFORM."+"PZ"+ALLTR(STR(DIGITJPART+1))+".NAME")="C" NEXTNAME="THISFORM."+"PZ"+ALLTR(STR(DIGIT PART+1))+".CAPTION"
368
Часть II. Объектно-ориентированное программирование
IF &NEXTNAME="0" THIS.CAPTION=&NEXTNAME &NEXTNAME=THISNAME ENDIF ENDIF ********************************************************************* ,
IF TYPE("THISF0P^."V PZ"+ALLTR(STR(DIGITJ>ART-1))V\NAME")="C" NEXTNAME="THISFORM."+"PZ"+ALLTR(STR(DIGIT_PART-1))+".CAPTION" IF &NEXTNAME="0" THIS.CAPTION=&NEXTNAME &NEXTNAME=THISNAME ENDIF ENDIF ************** IF TYPE("THISFORM."+"PZ"+ALLTR(STR(DIGIT_PART+10))+".NAME")="C" NEXTNAME="THISFORM."+"PZ"+ALLTR(STR(DIGIT_PART+10))+".CAPTION" IF &NEXTNAME="0" THIS.CAPTION=&NEXTNAME &NEXTNAME=THISNAME ENDIF ENDIF *************** IF TYPE("THISFORM."+"PZ"+ALLTR(STR(DIGIT_PART-10))+".NAME")="C" NEXTNAME="THISFORM."+"PZ"+ALLTR(STR(DIGIT_PART-10))+". CAPTION" IF &NEXTNAME="0" THIS.CAPTION=&NEXTNAME &NEXTNAME=THISNAME ENDIF ENDIF ENDPROC ENDDEFINE
Наиболее важным для нас является событие click, наступающее при щелч ке мышью на объекте. Но и тут ничего сложного: просто с помощью функ ции TYPE о , возвращающей переменную, обозначающую тип объекта, мы проверяем — а есть ли вообще "соседние" объекты у нашей кнопки? Если есть, производим проверку надписи соседнего объекта. Если надпись "0", то просто меняем надписи на этих двух кнопках между собой. Вот и все. Ко нечно, это не готовая игрушка, а просто учебный пример, показывающий тебе удобство использования объектно-ориентированного программирова ния. Для полноценной игрушки неплохо бы добавить процедуру провер-
Урок 27. Создание классов в Class Designer
369
ки — а не расположены ли надписи на кнопках уже по порядку? Можно придумать счетчик ходов, изменить оформление и т. д. Но это уже, как по нимаешь, дело наживное.
Другие полезные примеры Теперь мы немного поработаем с Class Designer и создадим с помощью данного инструмента еще несколько классов. Как я уже говорил, работа с этим конструктором почти ничем не отличается от работы с конструктором форм. И вот первое задание, на "засыпку": попробуй изменить цвет команд ной кнопки. Что, никак? И не получится (по крайней мере, в шестой версии Visual FoxPro). Тем не менее мы можем создать свой класс с определенны ми свойствами. 1. В окне диспетчера проекта перейдем на вкладку Classes (Классы) и на жмем кнопку New (Новый). 2. В открывшемся диалоговом окне укажем имя нового класса, класс-роди тель и библиотеку, в которой будет сохранен новый класс (рис. 27.13).
Рис. 27.13. Мы создаем новый класс на основе базового класса C o n t a i n e r
3. После нажатия кнопки ОК открывается диалоговое окно Class Designer (Конструктор классов), в котором непосредственно и будет происходить дальнейший процесс создания нового класса. Воспользовавшись стан дартной панелью Form Controls (Элементы управления экранной фор мы), разместим в окне Class Designer (Конструктор классов) объект container, а затем поместим в него объект shape (рис. 27.14). 4. Настроив такие свойства наших объектов, как цвет, размеры и т. д., об ратимся к событию init объекта container (который имеет имя ColorButton): THIS.SHAPE1.WIDTH=THIS.WIDTH-2 THIS.SHAPE1.HEIGHT=THIS.HEIGHT-2
Что произойдет? Да просто размеры объекта shape соответствующим об разом будут "подогнаны" под размер "своего" контейнера.
Часть II. Объектно-ориентированное программирование
370
Рис. 27.14. Объекты размещены в окне Class Designer
5. А теперь напишем обработку для события click объекта shape: THIS.LEFT=THIS..LEFT+2 THIS.TOP=THIS..TOP+2 WAIT "" TIMEOUT 0 . 1 THIS.LEFT=THIS..LEFT-2 THIS.TOP=THIS..TOP+2
Здесь мы изменяем значения свойств Left и тор, устанавливая их равж ми соответствующим свойствам контейнера, которому "принадлежит" данный объект. Изменение данных свойств приводит к эффекту "нажатия" на объект, после чего мы восстанавливаем исходные значения ука занных свойств. А для чего нам нужна строка WAIT "" TIMEOUT O . I ? Дело в том, что изме нение и восстановление этих значений произойдет так быстро, что мы ничего и не увидим! А команда WAIT прерывает выполнение программы на время, указанное в параметре TIMEOUT. Время указывается в секундах. Более того, после WAIT необходимо использовать пустые кавычки, чтобы подавить вывод системного сообщения FoxPro "Press any key to conti-
Урок 27. Создание классов в Class Designer
371
nue..." (Для продолжения нажмите любую клавишу). Кстати, в этих же кавычках можно ввести текст своего собственного сообщения. Результат наших действий представлен на рис. 27.15.
Рис. 27.15. Форма с цветными кнопками
А какой в этом практический смысл? Да сам не знаю. Хотя, если подумать... Можно, допустим, создать собственную панель инструментов и разместить там такие кнопки разного цвета. При нажатии на кнопку можно менять цвет активной экранной формы или цвет активного элемента управления. Можно использовать в какой-нибудь игрушке... А можно и вообще нигде не использовать — поучились и ладно. Более полезный пример — создание группы кнопок для навигации по записям таблицы. 1. Создаем
Класс
Navigator
на
основе
базового
класса
CommandGroup
(рис. 27.16). 2. Теперь осталось запрограммировать действия, происходящие при нажа тии кнопок (листинг 27.10). Листинг 27.10. Группа кнопок для навигации "Первая" GO TOP __SCREEN.ACTIVEFORM.REFRESH() "Следующая" IF EOF() =MESSAGEBOX("Последняя запись", "Конец файла") ELSE SKIP _SCREEN.ACTIVEFORM.REFRESH() ENDDIF
372
Часть II. Обьектно-ориентированное программирование
"Предыдущая" IF BOFO =MESSAGEBOX("Первая з а п и с ь " , "Начало файла") ELSE SKIP-1 _SCREEN.ACTIVEFORM.REFRESH() ENDIF "Последняя" GO BOTTOM SCREEN.ACTIVEFORM.REFRESH()
Рис. 27.16. Создание нового класса А вот и код с а м о г о класса — л и с т и н г 27.11. Листинг 27.11. Класс N a v i g a t o r ***************************** ********* ***************************** *— CLASS: *— PARENTCLASS: *— BASECLASS: *
NAVIGATOR (C:\CALC\MYLIB.VCX) COMMANDGROUP COMMANDGROUP
Урок 27. Создание классов в Class Designer DEFINE CLASS NAVIGATOR AS COMMANDGROUP BUTTONCOUNT = 4 VALUE = 1 HEIGHT
=36
WIDTH = 289 NAME = "NAVIGATOR" COMMAND1.AUTOSIZE =
.T.
COMMANDl.TOP = 5 COMMAND1.LEFT = 5 COMMAND1.HEIGHT = 25 COMMANDl.WIDTH = 54 COMMANDl.FONTSIZE = 8 COMMANDl.CAPTION = "ПЕРВАЯ" COMMAND1.NAME = "COMMANDl" COMMAND2.AUTOSIZE =
.T.
COMMAND2.TOP = 5 COMMAND2.LEFT = 58 COMMAND2.HEIGHT = 2 5 COMMAND2.WIDTH
=75
COMMAND2.FONTSIZE = 8 COMMAND2.CAPTION =
"СЛЕДУЩАЯ"
COMMAND2.NAME « "COMMAND2" COMMAND3.AUTOSIZE =
.Т.
COMMAND3.TOP = 5 COMMAND3.LEFT = 132 COMMAND3.HEIGHT = 25 COMMAND3.WIDTH
=81
COMMAND3.FONTSIZE = 8 COMMAND3.CAPTION = "ПРЕДВДУЩАЯ" COMMAND3.NAME = "COMMAND3" COMMAND4.AUTOSIZE -
.T.
COMMAND4.TOP = 5 COMMAND4.LEFT = 212 COMMAND4.HEIGHT = 25 COMMAND4.WIDTH
=71
COMMAND4.FONTSIZE = 8 COMMAND4.CAPTION = "ПОСЛЕДНЯЯ" COMMAND4.NAME = "COMMAND4"
PROCEDURE COMMANDl.CLICK GO TOP _SCREEN. ACTIVE FORM. REFRESH () ENDPROC PROCEDURE COMMAND2.CLICK
373
374
Часть II. Объектно-ориентированное программирование IF EOF() = .T. =MESSAGEBOX("ПОСЛЕДНЯЯ ЗАПИСЬ",
"КОНЕЦ ФАЙЛА")
ELSE SKIP _SCREEN.ACTIVEFORM.REFRESH() ENDIF ENDPROC PROCEDURE COMMAND3.CLICK IF BOF() =MESSAGEBOX("ПЕРВАЯ ЗАПИСЬ", "НАЧАЛО ФАЙЛА") ELSE SKIP-1 _SCREEN.ACTIVEFORM.REFRESH() ENDIF ENDPROC PROCEDURE COMMAND4.CLICK GO BOTTOM _SCREEN.ACTIVEFORM.REFRESH() ENDPROC ENDDEFINE * *— ENDDEFINE: NAVIGATOR
Данный класс можно включать в свои проекты и использовать для навига ции по записям таблицы. Еще один пример: масштабируемое поле ввода с тенью. 1. Разместим в окне Class Designer (Конструктор классов) элемент управ ления Container С расположенным "внутри" него Объектом TextBox (рис. 27.17). 2. В методе I n i t для данного контейнера пропишем: THIS.TEXT1.WIDTH=THIS.WIDTH-3 THIS.TEXT1.HEIGHT=THIS.HEIGHT-3 THIS.TEXT1.FONTSIZE=THIS .TEXTl.HEIGHT/1.6
Все, класс готов, можно посмотреть его в действии — рис. 27.18. Посмотрим его код — листинг 27.12. Листинг 2 7 . 1 2 . К л а с с ShadowTextBox
*--
CLASS:
*-- PARENTCLASS: * - - BASECLASS:
*
SHADOWTEXTBOX CONTAINER CONTAINER
(C:\CALC\MYLIB.VCX)
Урок 27. Создание классов в Class Designer DEFINE CLASS SHADOWTEXTBOX AS CONTAINER WIDTH = 438 HEIGHT =36 BACKCOLOR - RGB(128,128,228) NAME = "SHADOWTEXTBOX" ADD OBJECT TEXTl AS TEXTBOX WITH; HEIGHT = 23,; LEFT - 0, ; TOP = 0, ; WIDTH = 336, ; NAME = "TEXTl" PROCEDURE INIT THIS.TEXTl.WIDTH=THIS.WIDTH-3 THIS.TEXTl.HEIGHT=THIS.HEIGHT-3 THIS.TEXTl.FONTSIZE=THIS.TEXTl.HEIGHT/1.6 ENDPROC ENDDEFINE * *— ENDDEFINE: SHADOWTEXTBOX *************************************************************
Рис. 27.17. Новый класс в конструкторе классов
375
376
Часть II. Объектно-ориентированное программирование
Рис. 27.18. Три объекта, созданные на основе нового класса
Еще пример: создание собственного индикатора ProgressBar. Дело в том, что мы не можем изменить, допустим, цвет стандартного ProgressBar и т. д. А что мешает сделать свой индикатор? 1. За основу также берем контейнер. Затем размещаем на нем еще один и надпись (Label). Примерно вот так — рис. 27.19.
Рис. 27.19. Класс m y p r o g r e s s в конструкторе классов
Урок 27. Создание классов в Class Designer
377
2. Теперь осталось лишь настроить свойства данных объектов. В init на шего "главного" контейнера пишем следующее: THIS.LABEL1.LEFT=THIS.WIDTH/2-THIS.LABEL1.WIDTH/2 THIS.LABEL1.TOP=THIS.HEIGHT/2-THIS.LABEL1.HEIGHT/2 THIS.CONTAINER1.WIDTH=0 THIS.CONTAINER1.HEIGHT=THIS.HEIGHT
3. Разместим наш вновь созданный объект в экранной форме. Пусть это будет обычная форма, в качестве источника данных у которой будет ка кая-нибудь таблица (например, с одним полем, но с пятью тысячами записей), и кнопка, при нажатии которой начинается процесс сканиро вания записей нашей таблицы. В событии click данной кнопки пишем: SCAN THISFORM.MYPR0GRESS1.CONTAINER1.WIDTH=(THISFORM.MYPROGRESS1.WIDTH/; RECCOUNT (j ) *RECNO () THISFORM.MYPROGRESS1.LABELl.CAPTION=STR(RECNO()/RECCOUNT()*100)+"%" WAIT WINDOW "ОБРАБАТЫВАЕТСЯ ЗАПИСЬ № "+ ALLTR(STR(RECNO())) NOWAIT ENDSCAN
Результат наших действий представлен на рис. 27.20.
Рис. 27.20. Пример использования P r o g r e s s B a r
Часть II. Объектно-ориентированное программирование
378
И, как всегда, посмотрим код нашего класса — листинг 27.13. Листинг 27.13. Класс MyProgress
******************************************************************** *-- CLASS: *— PARENTCLASS: *— BASECLASS: *
MYPROGRESS (C:\CALC\MYLIB.VCX) CONTAINER CONTAINER
DEFINE CLASS MYPROGRESS AS CONTAINER WIDTH = 4 0 2 HEIGHT =40 BACKSTYLE m 0 BORDERWIDTH = 2 SPECIALEFFECT = 1 NAME = "MYPROGRESS" ADD OBJECT CONTAINERl AS CONTAINER WITH; TOP - 2,; LEFT = 0,; WIDTH - 61, ; HEIGHT = 37,; BORDERWIDTH = 2 , ; SPECIALEFFECT = 0, ; BACKCOLOR - RGB(0,255,255),; NAME = "CONTAINERl" ADD OBJECT LABEL1 AS LABEL WITH; AUTOSIZE = .T.,; FONTBOLD - .T.,; BACKSTYLE = 0 , ; CAPTION = "LABEL1",; HEIGHT = 17,; LEFT = 120, ; TOP = 12, ; WIDTH = 40, ; NAME = "LABEL1" PROCEDURE INIT THIS.LABEL1.LEFT=THIS.WIDTH/2-THIS.LABELl.WIDTH/2 THIS.LABELl.TOP=THIS.HEIGHT/2-THIS.LABELl.HEIGHT/2 THIS.CONTAINERl.WIDTH=0 THIS.CONTAINERl.HEIGHT=THIS.HEIGHT ENDPROC
Урок 27. Создание классов в Class Designer
379
PROCEDURE LABEL1.INIT THIS.CAPTION="0%" ENDPROC ENDDEFINE *— ENDDEFINE: MYPROGRESS ********************************************************************
Понятно, что, используя свой собственный индикатор, мы можем легко ме нять его самые различные свойства. Можно вместо второго контейнера по пробовать использовать какое-нибудь изображение, можно "заставить" наш индикатор подавать звуковые сигналы и т. д.
УРОК 28
Использование таймера До сих пор мы вели разговор об использовании визуальных классов. Но, если ты помнишь, существуют еще и невизуальные классы и одним из них является Timer. Объект класса Timer позволяет организовывать выполнение команд через заданный период времени. Основным свойством такого o6ъекта является свойство interval — именно в нем задается значение проме•жутка времени в миллисекундах. После истечения заданного времени про исходит событие Timer. Сейчас мы рассмотрим использование объектов класса Timer на конкретных примерах. Допустим, мы решили сделать кра сивую заставку, которая будет появляться перед запуском приложения, а затем исчезать с экрана. Создадим новый класс на основе базового класса Form (рис. 28.1).
Рис. 28.1. Создание нового класса
В конструкторе классов откроется макет нового класса. По виду это обыч ная экранная форма. Поместим на нее элемент управления Timer и произ ведем его настройку: свойство interval установим равным 2000 (две секун ды), а в событии Timer укажем: THISFORM. RELEASE о (рис. 28.2). Код созданного класса представлен в листинге 28.1.
Урок 28. Использование таймера
Рис. 28.2. Настройка свойств таймера
Листинг 28.1. Класс с использованием таймера *-- CLASS: *— PARENTCLASS: *~ BASECLASS:
SPLASH (C:\0LDF0X\MYL1B.VCX) FORM FORM
DEFINE CLASS SPLASH AS FORM HEIGHT = 2 8 6 WIDTH =379 SHOVWINDOW - 2 DOCREATE = .T. AUTOCENTER = .T. PICTURE = "..\DOCUMENTS AND SETTINGS\FLOWERS, CAPTION = "FORM2" CONTROLBOX = .F. TITLEBAR = 0 NAME = "SPLASH" ADD OBJECT TIMER1 AS TIMER WITH; TOP = 24.;
381
382
Часть II. Объектно-ориентированное программирован
LEFT = 252, ; HEIGHT = 23,; WIDTH = 23,; INTERVAL = 2000,; NAME = "TIMER1" ADD OBJECT IMAGE1 AS IMAGE WITH; PICTURE = "..\PROGRAM FILES\MICROSOFT VISUAL ^STUDIO\VFP98\FOX.BMP", ; STRETCH = 1,; HEIGHT - 48,; LEFT = 300,; TOP = 72,; WIDTH - 84,; NAME = "IMAGE1" ADD OBJECT LABEL2 AS LABEL WITH; AUTOSIZE = .T.,; FONTBOLD = .T.,; FONTSIZE = 22, ; BACKSTYLE = 0, ; CAPTION - "THE OLD FOX HOTEL",; HEIGHT = 37, ; LEFT = 65,; TOP = 81,; WIDTH = 251,; FORECOLOR = RGB(255,255, 255) , ; NAME = "LABEL2" ADD OBJECT IMAGE2 AS IMAGE WITH; PICTURE = "..\PROGRAM FILES\MICROSOFT VISUAL 4>STUDIO\VFP98\FOX.BMP",; STRETCH = 1,; HEIGHT = 48,; LEFT = 0,; TOP = 72,; WIDTH = 84,; NAME ш "IMAGE2" PROCEDURE TIMER1.TIMER THISFORM.RELEASE() ENDPROC ENDDEFINE * *— ENDDEFINE: SPLASH
Что же будет делать экранная форма, созданная на основе нашего нового класса? Да ничего особенного — просто исчезнет с экрана через две секун-
Урок 28. Использование таймера
383
ды после своего запуска. Еще один пример — "бегущая" строка. Для создания эффекта "бегущей" строки создадим класс на основе контейнера (рис. 28.3).
Рис. 28.3. "Бегущая" строка
На данном контейнере расположим два объекта: Label (свойство caption данного объекта будет определять текст бегущей строки) и Timer, в событии Timer которого пропишем следующие команды: WITH THIS.PARENT IF .LABELl.LEFT < .WIDTH .LABEL1.LEFT = .LABELl.LEFT + 1 ELSE .LABELl.LEFT = -.LABEL1.WIDTH ENDIF ENDWITH
Что-то новенькое, да? Я имею в виду PARENT. А на самом деле все просто: PARENT — это ссылка на объект, в состав которого входит наш элемент управления. В данном случае мы ссылаемся на наш контейнер. Теперь ос талось только установить желаемую скорость прокрутки (меняя значения свойства interval) и можно применять данный класс в любой экранной форме. Код созданного класса представлен в листинге 28.2. Листинг 28.2. "Бегущая" строка *— PARENTCLASS: CONTAINER *— BASECLASS: CONTAINER DEFINE CLASS RUNNING_STRING AS CONTAINER WIDTH = 647 HEIGHT = 2 1 NAME = "MYCLASS" ADD OBJECT LABELl AS LABEL WITH; CAPTION = "LABELl",; HEIGHT = 17,; LEFT = 120,; TOP = 4, ; WIDTH = 4 0, ; NAME = "LABELl"
Часть II. Объектно-ориентированное программирование
384
ADD OBJECT TIMER1 AS TIMER WITH; TOP = 4, ; LEFT = 288, ; HEIGHT = 23,; WIDTH = 23, ; NAME = "TIMER1" PROCEDURE TIMER1.TIMER WITH THIS.PARENT IF .LABEL1.LEFT < .WIDTH .LABEL1.LEFT = .LABEL1.LEFT + 1 ELSE .LABEL1.LEFT = -.LABELl.WIDTH END IF ENDWITH ENDPROC ENDDEFINE *— ENDDEFINE: RUNNING_STRING
И еще один пример — класс-секундомер (еще несколько страниц — и я только стихами — петь начну...). Мы не будем подробно останавливаться на процессе создания данно. класса, дабы не повторяться — этот класс также создан на базе экранн формы, вот так примерно он выглядит — рис. 28.4.
Рис. 28.4. Секундомер
А как и почему эта штука работает — посмотри код в листинге 28.3. I Листинг 28.3. Секундомер i
*-- CLASS: *— PARENTCLASS: * — BASECLASS:
SWATCH (C:\OLDFOX\MYLIB.VCX) FORM FORM
DEFINE CLASS SWATCH AS FORM TOP = 21 LEFT = 77 HEIGHT = 7 7 WIDTH = 258
Урок 28. Использование таймера D0CREATE - .Т. B0RDERSTYLE = О CAPTION = "FORM1" TITLEBAR = О BACKCOLOR = RGB(0,0,0) HOUR = О MINUTES = О SEC = О NAME = "F0RM1" ADD OBJECT TIMERl AS TIMER WITH; TOP = 48,; LEFT = 120,; HEIGHT = 23, ; WIDTH = 23,; INTERVAL = 1000,; NAME = "TIMERl" ADD OBJECT LABEL1 AS LABEL WITH; AUTOSIZE = .T.,; FONTITALIC = .T.,; FONTSIZE - 28,; ALIGNMENT = 2,; CAPTION = "",; HEIGHT » 46,; LEFT = 125, ; TOP = 2, ; WIDTH = 2,; FORECOLOR = RGB(255,255, 255) , ; BACKCOLOR = RGB(0,0,0),; NAME = "LABELl" ADD OBJECT CCMMANDl AS COMMANDBUTTON WITH; TOP = 48,; LEFT = 4,; HEIGHT = 27,; WIDTH = 60,; CAPTION = "ПАУЗА",; NAME = "COMMAND1" ADD OBJECT COMMAND2 AS COMMANDBUTTON WITH; TOP = 48,; LEFT = 68,; HEIGHT = 27,; WIDTH = 57,; CAPTION - "ЗАПУСК",; NAME = "CCMMAND2"
385
386
Часть II. Объектно-ориентированное программирование ADD OBJECT COMMAND3 AS CQMMANDBUTTON WITH; TOP = 48,; LEFT = 130, ; HEIGHT = 27,; WIDTH = 57, ; CAPTION = "СБРОС",; NAME = "COMMAND3"
ADD OBJECT COMMAND4 AS COMMANDBUTTON WITH; TOP = 48, ; LEFT = 192,; HEIGHT = 27,; WIDTH = 57,; CAPTION = "ВЫХОД",; NAME = "COMMAND4" PROCEDURE INIT PUBLIC MINUTES,HR,NSECONDS MINUTES=0 HR=0 NSECONDS=0 ENDPROC PROCEDURE TIMER1.TIMER NSECONDS=NSECONDS+l IF NSECONDS=60 NSECONDS=0 MINUTES=MINUTES+1 THISFORM.LABEL1.CAPTION=ALLTR(STR(HR))+":"+ALLTR(STR(MINUTES))+; ":"+ALLTR(STR(NSECONDS)) ENDIF *********•*******+******•***
THISFORM.LABEL1.CAPTION=ALLTR(STR(HR))+":"+ALLTR(STR(MINUTES))+; ":"+ALLTR(STR(NSECONDS)) IF MINUTES=60 MINUTES=0 HR=HR+1 THISFORM.LABEL1.CAPTION=ALLTR(STR(HR))+":"+ALLTR(STR(MINUTES))+; ":"+ALLTR(STR(NSECONDS)) ENDIF ****************************** IF HR=24 HR=0 NSECONDS=0 MINUTES=0
Урок 28. Использование таймера
387
THISFORM. LABEL1.CAPTI0N==ALLTR(STR(HR))+":"+ALLTR(STR(MINUTES))+; ":"+ALLTR(STR(NSECONDS)) END IF ENDPROC PROCEDURE COMMAND1.CLICK THISFORM.TIMER1.INTERVAL=0 ENDPROC PROCEDURE COMMAND2.CLICK THISFORM.TIMER1.INTERVAL=1000 ENDPROC PROCEDURE COMMAND3.CLICK THISFORM. TIMER1. INTERVALS THISFORM.LABEL1.CAPTION="0:0:0" MINUTES=0 HR=0 NSECONDS=0 ENDPROC PROCEDURE COMMAND4.CLICK THISFORM.RELEASE() ENDPROC ENDDEFINE * *— ENDDEFINE: SWATCH
И еще несколько слов о применении элемента управления Timer. Допустим, мы работаем в сети с какой-то базой данных. Для просмотра данных ис пользуется Grid. С помощью таймера можно указать период времени, через который будет происходить обновление данных в Grid. Достаточно указать в событии Timer: THISFORM.GRID.REFRESH
УРОК 29
Создание экранных форм на основе пользовательских классов До сего момента мы создавали экранные формы на основе базового класса Form, поставляемого вместе с Visual FoxPro. Но мы можем создать на базе этого основного класса свой класс, а уже на основе созданного класса соз давать экранные формы. В качестве примера "соорудим" свой MessageBox. Что это такое, ты уже видел. Итак, создаем новый класс — рис. 29.1.
Рис. 29.1. Создаем новый класс на основе класса Form Вот так будет выглядеть наш новый класс — рис. 29.2.
Рис. 29.2. Готовый класс на основе класса Form А код созданного класса представлен в листинге 29.1. Листинг 29.1. Класс MyMessageBox *-- CLASS: *— PARENTCLASS: *— BASECLASS:
MYMESSAGEBOX (C:\OLDFOX\MYLIB.VCX) FORM FORM
Урок 29. Создание экранных форм на основе пользовательских классов 389 DEFINE CLASS MYMESSAGEBOX AS FORM HEIGHT - 40 WIDTH - 155 DOCREATE - .T. AUTOCENTER - .T. CAPTION - "Завершить работу?" CLOSABLE - .P. MAXBUTTON - .F. MINBUTTON - .F. ICON = "..\PROGRAM FILES\MICROSOFT VISUAL 4>STUDIO\COMMON\GRAPHICS\ICONS\MISC\QUESTION.ICO" WINDOWTYPE = 1 BACKCOLOR = RGB(255,255,255) NAME = "MYMESSAGEBOX" ADD OBJECT SHADOWBUTTON1 AS SHADOWBUTTON WITH; TOP = 6, ; LEFT - 3,; WIDTH = 69, ; HEIGHT = 30, ; NAME = "SHADOWBUTTON1",; COMMAND1.CAPTION = "ДА",; COMMANDl.NAME = "COMMAND1" ADD OBJECT SHADOWBUTTON2 AS SHADOWBUTTON WITH; TOP = 6, ; LEFT * 80,; WIDTH - 69, ; HEIGHT = 30, ; NAME - "SHADOWBUTTON2",; COMMAND1.CAPTION = "НЕТ",; COMMAND1.NAME = "COMMANDl" PROCEDURE SHADOWBUTTONl.COMMANDl.CLICK CLOSE ALL CLEAR EVENTS QUIT ENDPROC PROCEDURE SHADOWBUTTON2.COMMANDl.CLICK THISFORM.RELEASE() ENDPROC ENDDEFINE *— ENDDEFINE: MYMESSAGEBOX
Все хорошо, но не смущает ли тебя тот факт, что кнопки нашего MessageBox сделаны не на основе уже знакомого нам базового класса CommanddButton, a
390
Часть II. Объектно-ориентированное программирование
на основе какого-то таинственного класса shadowButton? И непонятно, от куда взялся этот класс — ведь в программном коде он не определен... А этот класс создан заранее, и расположен он в той же библиотеке классов, что и н а ш Класс MessageBox (ЛИСТИНГ 29.2). Листинг 29.2. Класс ShadowButton DEFINE CLASS SHADOWBUTTON AS CONTAINER WIDTH = 86 HEIGHT = 30 BACKCOLOR = RGB(0,0,0) NAME = "SHADOWBUTTON" ADD OBJECT COMMANDl AS COMMANDBUTTON WITH; TOP = 0,; LEFT - 0,; HEIGHT - 27,; WIDTH = 84,; CAPTION = "COMMANDl",; NAME = "COMMAND1" PROCEDURE INIT THIS.COMMAND1.WIDTH=THIS.WIDTH-2 THIS.COMMAND1.HEIGHT=THIS.HEIGHT-2 THIS.COMMANDl.FONTSIZE=THIS.COMMANDl.HEIGHT/4.5 ENDPROC ENDDEFINE
Более интересным примером может послужить пример формы, в которой размеры всех входящих в нее элементов управления изменяются при изме нении размеров самой формы. Данный пример найден автором на просто рах сети Интернет и создателем сего кода является В. Поторочин. Откроем конструктор форм для создания новой формы — рис. 29.3. Теперь добавим в нашу форму новые свойства: • Firstheight — первоначальная высота формы; • Firstwidth — первоначальная ширина формы; • Nkofh — коэффициент изменения высоты формы; • Nkofw — коэффициент изменения ширины формы; • Amas[i,i] — в этом массиве будут храниться первоначальные значения размеров всех объектов формы; • Nkolm — размерность массива;
Урок 29. Создание экранных форм на основе пользовательских классов
391
• Nb1,Nb2 — эти значения будут использованы при изменении свойства Fontsize (Размер шрифта); • Ndelta — текущее смещение значения Fontsize.
Рис. 29.3. Новая форма в конструкторе
Как поместить в свойства формы массив? Точно так же, как и обычные пе ременные — рис. 29.4. Теперь нашу форму необходимо "оснастить" новым методом Recurs. Его код представлен в листинге 29.3.
Рис. 29.4. В качестве нового свойства — массив
392
Часть II. Объектно-ориентированное программирование
Листинг 29.3. Метод Recurs LPARAMETERS OOBJ, LP LOCAL NTOTMEM,I,AMEMS[1],М1 Ml - 7 WITH OOBJ IF THISFORM.NAME # .NAME OR THISFORM.BASECLASS # .BASECLASS IF TYPE("OOBJ.TOP") - "N" OR TYPE("OOBJ.HEIGHT") - "N"; OR TYPE("OOBJ.LEFT") - "N" OR TYPE("OOBJ.WIDTH") = "N"; OR TYPE("OOBJ.FONTSIZE") - "N" THISFORM.NKOLM = THISFORM.NKOLM + 1 IF
!LP
DIMENSION THISFORM.AMAS[THISFORM.NKOLM,Ml] IF TYPE("OOBJ.TOP") = "N" THISFORM.AMAS[THISFORM.NKOLM,1] =COBJ.TOP ENDIF IF TYPE("OOBJ.HEIGHT") = "N" THISFORM.AMAS[THISFORM.NKOLM,2] = OOBJ.HEIGHT ENDIF IF TYPE("OOBJ.LEFT") = "N" THISFORM.AMAS[THISFORM.NKOLM,3] = OOBJ.LEFT ENDIF IF TYPE("OOBJ.WIDTH") = "N" THISFORM.AMAS[THISFORM.NKOLM,4] = OOBJ.WIDTH ENDIF IF TYPE("OOBJ.HEADERHEIGHT") = "N" THISFORM.AMAS[THISFORM.NKOLM,5] =OOBJ.HEADERHEIGHT ENDIF IF TYPE("OOBJ.ROWHEIGHT") = "N" THISFORM.AMAS[THISFORM.NKOLM, 6] = OOBJ.ROWHEIGHT ENDIF IF TYPE("OOBJ.FONTSIZE") = "N" THISFORM.AMAS[THISFORM.NKOLM,7] =OOBJ.FONTSIZE ENDIF ELSE IF TYPE("OOBJ.TOP") = "N" OOBJ.TOP = THISFORM.AMAS[THISFORM.NKOLM,1]*THISFORM.NKOFH ENDIF IF TYPE("OOBJ.HEIGHT") = "N" OOBJ.HEIGHT = THISFORM.AMAS[THISFORM.NKOLM,2]*THISFORM.NKOFH ENDIF I F TYPE("OOBJ.LEFT") = " N "
OOBJ.LEFT = THISFORM.AMAS[THISFORM.NKOLM,3]*THISFORM.NKOFW ENDIF
Урок 29. Создание экранных форм на основе пользовательских классов
393
IF TYPEC'OOBJ.FONTSIZE") = "N" IF (THISF0RM.AMAS[THISF0RM.'NK0LM,7]*THISTORM.NK0FH)-THISF0RM.NDELTA > 4 OOBJ.FONTSIZE = (THISFORM.AMAS[THISFORM.NKOLM,7]*THISFORM.NKOFH)THISFORM.NDELTA ELSE OOBJ.FONTSIZE = 4 THISFORM.NDELTA = THISFORM.NDELTA - 1 ENDIF ENDIF IF TYPE("OOBJ.WIDTH") = "N" IF (OOBJ.BASECLASS ="LABEL" AND !.WORDWRAP); OR OOBJ.BASECLASS ="CHECKBOX" IF (TXTWIDTH(OOBJ.CAPTION,OOBJ.FONTNAME,OOBJ.FONTSIZE))*; FONTMETRIC(6,OOBJ.FONTNAME,OOBJ.FONTSIZE) > OOBJ.WIDTH THISFORM.NB1 = 1 THISFORM.NB2 = 0 ENDIF IF (TXTWIDTH(OOBJ.CAPTION,OOBJ.FONTNAME,OOBJ.FONTSIZE+1)) *; FONTMETRIC(6,OOBJ.FONTNAME,OOBJ.FONTSIZE+1) > OOBJ.WIDTH THISFORM.NB2 = 0 ENDIF ENDIF OOBJ.WIDTH = THISFORM.AMAS[THISFORM.NKOLM,4]*THISFORM.NKOFW ENDIF IF TYPEC'OOBJ.HEADERHEIGHT") = "N" OOBJ.HEADERHEIGHT = THISFORM.AMAS[THISFORM.NKOLM,5]*THISFORM.NKOFH ENDIF IF TYPE("OOBJ.ROWHEIGHT") = "N" OOBJ.ROWHEIGHT = THISFORM.AMAS[THISFORM.NKOLM,6]*THISFORM.NKOFH ENDIF ENDIF ENDIF ENDIF NTOTMEM = AMEMBERS(AMEMS,OOBJ,2) FOR I = 1 TO M.NTOTMEM OOBJ = EVAL("."+AMEMS[M.I]) IF TYPE("."+AMEMS[M.I]) = "0" THISFORM.RECURS(OOBJ, LP) ENDIF ENDFOR ENDWITH
Для этого необходимо вызвать пункт New Method (Новый метод) из систем ного меню Form (Форма), в диалоговом окне указать имя метода и нажать
394
Часть (I. Объектно-ориентированное программирование
кнопку Add (Добавить). Название данного метода отобразится в окне свойств экранной формы Properties. Теперь нужно дважды щелкнуть мышью на надписи Default (справа от имени метода) и внести в открывшее ся окно редактирования процедур приведенный ранее текст программного кода. В метод init экранной формы поместить: THISFORM.FIRSTHEIGHT=THISFORM.HEIGHT THISFORM.FIRSTWIDTH=THISFORM.WIDTH THISFORM.NKOLM = 0 THISFORM.NDELTA = 0 THISFORM.RECURS (THISFORM, .F.) А В метод Resize: THISFORM.NKOFH = THISFORM.HEIGHT/THISFORM.FIRSTHEIGHT THISFORM.NKOFW = THISFORM.WIDTH/THISFORM.FIRSTWIDTH THISFORM.NKOLM = 0 THISFORM.NB1 = 0 THISFORM.NB2 = 1 THISFORM.RECURS(THISFORM, .T.) IF (THISFORM.NB2 > 0 AND THISFORM.NDELTA > 0); OR (THISFORM.NB1 > 0) THISFORM.NDELTA = THISFORM.NDELTA + THISFORM.NB1 THISFORM.NDELTA = THISFORM.NDELTA - THISFORM.NB2 ENDIF
Все готово! Но мы ведь создали обычную экранную форму, а как же обе щанный класс? Превратить форму в класс проще простого — вызываем пункт Save As Class (Сохранить как класс) из системного меню File (Файл) — рис. 29.5.
Рис. 29.5. Диалоговое окно Save As Class
Урок 29. Создание экранных форм на основе пользовательских классов
395
В диалоговом окне Save As Class (Сохранить как класс) необходимо указать имя класса и библиотеку классов, которой он будет принадлежать. Чтобы убедиться, что наша форма действительно работает, разместим на ней ос новные элементы управления и попробуем ее запустить — рис. 29.6, 29.7.
Рис. 29.6. Исходное состояние формы
Рис. 29.7. После изменения размеров формы
Как видим, все прекрасно работает. Ну а как же все-таки создавать формы на основе своих классов? Для этого нужно обратиться к диалоговому окну настроек Visual FoxPro. Вызывается это окно из пункта Options (Настройки) системного меню Tools (Инструменты) — рис. 29.8.
396
Часть II. Объектно-ориентированное программирование
Рис. 29.8. Диалоговое окно Options
Теперь нужно перейти на вкладку Forms (Формы) и в группе переключате лей Template classes (Шаблоны) установить флажок Form (Форма), после чего откроется диалоговое окно Form Template (Шаблон формы) (рис. 29.8). Здесь необходимо указать нужную библиотеку классов, а в окне Class Name (Имя класса) указать имя класса. После проделанных манипуляций все новые экранные формы будут созда ваться на основе выбранного класса.
Рис. 29.9. Диалоговое окно Form Template
УРОК 30
Создание панели инструментов Класс TooiBar (Панель инструментов) представляет собой разновидность экранной формы. Обычно он включает в себя такие элементы управления, как командные кнопки, но в данный контейнер, как и в форму, можно включить все, что угодно. Создаем свою панель — рис. 30.1.
Рис. 30.1. Создание панели инструментов
398
Часть II. Объектно-ориентированное программирование
Посмотрим код? Листинг 30.1. Листинг 30.1. Создание панели инструментов DEFINE CLASS MY_NAVIGATOR AS TOOLBAR CAPTION = "" HEIGHT = 4 0 LEFT = 0 TOP = 0 WIDTH = 136 NAME = "MY_NAVIGATOR" ADD OBJECT COMMANDl AS COMMANDBUTTON WITH; TOP = 5,; LEFT - 5,; HEIGHT - 31,; WIDTH = 34,; PICTURE = "..\PROGRAM FILES\MICROSOFT VISUAL ->STUDIO\COMMON\GRAPHICS\ICONS\ARROWS\ARW06UP. ICO", ; CAPTION = "",; TOOLTIPTEXT = "ПЕРВАЯ ЗАПИСЬ",; NAME - "COMMANDl" ADD OBJECT COMMAND2 AS COMMANDBUTTON WITH; TOP = 5,; LEFT - 38,; HEIGHT = 31,; WIDTH - 32,; PICTURE = "..\PROGRAM FILES\MICROSOFT VISUAL ^STUDIO\COMMON\GRAPHICS\ICONS\ARROWS\ARW06RT.ICO",; CAPTION = "",; TOOLTIPTEXT = "СЛЕДУЮЩАЯ ЗАПИСЬ",; NAME = "COMMAND2" ADD OBJECT COMMAND4 AS COMMANDBUTTON WITH; TOP - 5,; LEFT - 69,; HEIGHT = 31,; WIDTH = 34,; PICTURE = "..\PROGRAM FILES\MICROSOFT VISUAL 4>STUDIO\C(M4ON\GRAPHICS\ICONS\ARROWS\ARW06DN. ICO", ; CAPTION = "",; TOOLTIPTEXT = "ПРЕДЫДУЩАЯ ЗАПИСЬ",; NAME = "COMMAND4"
Урок 30. Создание панели инструментов
399
ADD OBJECT COMMAND3 AS COMMANDBUTTON WITH; TOP - 5,; LEFT = 102, ; HEIGHT = 31,; WIDTH = 29, ; PICTURE = "..\PROGRAM FILES\MICROSOFT VISUAL "bSTUDIO\COMMON\GRAPHICS\ICONS\ARROWS\ARW06LT.ICO", ; CAPTION = "",; TOOLTIPTEXT = "ПОСЛЕДНЯЯ ЗАПИСЬ",; NAME - "COMMAND3" PROCEDURE COMMAND1.CLICK IF !BOF() GO TOP _SCREEN.ACTIVEFORM.REFRESH() ENDIF ENDPROC PROCEDURE COMMAND2.CLICK IF !EOF() SKIP _SCREEN.ACTIVEFORM.REFRESH() ENDIF ENDPROC PROCEDURE COMMAND4.CLICK IF !EOF() GO BOTTOM _SCREEN.ACTIVEFORM.REFRESH() ENDIF ENDPROC PROCEDURE COMMAND3.CLICK IF !BOF() SKIP -1 _SCREEN.ACTIVEFORM.REFRESH() ENDIF ENDPROC ENDDEFINE
Данную панель инструментов можно включить в экранную форму — рис. 30.2. Естественно, в панели инструментов можно использовать как элементы управления, созданные на основе базовых классов Visual FoxPro, так и соз данные на основе пользовательских классов.
400
Часть II. Обьектно-ориентированное программирование
Рис. 30.2. Использование панели инструментов для просмотра записей
УРОК 3 1
Управление классами На этом уроке мы познакомимся с инструментом, который позволяет на много упростить работу с классами.
Class Browser В Visual FoxPro имеется удобное средство, с помощью которого можно ра ботать с классами: создавать новые, редактировать существующие, а также просматривать библиотеки классов. Называется оно Class Browser (Браузер классов). Открыть его можно двумя способами: в системном меню Tools (Инструменты) выбрать команду Class Browser (Браузер классов) или на брать в командном окне: DO (BROWSER) . Каким бы способом мы его не вы зывали, результат будет один — рис. 31.1.
Рис. 31.1. Окно Class Browser
402
Часть II. Объектно-ориентированное программирование
Данное окно содержит панель инструментов с кнопками, назначение кото рых описано в табл. 31.1. Таблица 31.1. Кнопки панели окна Class Browser
При щелчке правой кнопкой мыши на окне Class Browser (Браузер классов) открывается контекстное меню — рис. 31.2. Описание команд контекстного меню приведено в табл. 31.2.
Урок 31. Управление классами
403
Рис. 31.2. Контекстное меню Таблица 31.2. Команды контекстного меню Class Browser Команда
Описание
Descriptions (Описание)
Включает или выключает панели описания биб лиотеки и класса в нижней части окна Class Browser
Always on Top (Всегда на переднем плане)
Если стоит отметка, то окно Class Browser на ходится всегда на переднем плане
Auto Expand (Автоматическое расширение)
Если стоит отметка, список автоматически раз ворачивается
Parent Class Toolbar (Просмотр родительского класса)
Если стоит отметка, в системное меню доба вится кнопка для редактирования методов ро дительских классов
Restore Defaults (Восстановить настройки)
Восстанавливает настройки Class Browser
Hierarchical (Иерархия)
Если стоит отметка, то список классов отобра жается в виде иерархического дерева
Protected (Защищенные)
Если стоит отметка, то будут отображаться и защищенные члены класса
Hidden (Скрытые)
Если стоит отметка, то будут отображаться и скрытые члены класса
Empty (Пустые)
Если стоит отметка, то будут отображаться и пустые члены класса
404
Часть II. Объектно-ориентированное программирование Таблица 31.2 (окончание)
Команда
Описание
Modify (Изменение)
Происходит изменение (модификация) выбран ного класса
Rename (Переименовать)
. Переименование выбранного объекта
Redefine (Переопределить)
Изменение родительского класса для выбран ного класса
Remove (Удалить)
Удаляет указанный класс из библиотеки клас сов
View (Просмотр)
Просмотр текущего значения для выбранного свойства
Container Icon (Иконка)
Пиктограмма для выбранного класса
Select Parent Class (Выбор)
Выбор базового класса для указанного объекта
New Window (Новое окно)
Новое окно Class Browser
New Component Gallery (Новая галерея компонентов)
Новое окно галереи компонентов
Refresh (Обновить)
Обновление окна
Help (Справка)
Справка о Class Browser
При создании приложений очень удобно использовать окно просмотра кода класса — достаточно скопировать текст и затем можно его использовать в качестве программ или подпрограмм.
Информация о классе и пиктограмма класса Для просмотра информации о классе используется диалоговое окно Class Info (Информация о классе) (рис. 31.3). Оно вызывается с помощью одно именной команды из меню Class. Данное окно содержит две вкладки: Class (Класс) и Members (Члены). На вкладке Class (Класс) мы можем указать значок (пиктограмму) для каждого класса. Вернее, значка там можно указать два: один в поле ввода Toolbar icon (Значок на панели инструментов) — данный значок будет отображаться на панели инструментов Form Controls, а другой — в поле Container icon (Значок контейнера) — он будет отображаться в окне Class Browser. He знаю, как насчет второго, а вот первый рекомендую указывать — ты ведь уже заметил, что все однотипные объекты твоей библиотеки отображаются на панели инструментов одинаковыми значками и определить, "кто есть
Урок 31.
Управление классами
405
кто" можно только по всплывающей подсказке. Представь себе 187 одина ковых значков и ты поймёшь, о чем это я... Перейдем к рассмотрению вкладки Members (Члены) — рис. 31.4.
Рис. 31.3. Диалоговое окно Class Info, вкладка Class
Рис. 31.4. Диалоговое окно CJass Info, вкладка Members
406
Часть II. Объектно-ориентированное программирование
На данной вкладке отображен список объектов класса, а также перечень методов и свойств. Столбец Name (Имя) содержит имя класса, столбец Visibility (Видимость) может принимать три значения: Public (Глобальный), Protected (Защищенный) и Hidden (Скрытый). В столбце No Init можно за претить выполнение метода init при создании объекта. По нажатию кноп ки Modify (Модификация) открывается диалоговое окно Edit Property/Method (Редактирование свойств и методов) (рис. 31.5), в котором можно как изме нить значения выбранных свойств, так и добавить новое свойство или ме тод (кнопки New Property и New Method). Используя кнопку Remove (Уда лить), можно удалить указанный компонент.
Рис. 31.5. Диалоговое окно Edit Property/Method
В столбце Name (Имя) отображается наименование объекта, свойства ил метода, в столбце Туре (Тип) — тип объекта (О — объект, М — метод, Р свойство). Столбцы Access и Assign указывают, были ли созданы соответст- вующие методы. Столбец Visibility определяет тип свойства или метода.
УРОК 32
Фундаментальные классы Visual FoxPro Конечно, хорошо самому писать различные классы — есть чем и народ уди вить, и себя показать... Но! Зачем "изобретать велосипед"? Ведь наивно бы ло бы думать, что, допустим, класс командной кнопки, которая осуществля ет единственное действие — закрытие экранной формы — придумали вчера. Нет, конечно. Все эти базовые или фундаментальные классы изобретены давным-давно. Нам же остается их где-то взять и уметь применять в своих приложениях. А где их взять? Подсказываю три возможных варианта. • Купить. • Украсть (карается законом!). • Использовать библиотеки фундаментальных классов, входящих в ком плект поставки Visual FoxPro. Вот третий вариант и обсудим. В Visual FoxPro есть набор библиотек клас сов, которые могут быть использованы в наших приложениях для решения большинства основных задач. Хранится все это "добро" в обычных файлах с расширением vex, а каталог, где все это "лежит", так и называется Foundation Classes (Фундаментальные классы). Какие же такие "хитрые" классы и библиотеки приготовили для нас отцы-основатели нашего Лиса? Ответ на этот вопрос — в табл. 32.1. Таблица 32.1. Фундаментальные классы из комплекта Visual FoxPro Название класса
Название библиотеки
Описание класса
About Dialog
_dialogs.vcx
Включает в приложение стандартное диалоговое окно About
ActiveX Calendar
_datetime.vcx
Позволяет включить в форму календарь
Application Registry
Registry.vcx
Операции, связанные с реестром Win dows
408
Часть //. Объектно-ориентированное программирование Таблица 32.1 (продолжение)
Название класса
Название библиотеки
Array Handler
jjtility.vcx
Операции с массивами, недоступные при использовании стандартных средств
Cancel Button
_miscbtns.vcx
Кнопка Cancel (Отмена), закрывающая экранную форму
Clock
_datetime.vcx
Выводит в экранную форму текущее время
C o n f l i c t Catcher
_dataqwery.vcx
Диалоговое окно, в котором показаны конфликтные значения при редактиро вании данных
Cookies Class
Jntenet.vcx
Используется в качестве FoxISAPI
Cross Tab
_utility.vcx
Используется для создания перекрест ных таблиц
Data E d i t Button
Wizbtns.vcx
Панель навигации по записям таблицы. Кнопки Top, Previous, Next, Bottom, Find, Print, Add, Delete, Edit, Save (Пер вая, Предыдущая, Следующая, Послед няя, Найти, Печать, Добавить, Удалить, Редактировать, Сохранить)
Data Navigation Buttons
_datanav.vcx
Группа кнопок (Top, Previous, Next, Bottom) (Первая, Предыдущая, Сле дующая, Последняя)
Data Session Manager
_app.vcx
Обслуживает обновление данных в эк ранных формах при работе с данными
Data V a l i d a t i o n
_datanav.vcx
Отслеживает конфликты между данными
Data Navigation Object
Jable.vcx
Данный класс обязательно используется в сочетании с элементами управления для перемещения (навигации) по запи сям таблиц
_dbf3html
Jnternet.vcx
Курсор для HTML
D i s t i n c t Values Combo
_dataqwery.vcx
Заполняет поле со списком (ComboBox) уникальными значениями
Error Object
_app.vcx
Стандартный обработчик ошибок
F i e l d Mover
_app.vcx
Диалоговое окно, с помощью которого можно переносить поля из одного спи ска в другой. (Мы видели такую штуку при использовании построителя для Grid)
F i l e Version
_utility.vcx
Считывает ресурс версии файла
Описание класса
Урок
32.
Фундаментальные
классы
Visual
FoxPro
409
Таблица 32.1 (продолжение) Название класса
Название библиотеки
Описание класса
F i l t e r Dialog Box Button
Jable.vcx
Кнопка, которая используется в диало говом окне Filter (Фильтр)
F i l t e r Dialog Box
Jable.vcx
Диалоговое окно Filter (Фильтр)
Find Button
Jable.vcx
Кнопка, используемая окне поиска записи
Find Dialog Box
Jable.vcx
Диалоговое окно, с помощью которого можно отыскать указанный текст
Find Object
Jable.vcx
Данный объект отыскивает указанную запись по заданному условию
Find (Find Next) Buttons
_utility.vcx
Кнопки Find (Найти) и Find Next (Найти следующую)
Font Combobox
Jormat.vcx
Раскрывающийся список с перечнем доступных шрифтов
Font Size Combobox
Jormat.vcx
Раскрывающийся список с перечнем доступных размеров шрифтов
Format Toolbar
Jormat.vcx
в диалоговом
Панель инструментов для форматирова ния текста
FRX-HTML
Jnternet.vcx
Преобразует отчет VFP (с расширением frx) в формат HTML
G e t f i l e and Directory
_controls.vcx
Диалоговое окно для выбора папок и файлов
Goto Dialog Box Button
Jable2.vcx
Кнопка, применяемая в диалоговом окне Goto
Goto Dialog Box
Jable.vcx
Диалоговое окно для перемещения по записям
Graph by Record
_utility.vcx
Используется для построения графиков
Graph Object
_autgraph.vcx
Используется с Graph Wizard (Мастер диаграмм (графиков))
Help Button
jniscbth.vcx
Кнопка, отображающая раздел справки, заданный свойством HelpContextld
Hyperlink Button
Jiyperlink.vcx
Кнопка, запускающая Web-браузер
Hyperlink Image
Jiyperlink.vcx
Изображение, браузер
Hyperlink Label
Jiyperlink.vcx
Надпись, запускающая Web-браузер
запускающее
Web-
410
Часть II. Обьектно-ориентированное программирование Таблица 32.1 (продолжение)
Название класса
Название библиотеки
Описание класса
Item Locator
_dialogs.vcx
Диалоговое окно для поиска файла
I N I Access
Registry.vcx
Осуществляет доступ к системному рее стру Windows для получения информа ции из INI-файла
Keywords Dialog Box
_dialogs.vcx
Диалоговое окно со списком ключевых слов
Launch Button
jnsicbtn.vcx
Кнопка для запуска приложения. Ис пользуется командой RUN
Locate Button
Jable2.vcx
Кнопка для вызова диалогового окна, выполняющего функции, аналогичные команде Locate
Lookup Combobox
_dataquery.vcx
ComboBox, список значений которого заполняется данными из полей
M a i l Merge Object
Mailmerge.vcx
Класс, который использует Mail Merge Wizard (Мастер слияния данных) для формирования документа Word
Messagebox Handler
_dialogs.vcx
Оболочка функции MESSAGEBOX ()
Mover
_movers.vcx
Элемент управления списком для орга низации перемещения данных
MouseOver E f f e c t s
_ui.vcx
Обеспечивает выполнение функций вы деления элемента управления при пе ремещении над ним указателя мыши
Navigator Shortcut Menu
_table2.vcx
Контекстное меню, содержащее коман ды навигации
Navigation Toolbar
_table2.vcx
Панель инструментов для перемещения по записям таблицы
Object State
_app.vcx
Элемент управления, состояние объекта
ODBC R e g i s t r y
Registry.vcx
Извлекает связанную с ODBC информа цию из системного реестра Windows
O f f l i n e Switch
_dataquery.vcx
Набор кнопок, позволяющий переклю чаться между Online- и Offline-данными при работе с удаленными представле ниями
OK Button
_miscbtn,vcx
Кнопка, которая закрывает экранную форму и фиксирует все изменения дан ных
определяющий
Урок 32. Фундаментальные классы Visual FoxPro
411 Таблица 32.1 (продолжение)
Название класса
Название библиотеки
Output Object
_reports.vcx
Этот класс организует взаимодействие с источником данных для отчетов
Output Controls
_reports.vcx
Формирует запросы для ввода опций при выводе отчета
Output Dialog Box
_reports.vcx
Диалоговое окно для ввода опций при выводе отчета
Password Dialog Box
_dialogs.vcx
Диалоговое окно для ввода пароля
Pivot Table
_pivtable.vcx
Используется в Pivot Table Wizard для формирования таблицы Excel
Preview Report
_miscbtn.vcx
Набор кнопок, используемый при пред варительном просмотре отчета
QBF
_dataquery.vcx
Набор кнопок для выполнения запроса
R e g i s t r y Access
Registry, vex
Используется для получения информа ции из системного реестра Windows
Resize Object
_controls.vcx
Данный класс организует изменение размеров объекта при изменении раз меров экранной формы
RTF Controls
_format.vcx
Используется для форматирования тек ста в формате RTF
Run Form Button
_miscbtn.vcx
Кнопка для запуска экранной формы
SCX-HTML
_innternet.vcx
Преобразует файл формата FRX в файл формата HTML
Sendmail Button
_miscbtn.vcx
Используется для отправки почтового сообщения из экранной формы
S h e l l Execute
_environ.vcx
Кнопка для запуска некоторого прило жения из текущего приложения
Shortcut Menu Class
_menu.vcx
Используется при создании контекстных меню
Simple E d i t Buttons
Wizbtns.vcx
Набор кнопок Add, Delete, Edit, Dublicate, Save, Cancel (Добавить, Уда лить, Редактировать, Копировать, Со хранить, Отмена) для редактирования таблиц и видов
Simple Picture Navigation Buttons
_table.vcx
Пиктографические кнопки Next (Сле дующая) и Previous (Предыдущая) для перемещения по записям таблицы или представления данных
Описание класса
412
Часть II. Объектно-ориентированное программирование Таблица 32.1 (продолжение)
Название класса
Название библиотеки
Simple Navigation Buttons
.table, vex-
Обычные кнопки Next (Следующая) и Previous (Предыдущая) для перемеще ния по записям таблицы или представ ления данных
Sort Dialog Box Buttons
Jable2.vcx
Данная кнопка используется в диалого вом окне сортировки
Sort Object
Jable2.vcx
Используется для сортировки данных
Sort Selector
_table2.vcx
Набор кнопок для сортировки данных по возрастанию или убыванию
Sort Mover
_movers.vcx
Используется для автоматической сор тировки данных
Sound Player
jnutimedia.vcx
Используется для загрузки и проигрыва ния звуковых файлов
Splash Screen
_dialogs.vcx
Используется для создания заставки для приложений
SQL Pass Through
_dataquery.vcx
Используется для выполнения операций SQL Path Through
Stop Watch
_datetime.vcx
Секундомер
String Library
_utility.vcx
Удаляет символы возврата каретки и перевода строки из данных строкового типа
Super Mover
_movers.vcx
Элемент управления списком. Имеет кнопки Move, Remove, MoveAII, RemoveAII (Переместить, Удалить, Пере местить все, Удалить все) для переме щения данных
System Toolbar
_app.vcx
Используется в приложениях для установки или удаления системной панели управления
Table Mover
_movers.vcx
Список, который автоматически загру жает таблицы и поля из текущего источ ника данных
Text Preview
Описание класса
Текстовый окон
редактор
для
диалоговых
Thermometer
_controls.vcx
Элемент управления в виде термометра
Trace Aware Timer
_app.vcx
Управляет окном трассировки
Урок 32. Фундаментальные классы Visual FoxPro
413 Таблица 32.1 (окончание)
Название класса
Название библиотеки
Type
_utility.vcx
Извлекает информацию о типе из биб лиотеки типов и формирует текстовый файл
URL Combo
_intemet.vcx
Поле со списком для ввода адреса ин тернет-страницы
URL O p e r a t i o n D i a l o g Box
_internet.vcx
Диалоговое окно для хранения адресов ресурсов Интернет
VCR B u t t o n s
_table.vcx
Группа кнопок для перемещения по записям
VCR P i c t u r e s Navigation Buttons
_table.vcx
Группа пиктографических кнопок для перемещения по записям
Video
_multimedia.vcx
Загрузка и проигрывание видеофайлов
Web Browser C o n t r o l
_webview.vcx
Позволяет включать в экранную форму браузер Internet Explorer
Window
_ui.vcx
Используется для управления окнами
Library
Player
Handler
Описание класса
Просмотрев эту таблицу, ты наверняка с недоумением пожмешь плечами и скажешь: "Ну и что? А я то здесь причем?" А притом, что все эти уже гото вые классы ты можешь использовать при разработке своих приложений. Другой вопрос, как и с помощью чего это сделать? Именно для этого случая разработчики приготовили для нас еще один сюрприз, о котором мы пого ворим на следующем уроке.
УРОК зз
Галерея компонентов (Component Gallery) С помощью галереи компонентов можно группировать такие компоненты, как проекты, классы, формы, отчеты и т. д. Также она предоставляет сред ства для создания новых проектов, форм и т. д. А еще, как я уже говорил, с помощью этой хитрой штуки можно включать в свои приложения фунда ментальные (и не только) классы. Для запуска придется выполнить одно из следующих действий: выбрать команду Component Gallery (Галерея компонентов) из меню Tools (Инструменты) или набрать команду DO (GALLERY) В командном окне. В любом случае галерея появится на экране — рис. 33.1.
Рис. 33.1. Диалоговое окно Component Gallery
Урок 33. Галерея компонентов (Component Gallery)
415
Как видишь, диалоговое окно разбито на две части. Левая, в которой нахо дятся каталоги, называется панель каталогов, а правая, на которой располо жены объекты, — панель объектов. По умолчанию каталоги в галерее компонентов организованы следующим образом — табл. 33.1. Таблица 33.1. Каталоги в галерее компонентов Каталог
Описание
Catalogs
Корневой каталог
VFP Main
Содержит компоненты, используемые другими каталогами
Favorites
В этот каталог мы можем поместить те компонен ты, которые чаще всего используем при работе
Visual FoxPro
Содержит все базовые классы Visual FoxPro, шаб лоны приложений, форм, отчетов и т. д., а также инструменты для разработки приложений
Data
Содержит средства для работы с данными
Foundation Classes
Библиотеки фундаментальных классов
Help
Файлы с разделами справки
Templates
Шаблоны различных мастеров (Wizard)
Tools
Содержит инструменты для разработки приложе ний
My Base Classes
Подклассы основных классов Visual FoxPro
ActiveX
Содержит перечень всех зарегистрированных на компьютере элементов управления ActiveX
World Wide Web
Список адресов Web-страниц, посвященных Visual FoxPro
Multimedia
Файлы мультимедиа (звуковые, видео, изображе ния), которые можно включать в приложения
Samples
Программы учебных приложений
416
Часть II. Объектно-ориентированное программирование
Панель инструментов Component Gallery Панель инструментов содержит следующие к н о п к и — табл. 33.2. Таблица 33.2. Кнопки панели инструментов
Рис. 33.2. Диалоговое окно Open
Урок 33. Галерея компонентов (Component Gallery)
417
Рис. 33.3. Диалоговое окно Component Gallery Options, вкладка Standard
Вкладка Standard (Стандартные) позволяет настроить общие параметры ок на галереи компонентов (рис. 33.3). Опции вкладки Standard (Стандартные) перечислены в табл. 33.3. Таблица 33.3. Опции вкладки Standard Опция
Описание
Группа Global defaults (Общие установки) Enable item renaming (Разрешить переименовывать объект)
Если установлен данный флажок, раз решается переименовывать каталоги и объекты
FFC Builder Lock (Запуск построителя)
При установке данного флажка при перетаскивании объекта на экранную форму будет автоматически запущен соответствующий построитель
Drag and drop to desktop (Перенести и оставить на рабочем столе)
При установке данного флажка объект можно перетащить на рабочий стол. (Правда, работать он там не будет)
Advanced editing enabled (Возможность дополнительного редактирования)
При установке этого флажка в окно свойств объекта будут добавлены до полнительные вкладки (Type, Scripts, Views, Comments) (Тип, Скрипты, Представления, Комментарии)
Часть II. Объектно-ориентированное программирование
418
Таблица 33.3 (окончание) Опция
Описание
Группа Catalog default behavior (Действия каталога по умолчанию) Open file as new view (Открыть файл)
Если установлен этот переключатель, то объект, который может быть либо открыт, либо добавлен при двойном щелчке мыши, будет именно открыт
Add file to current view (Добавить файл)
Если установлен этот переключатель, то объект, который может быть либо открыт, либо добавлен при двойном щелчке мыши, будет именно добавлен
Группа Item default behavior (Действия объекта по умолчанию) Modify item file (Модифицировать файл)
При установке этого переключателя объект будет модифицирован при двойном щелчке
Run item file (Запуск файла)
При установке этого переключателя объект будет запущен на выполнение при двойном щелчке
Рис. 33.4. Диалоговое окно Component Gallery Options, вкладка Catalogs
На вкладке Catalogs (Каталоги) расположен список входящих в состав гале реи компонентов каталогов (рис. 33.4). При желании можно добавить но вый каталог, воспользовавшись кнопкой New (Новый).
Урок 33. Галерея компонентов (Component Gallery)
419
Рис. 33.5. Раскрывающийся список View Type
На панели инструментов галереи компонентов имеется раскрывающийся список View Type (Тип представления) — рис. 33.5 Здесь имеется список значений, управляющих видом отображения данных в окне галереи компонентов. Изменить (см. рис. 33.7), удалить или добавить дополнительные значения можно с помощью вкладки Dynamic Views (Ди намические представления) — рис. 33.6.
Рис. 33.6. Диалоговое окно Component Gallery Options, вкладка Dynamic Views
420
Часть II. Объектно-ориентированное программирование
Рис. 33.7. Диалоговое окно Edit View
Работа с галереей компонентов Сейчас попробуем на практике применить все ранее описанное. В конст рукторе форм создадим обычную форму. Затем, не закрывая окна конструк тора форм, вызовем окно галереи компонентов, в котором откроем каталог Foundation Classes (Фундаментальные классы), а в нем — каталог Buttons (Кнопки). В правом окне галереи компонентов выберем объект OK Button и перетащим его мышью в нашу форму. Теперь откроем подкаталог DateTime (Дата/Время), в правом окне выберем объект Clock (Часы) и нажмем пра вую кнопку мыши. В появившемся контекстном меню выберем команду Add to form (Добавить в форму). Запустим форму на выполнение — рис. 33.8.
Рис. 33.8. Использование компонента из галереи
Видишь, за десять секунд мы сделали форму, которая отображает текущие дату и время, да еще и закрывается при щелчке по кнопке. Удобно, правда? Еще мы узнали, что добавлять объекты можно как используя контекстное меню, так и просто перетаскивая их — галерея компонентов полностью поддерживает метод Drag and Drop (Перенести и оставить). Более того, на основе фундаментальных классов с помощью галереи компо нентов можно создавать новые компоненты для своих приложений. Пом нишь, при изучении таймера мы делали форму-заставку? Так вот, в галерее компонентов уже есть готовый класс экрана-заставки.
Урок 33. Галерея компонентов (Component Gallery)
421
1. Открой подкаталог Dialogs (Диалоги или диалоговые окна) и щелкни правой мышью по объекту Splash Screen. В контекстном меню выбери команду Create Form (Создать форму). 2. После этого откроется диалоговое окно, в котором нужно указать имя новой формы, а затем автоматически запустится конструктор форм с уже готовым шаблоном — рис. 33.9.
Рис. 33.9. Создание новой формы
Использование галереи компонентов для создания приложения С помощью галереи компонентов можно создавать не только компоненты приложений, но и сами приложения. 1. В окне галереи компонентов открой корневой каталог (Catalogs) и дваж ды щелкни по объекту New Application (Новое приложение). 2. Откроется диалоговое окно Enter Project Name (Введите имя проекта) (рис. 33.10). Всего то и остается, что указать имя проекта, и через не сколько секунд запустится построитель проекта (Application Builder).
422
Часть II.
Объектно-ориентированное программирование
Рис. 33.10. Диалоговое окно Enter Project Name
Но это еще не все! Галерея компонентов содержит несколько готовых при ложений, на базе которых можно построить свое собственное. Хранятся они в папке Applications (Приложения) каталога Templates (Шаблоны) (рис. 33.11).
Рис. 33.11. Шаблоны приложений
Заключение Ну вот, подходит к концу наша книга, пора подводить итоги. Пройдя все уроки, ты научился (а мне хотелось бы верить, что это так) создавать сво бодные таблицы и таблицы базы данных, экранные формы, отчеты, слож ные (и не очень) запросы и представления данных, перекрестные таблицы, графики и т. д. В общем, можно сказать, что ты полностью усвоил основ ные навыки работы с Visual FoxPro. Почему основные? Да потому, что эта книга лишь приоткрыла для тебя дверь в мир СУБД, и я думаю, что это бы ла интересная экскурсия... О Visual FoxPro написано немало книг, справочников, учебных пособий, и если ты решишь серьезно заняться программированием, тебе не составит труда найти их. А я напоследок "подарю" тебе список ресурсов Интернет, посвященных FoxPro. • Официальные: http://www.microsoft.com/rus/ — Microsoft в России. http://msdn.microsoft.com/vfoxpro/default.asp — Microsoft Visual FoxPro. • Пресса: www.newsletter.narod.ru/foxtaIk/FoxTalk.htm — "FoxTalk". • Коллективные: www.firststeps.ru — "Первые шаги" — Клементьев В. А., Сергей Платонов, Каев Артем. www.infocity.kiev.ua — "Виртуальный город компьютерной документа ции" — Пинкус Михаил. www.universalthread.com — Michel Fournier, Nick Neklioudov, Evan Delay, Gerald Santerre, Claudio Lassala, MartHn SalHas. • Частные: www.dbrad32.narod.ru — Баянов Дмитрий Александрович. www.wet.narod.ru — Ветчинов Владимир.
424
Заключение
www.Foxpopuli.narod.ru — Горяинов Евгений. www.clickexpIorer.narod.ru — Грицюк Сергей. www.vfpdev.narod.ru — Дроздов Михаил. www.nsvisual.com/fox2 — Жирнов Сергей. www.foxuser.by (nm) (boom).ru — Закиров Орион. www.skc.narod.ru — Коваль Александр. www.urfin.boom.ru — Радченко Виктор Вадимович. www.foxtools.newmail.ru — Сидоров Леонид. www.dushes.hotbox.ru — Смирнов Андрей Валерьевич. www.sumarokov.nm.ru — Сумароков Сергей. www.vfp.narod.ru — Тананаев Дмитрий Александрович. • Форумы: http://talk.mail.ru/forum/fido7.ru.foxpro — Эха по FPD. http://talk.mail.ru/forum/fido7.ru.visual.foxpro — Эха по VFP. http://ljuda_m.chat.ru/foxolb_07_02.rar — Обзор русскоязычных ресурсов FoxPro — Alex Kise. А теперь хочется сказать слова благодарности всем, кто помогал мне при создании этой книги. Огромное СПАСИБО: • моей супруге Елене — за понимание и поддержку в этом нелегком начи нании; • семье Ушаковых, Владимиру и Татьяне — за оказанную техническую по мощь; • Жанне Манойленко — за полуночное редактирование. И, конечно же, огромное спасибо тебе, уважаемый читатель — ведь это не я, это МЫ вместе с тобой написали эту книгу. Успехов тебе и СЧАСТЛИВОГО ПРОГРАММИРОВАНИЯ! Дмитрий Шапорев [email protected]
ПРИЛОЖЕНИЯ
ПРИЛОЖЕНИЕ 1
Настройка параметров конфигурации Visual FoxPro Для настройки параметров, определяющих работу Visual FoxPro, необходимо вызвать диалоговое окно Options (Параметры) посредством команды Options (Параметры/Опции) системного меню Tools (Инструменты) (рис. П1.1).
Рис. П1.1. Вызов окна Options
После выполнения этой команды окно настроек не заставит себя ждать рис. П1.2.
Приложение
428
1
Рис. П1.2. Диалоговое окно Options
Все параметры разделены на соответствующие группы, расположенные на двенадцати вкладках, описание которых приведено в табл. П1.1. Таблица П1.1. Вкладки окна Options Вкладка
Описание
Controls (Элементы управления)
Настройка визуальных классов и объектов OLE
Data (Данные)
Настройка параметров для управления данными
Debug (Отладка)
Настройка параметров трассировки и отладки программ
Field Mapping (Поля)
Определяет тип объекта, который будет создан в форме при переносе на нее полей таблиц из окна Data Environment (Среда окружения), Database Designer (Конструктор базы данных) или проекта
File Locations (Расположение файлов)
Отображает расположение файлов и каталогов
Forms (Формы)
Настройка конструктора экранных форм
General (Основные параметры)
Настройки звука и ввода данных
Projects (Проекты)
Настройка окна проекта
Настройка параметров конфигурации Visual FoxPro
429 Таблица П1.1 (окончание)
Вкладка
Описание
Regional (Региональные параметры)
Настройка формата отображения дат, чисел, денежных единиц и времени
Remote Data (Удаленные данные)
Настройка удаленного доступа к данным
Syntax Coloring (Цвет синтаксиса)
Настройка цвета шрифта
View (Вид)
Настройка отображения на экране строки со стояния, системного времени, системных со общений
Начнем по порядку описание каждой вкладки. С помощью вкладки Controls (Элементы управления) (рис. П1.3) можно до бавлять как библиотеки классов, так и элементы управления ActiveX (мы уже делали это). Для добавления элемента или библиотеки служит кнопка Add (Добавить), для удаления — Remove (Удалить).
Рис. П1.3. Диалоговое окно Options, вкладка Controls
Вкладка Data (Данные) (рис. Ш.4) позволяет настроить определенные па раметры, описание которых приведено в табл. П1.2.
Приложение
430
Рис. П1.4. Диалоговое окно Options, вкладка Data
Таблица П1.2. Параметры вкладки Data Параметр
Описание
Open exclusive (Открывать монопольно)
Это и есть тот самый эксклюзивный доступ, о котором мы говорили ранее. При выборе этой опции таблица будет открыта в монопольном режиме, и никто другой не сможет открыть эту таблицу (имеется в виду работа нескольких пользователей в сети)
Show field names (Отображать имена полей)
При выполнении таких команд,
как
SUM,
DISPLAY, AVERAGE, L I S T , НЭД с т о л б ц а м и б у д у т
отображаться названия соответствующих полей. Эта опция соответствует команде SET HEADING Prompt for code page (Предлагать выбор кодовой страницы)
Определяет, предлагать ли пользователю вы брать кодовую страницу. Например, при попыт ке просмотра таблицы FoxPro for DOS будет предъявлено диалоговое окно Code Page. Со ответствует команде SET CPDIALOG
Ignore deleted records (Игнорировать удаленные записи)
Определяет, каким образом будут обрабаты ваться "удаленные" записи. Дело в том, что команда DELETE не удаляет записи физически, а лишь помечает их определенным образом. Если этот флажок не установлен, то такие записи будут обрабатываться как и все осталь ные. Соответствует команде SET DELETED
1
Настройка параметров конфигурации Visual FoxPro
431 Таблица П1.2 (продолжение)
Параметр
Описание
Rushmore optimization (Оптимизация Rushmore)
Определяет, включен ли метод ускоренного поиска информации, называемый Rushmore. Рекомендуется отключать лишь в особых слу чаях. Соответствует команде SET O P T I M I Z E
Unique records in indexes (Уникальные записи в индексах)
Соответствует команде SET UNIQUE. При уста новке данного флажка индексы будут поддер живать только неповторяющиеся значения ключей, несмотря даже на то, что могут быть записи и с одинаковыми значениями
Collation sequence (Порядок сортировки)
С помощью раскрывающегося списка можно выбрать желаемый порядок сортировки симво лов. Соответствует команде SET COLLATE
Record counter interval (Интервал отсчета записей)
Определяет частоту выдачи сообщений в стро ку состояния о количестве обработанных запи сей при выполнении таких команд, как PACK И RE INDEX. Соответствует команде SET ODOMETR.
Значения могут быть в интервале от 1 до 32 787, но при установке слишком малого ко личества записей может замедлить работу приложения, т. к. потребует более частого об новления экрана Memo block size (Размер мемо-блоков)
Соответствует команде SET BLOCKS IZE и опре деляет длину Memo-блока в байтах
Browse refresh interval (Интервал обновления при просмотре)
Определяет, через какой интервал времени (в секундах) данные в окне Browse будут об новлены в соответствии с физическими данны ми в таблице. Команда SET REFRESH
Table refresh interval (Интервал обновления таблицы)
Определяет, через какой интервал времени (в секундах) данные в любом окне (не только Browse) будут обновлены в соответствии с фи зическими данными в таблице
SET NEAR on (Установить вблизи)
Влияет на действия Лиса при неудачном поис ке записи. Если флажок снят, то при неудач ном поиске указатель остановится в конце файла. При установленном же флажке указа тель остановится на следующей по алфавиту записи относительно той позиции, в которой ожидалось найти искомое значение. Соответ ствует команде SET NEAR
SET EXACT on (Установить точно)
Управляет поиском символьных строк. При установленном флажке искомое значение должно точно совпадать с критерием поиска, т. е. как по длине строки, так и посимвольно. Соответствует команде SET EXACT
Приложение 1
432
Таблица П1.2 (окончание) Параметр
Описание
SET ANSI on (Установить ANSI)
При сравнении двух строк разной длины более короткая дополняется пробелами, чтобы длины сравниваемых строк стали одинаковыми. Если флажок не установлен, строки сравниваются посимвольно до длины более короткой. Коман да SET ANSI
Опции для работы в сети (многопользовательский режим) Automatic file locking (Автоматическая блокировка файлов)
Соответствует команде SET LOCK и устанавли вает режим автоматической блокировки фай лов при совместном доступе
Multiple record locks (Блокировка нескольких записей)
Соответствует команде SET MULTILOCKS и ис пользуется для блокировки и совместной обра ботки сразу нескольких записей
С помощью параметров вкладки Debug (Отладка) (рис. П1.5) настраивается работа отладчика (табл. П1.3).
Рис. П1.5. Диалоговое окно Options, вкладка Debug
Настройка параметров конфигурации Visual FoxPro
433
Таблица П1.3. Параметры вкладки Debug Параметр
Описание
Environment (Среда)
Определяет среду для отладчика. При выборе Debug Frame (Оболочка отладчика) все окна отладчика располагаются внутри окна Visual FoxPro Debugger (Отладчик Visual FoxPro). При выборе FoxPro Frame отдельные окна от ладчика можно отображать в главном окне Visual FoxPro
Display Timer Events (Отображать события таймера)
При отмеченном флажке в процессе отладки будут отображены события таймера
Specify Window (Определить для окна)
Здесь перечислены окна отладчика, для которых можно задать такие параметры, как размер и цвет шрифта и т. д. Все эти параметры перечис лены в нижней части вкладки
Рис. П1.6. Диалоговое окно Options, вкладка Field Mapping
С помощи вкладки Field Mapping (Поля) (рис. П1.6) можно назначить дей ствующие по умолчанию элементы управления в зависимости от типа поля. Для чего это нужно? А вот смотри: раньше тип объекта, связанный с типом поля, был строго фиксирован и представлял собой в большинстве случаев
434
Приложение 1
текстовое поле. Но, допустим, для поля типа Logical удобнее использовать такой элемент управления, как флажок. Теперь мы легко это можем опре делить. Замечу, что началось такое "удобство" с пятой версии Visual FoxPro. Опишем параметры базы данных (Database options) — табл. П1.4. Таблица П1.4. Группа Database options Параметр
Описание
Drag and drop field caption ("Перетащить и оставить" заголовки полей)
При установке этого флажка заголовок поля будет сформирован на основе свойства Caption структуры таблицы и включен при добавлении поля на экранную форму
Copy field comment (Копировать комментарии полей)
Копируется комментарий к данному полю
Copy field input mask (Копировать маску ввода)
Копируется маска ввода для данного поля
Copy field format (Копировать формат поля)
Копируется формат данного поля
Для изменения элемента управления, связанного с каким-либо типом поля, необходимо нажать кнопку Modify (Модификация) и указать в диалоговом окне Modify Field Mapping (Модификация полей) объект базового или поль зовательского класса (рис. П1.7).
Рис. П1.7. Диалоговое окно Modify Field Mapping
Во время своей работы наш трудяга Лис использует огромное количество различных файлов. А как управляться со всем этим хозяйством, где что ис кать? А вот на вкладке File Locations (Размещение файлов) (рис. П1.8) име-
Настройка параметров конфигурации Visual FoxPro
435
ется таблица, которая и используется для определения расположения фай лов и папок (табл. П1.5).
Рис. П1.8. Диалоговое окно Options, вкладка File Locations Таблица П1.5. Файлы для работы Visual FoxPro Имя (по умолчанию)
Тип файла
Назначение файла
ActiveDoc Launcher
Определяет имя и расположение при ложения, вызываемого командой Run Active Doc (Запустить активный доку мент) из меню Tools (Инструменты)
Runactd.prg
Builders
Определяет имя и расположение при ложения построителя (Builder)
Builder.app
Class Browser
Определяет имя и расположение при ложения Class Browser
Browser.app
Component Gallery
Определяет имя и расположение при ложения Component Gallery
Galery.app
Converter
Определяет имя и расположение при ложения, осуществляющего конверта цию форм и отчетов, разработанных в ранних версиях FoxPro в формат данной версии
Converter.app
Приложение 1
436
Таблица П1.5 (продолжение) Тип файла
Назначение файла
Coverage Profiler
Определяет имя и расположение при ложения для статистической обработки созданных приложений
Default Directory
Имя каталога по умолчанию, в котором Visual FoxPro будет размещать про граммные файлы и таблицы
Default Include File
Определяет имя и расположение фай ла, в котором будут заданы различные константы
Documenting Wizard
Определяет имя и расположение при ложения для документирования прило жений и программ
Expression Wizard
Определяет имя и расположение по строителя приложений
HTML Generator
Определяет имя и расположение при ложения, которое используется для со хранения созданного приложения в формате HTML
Help File
Определяет имя и расположение справ ки
Menu Builder
Определяет имя и расположение по строителя меню
Resource File
Определяет имя файла ресурсов. Ресурсный файл FOXUSER.DBF- обыч ная таблица, в которой хранится ин формация об установках редактора, режимах работы, размерах окон и т. д.
Samples Directory
Определяет имя и расположение ката лога с учебными примерами Visual FoxPro
Search Path
Задает каталог, в котором будет про должен поиск файлов, не найденных в текущем каталоге
Spelling Checker
Определяет имя и расположение при ложения для проверки орфографии
Startup Program
Определяет имя и расположение при ложения, которое начинает работать при запуске Visual FoxPro
Имя (по умолчанию) Coverage.арр
Beautify.app
GetbtmJ.app
Vfp6strt.app
Настройка параметров конфигурации Visual FoxPro
437 Таблица П1.5 (окончание)
Тип файла
Назначение файла
Temporary Files
Каталог для создания временных фай лов
Wizards
Определяет имя и расположение масте ров
Имя (по умолчанию)
Вкладка Forms (Формы) (рис. ГЛ.9) используется для настройки конструк тора форм. Ее параметры описаны в табл. Ш.6.
Рис. П1.9. Диалоговое окно Options, вкладка Forms Таблица П1.6. Параметры вкладки Forms Параметр
Описание
Grid lines (Линии сетки)
Отображение линий сетки
Horizontal spacing (Интервал по горизонтали)
Определяет расстояние между горизонталь ными линиями сетки (в пикселах)
Vertical spacing (Интервал по вертикали)
Определяет расстояние между вертикальны ми линиями сетки (в пикселах)
Приложение 1
438
Таблица П1.6 (окончание) Параметр
Описание
Snap to grid (Привязка к сетке)
При перемещении объекта в макете формы он автоматически устанавливается в ближай шую точку пересечений линий сетки
Show position (Показать позицию)
При установленном флажке в строке состоя ния будут отображаться размер и позиция верхнего левого угла объекта
Tab ordering (Порядок табуляции)
Определяет, в каком порядке элементы I управления будут получать фокус при работе формы. Имеется два значения: Interactive (Интерактивно) и By list (По списку). При ус тановленном значении Interactive (рис. П1.10) для определения порядка получения объек тами фокуса необходимо нажать клавишу <Sr»ft> и поочередно щелкать мышью на эле ментах управления. При установке значения By list (рис. Л 1.11) порядок табуляции будет отображен в виде списка
Scale units (Единица измерения)
Выбор единицы измерения для определения размеров объектов. Используются две едини цы: пиксел и фоксел
Maximum design area (Максимальная рабочая область)
Задается максимальная разрешающая спо собность экрана
Template classes (Классы шаблонов)
С помощью данного шаблона можно опреде лить два класса, которые будут использованы как шаблоны для форм и наборов форм
Builder lock (Привязка построителя)
Автоматический запуск построителя встраивании обьекта в форму
Prompt to save changes before running form (Предлагать сохранять изменения при запуске формы)
Если этот флажок снять, то все изменения после редактирования формы будут автома тически сохранены перед ее запуском
при
На вкладке Genera] (Общие уста*говки) (рис. П1.12) устанавливаются параметры общего назначения, такие <ак звук, цветовая палитра и т. д. Т и п звукового сигнала, которыег будет звучать п р и вводе недопустимых данных, задается в области WJirning sound (Предупреждающий сигнал) (табл. П1.7).
Совместимость с ранними версиями определяется установкой флажка dBase compatibility (Совместимость с dBase). Если флажок сброшен, то Visual FoxPro выполняет программы и приложения, написанные в ранних версиях FoxPro (например, FoxPro for DOS). Если же флажок установлен, то коман ды, перечисленные в табл. П1.8, будут выполняться по-другому.
Настройка параметров конфигурации Visual FoxPro
Рис. П1.10. Интерактивное определение порядка табуляции
Рис. П1.11. Определение порядка табуляции по списку
439
Приложение 1
440
Рис. П1.12. Диалоговое окно Options, вкладка General Таблица П1.7. Параметры группы Warning sound Параметр
Описание
Off (Выключен)
Звуковой сигнал отсутствует
Default (По умолчанию)
Частота (512 Гц) и продолжительность (2 с) звукового сигнала установлены по умолчанию
Play (Проиграть)
Проигрывается выбранный файл
Таблица П1.8. Выполнение команд Команда RANGE
ON
OFF
Всегда проверяет диапазон
Проверяет диапазон только при изменении данных
@
GET
@
SAY
При выводе информации на экран происходит прокрутка экрана
Вывод информации прекра щается при достижении пра вого нижнего угла
@
SAY
Функция CHR О вызывает звуковой сигнал
Функция CHR () не вызывает звуковой сигнал
Настройка параметров конфигурации Visual FoxPro
441 Таблица П1.8 (продолжение)
Команда @
SAY
ON
OFF
В предложении PICTURE
В предложении PICTURE
крайняя правая цифра округляется
крайняя правая цифра отсе кается
ACTIVATE SCREEN
При активизации экрана курсор занимает пози цию 0,0
При активизации экрана по зиция курсора не меняется
ACTIVATE WINDOW
При активизации окна кур сор занимает позицию 0,0
При активизации окна пози ция курсора не меняется
APPEND MEMO
Расширение по умолчанию txt
Расширение отсутствует
DECLARE
Создает массив
Рекомендуется применять аналогичную команду DIMENSION
FSIZE
Возвращает размер файла
Возвращает размер поля
GO/GOTO (совместно С SET TALK ON)
Выводит сообщение с номе ром рабочей области и записи
Такое сообщение не выво дится
INKEY()
При нажатии клавиш <Shift> и <Shift>+
При нажатии клавиш <Shift> и <Shift>+
LASTKEY()
Возвращает код последней нажатой клавиши
Рекомендуется использовать
LIKEO
Пробелы в строках удаляют ся перед сравнением
Пробелы не удаляются
MENU И POPUP
Меню размещается в теку щем окне, курсор распола гается на одной из опций списка
Меню размещается в собст венном окне, курсор распо лагается в активном окне
Вложенные операторы
При возвращении на более высокий уровень выполняет
При возвращении на более высокий уровень текущие
ся команда CLEAR GETS
установки GETS остаются
Параметры, передаваемые по ссылке, доступны в вызы ваемой процедуре
Параметры, передаваемые по ссылке, недоступны в вызываемой процедуре
Передаваемые параметры
INKEY()
Приложение 1
442
Таблица П1.8 (продолжение) Команда
ON
OFF
PLAY MACRO
Добавляется неявная ком бинация клавиш
Ничего не добавляется
READ
При нажатии клавиши
Проверка не выполняется
оператором V A L I D
RUN
Перед началом вывода кур сор передвигается на пер вую позицию 24 строки. По сле завершения экран сдви гается на 3 строки вверх
Вывод происходит с текущей позиции курсора. После вы полнения экран сдвигается на 2 строки вверх
SELECT ()
Возвращает наибольший номер неиспользованной рабочей области
Возвращает номер выбран ной рабочей области
SET COLOR TO
Устанавливает цвета окон и меню, определенных поль зователем
Рекомендуется использовать команду COLOR OF SCHEME
SET BORDER
Устанавливает границы окон, меню и полей
SET FIELDS
Определяет список полей, к которым возможен доступ
SET MEMOWIDTH
Определяет ширину символьных выражений и Мемо-полей
SET MESSAGE
Отображает символьное выражение в последней строке экрана
Выражение отображается только при установке SET STATUS ON
SET PRINTER TO
Выходной файл имеет расширение prt
Не имеет расширения
STORE
Не может присвоить значе ния сразу всем элементам массива
Может присвоить значения сразу всем элементам мас сива
SUM
Количество десятичных знаков при выполнении этой команды определяется КОМаНДОЙ SET DECIMALS TO
Количество десятичных зна ков при выполнении этой команды определяется фор матом суммируемого поля
Настройка параметров конфигурации Visual FoxPro
443 Таблица П1.8 (окончание)
Команда
ON
OFF
SYS(2001,"COLOR")
Возвращает значение, уста новленное командой SET COLOR
Возвращает значение цвето вой пары для оператора SET COLOR TO
TRANSFORM
Возвращает строку симво лов из символьного или чи слового выражения
USE
Если указан путь VFP и в команде указано устройст во, то поиск файла произ водится только на указан ном устройстве
Если указан путь VFP и в команде указано устрой ство, то поиск файла произ водится сначала на указан ном устройстве, а потом — по указанному пути
Если установлен флажок Use Visual FoxPro color palette (Использовать па литру Visual FoxPro), то Лис будет использовать собственную цветовую па литру при просмотре растровых изображений. В противном случае будет задействована палитра, используемая при создании изображения. Данный параметр соответствует команде SET PALETTE. Опция Confirm file replacement (Подтверждать замену файла) определяет, будет ли отображаться сообщение перед записью существующего файла. Команда SET SAFETY. Флажок Browse IME Control (Просмотр с помощью IME) устанавливается только при использовании двухбайтовой символьной системы. IME — это Input Method Editor (Редактор метода ввода). А еще на вкладке General (Общие установки) имеются три опции, связан ные с программированием: • Cancel programs on escape (Прекращать работу программ при нажатии клавиши <Esc>). Соответствует команде SET ESCAPE; • Log compilations errors (Отслеживать ошибки при компиляции) — при компиляции файлов информация о возникших ошибках выводится на экран. В то же время вся информация об ошибках сохраняется и в спе циальном файле с расширением err; • При установке флажка SET DEVELOPMENT (Режим разработки) перед запуском откомпилированного файла происходит проверка, не вносились ли в него изменения. Если изменения обнаружены, файл будет переком пилирован. Раскрывающийся список Navigation keys (Клавиши навигации) содержит два элемента: Windows Compatible и MS-DOS Compatible (соответственно,
Приложение 1
444
совместимые с Windows и совместимые с DOS). Выбор значения этого спи ска соответствует команде SET KEYCOMP. С помощью опции Fill new records with current values (Заполнять новые за писи текущими значениями) можно переносить содержимое текущей запи си в новую запись таблицы. Соответствует команде SET CARRY. Если установлен флажок Enter or tab to exit fields (Нажать <Enter> или
Рис. П1.13. Диалоговое окно Options, вкладка Projects
Параметры вкладки Projects (Проекты) (рис. П1.12) связаны с использова нием диспетчера проектов. В области Project double-click action (Действие, выполняемое проектом при двойном щелчке) находятся следующие опции: • Run selected file (Запустить выбранный файл) — при двойном щелчке на имени файла в окне диспетчера проекта указанный файл запускается на выполнение; • Modify selected file (Модифицировать выбранный файл) — при двойном щелчке на имени файла в окне диспетчера проекта указанный файл от крывается для модификации. Например, при щелчке на файле экранной формы эта форма откроется в конструкторе.
Настройка параметров конфигурации Visual FoxPro
445
При установленном флажке Prompt for Wizards (Предлагать мастеров) Лис "поинтересуется", будем ли мы создавать файл вручную или же воспользу емся соответствующим мастером. Установка флажка Display user-defined container icons (Отображать значки, определенные пользователем) позволяет отображать эти самые значки в ок не диспетчера проекта. Далее расположена группа опций Source control options (Параметры управ ления ресурсами) (табл. П1.9). Если установлен пакет Microsoft Visual SourceSafe (VSS), то его название должно быть указано в раскрывающемся списке Active source control provider (Активный провайдер управления ре сурсами). Таблица П1.9. Параметры группы Source control options Параметр
Описание
Automatically add new projects to source control (Автоматически добавлять новые проекты в систему управления исходными данными)
Понятно из названия
Check out files upon modify (Отметить файлы при модификации)
При попытке модифицировать файл автоматически будет вызван Microsoft Visual SourceSafe
Add files to source control upon add (Добавлять файлы в систему управления исходными данными при добавлении в проект)
Происходит автоматическое добавле ние новых файлов проекта в Microsoft Visual SourceSafe
Remove files from source control upon removal from project (Удалять файлы из системы управления ресурсами при уда лении из проекта)
То же самое, что и предыдущий пара метр, только наоборот. При удалении файла из проекта удаляются ссылки на него в Microsoft Visual SourceSafe
Display dialog box for shortcut menu commands (Открывать диалоговое окно из всплывающего меню команд)
При установке этого флажка можно выполнять команды Microsoft Visual SourceSafe из контекстного меню про екта для нескольких файлов
В поле ввода Text generation (Генерация текста) можно задать имя файла, который осуществляет сохранение целостности информации между Microsoft Visual SourceSafe и VFP. В поле ввода Project class (Класс проекта) можно ввести имя класса, кото рый будет использован при создании новых проектов. На вкладке Regional (Региональные) (рис. П1.14) можно задать параметры, отвечающие за форматы дат, времени, валюты и числовых данных. Самым "главным" здесь является флажок Use System Settings (Использовать сие-
Приложение
446
1
темные установки). А знаешь почему? Да потому что при его установке все остальные опции станут недоступными и в работу вступят системные уста новки. Другое дело, когда данный флажок не установлен — табл. ШЛО.
Рис. П1.14. Диалоговое окно Options, вкладка Regional
Таблица П1.10. Параметры вкладки Regional Параметр
Описание
Date Format (Формат даты)
Из данного раскрывающегося списка можно выбрать название наиболее подходящего формата для отображения дат
Date Separator (Разделитель даты)
Изменение символа разделения даты
Century (Столетие)
Влияет на отображение в дате года— либо четырьмя символами, либо двумя
12-Hour, 24-Hour (12 часов, 24 часа)
12- либо 24-часовой формат отображения времени
Seconds (Секунды)
При установке данного флажка отображаются секунды
Currency Format (Формат денежной единицы)
С помощью этого списка можно определить, где будет отображаться символ денежной единицы: перед числом или за ним
Настройка
параметров
конфигурации
Visual
FoxPro
447
Таблица П1.10 (окончание) Параметр
Описание
Currency Symbol (Символ денежной единицы)
Позволяет определить символ денежной еди ницы. Команда SET CURRENCY TO
1000 Separator (Разделитель тысяч)
Здесь задается символ, который отображает ся после каждой третьей цифры слева от де сятичного знака — разделяет тысячи
Decimal Separator (Десятичный разделитель)
Символ для разделения целой и дробной час тей числа
Decimal Digits (Десятичные цифры)
Определяет минимальное количество деся тичных знаков. Диапазон значений от 0 до 18. Команда SET DECIMALS TO
Week Starts on (Неделя начинается с)
Здесь можно указать, с какого дня начинается неделя. Что? Это у нас с понедельника, а у "них" немного по-другому...
First Week of Year (Первая неделя года)
Тут возможны три значения: Contains Jan 1 (Включая 1 января), First 4-Day Week (Первая неделя — 4-дневная) и First Full Week (Первая неделя — полная)
На вкладке Remote Data (Удаленные данные) (рис. П1.15) определяется, каким образом Лис работает с удаленными данными и с представлениями удаленных данных (табл. П1.11). Что такое представление удаленных дан ных? Это любой файл данных, который не является базой данных или таб лицей FoxPro. Таблица П1.11. Параметры вкладки Remote Data Параметр
Описание
Share connection (Общее соединение)
При установке флажка данной опции можно открыть несколько удаленных представлений данных
Fetch memo (Выбрать мемо-поля)
Выборка мемо-полей при удаленном соединении происходит только в том случае, когда пользо ватель активизировал Мемо-поле. Данный фла жок рекомендуется устанавливать для снижения нагрузки сети
Criteria (Критерий)
Используется для управления обновлением SQL. Возможны четыре значения: Key Fields Only (Только ключи), Key and update Fields (Ключи и обновляемые поля), Keys and Modified Fields (Ключи и модифицированные поля), Key and TimeStamp (Ключи и поля меток времени)
448
Приложение 1 Таблица П1.11 (продолжение)
Параметр
Описание
Method (Метод обновления)
При выборе первого варианта SQL Update (Об новление) обновление данных происходит с по мощью SQL-функции update, а при выборе вто рого (SQL Delete + SQL Insert— удаление и вставка) сначала удаляются старые записи, а затем вставляются другие с новыми значениями
Records to fetch at a time (Одновременно выбрать записи)
Данная опция предназначена для ограничения нагрузки на сеть и определяет количество запи сей, возвращаемых от запроса за один раз
Maximum records to fetch (Максимальное число считываемых записей)
Позволяет определить максимальное число записей, возвращаемых запросом за один раз
Use memo for fields >= (Использовать тип memo для полей)
Некоторые удаленные таблицы могут поддержи вать длинные символьные поля. Данная опция позволяет автоматически преобразовывать та кие поля в поля типа Memo
Records to batch update (Число записей для группового обновления)
Здесь определяется число записей, отправляе мых серверу в одной инструкции SQL
Asynchronous execution (Асинхронное выполнение)
При установке асинхронного выполнения твое приложение может не дожидаться, пока пол ностью закончится обработка инструкции SQL, a выполнять в это время другие действия
Display warnings (Отображать предупреждения)
Определяет, нужно ли выводить на экран сооб щения об ошибках, возникающих при обработке инструкции SQL
Batch processing (Пакетная обработка)
Данная опция определяет, каким образом будут считываться несколько результирующих набо ров
Automatic transactions (Автоматическая обработка транзакций)
Определяет, будет ли транзакция SQL обраба тываться средствами Visual FoxPro (автоматиче ски)
Show login (Показывать окно регистрации)
В некоторых случаях при доступе к удаленным данным может потребоваться регистрация. Вот в этом раскрывающемся списке и можно настро ить отображение окна регистрации: Always (Всегда), Never (Никогда), Only When Neces sary (При необходимости)
Connection timeout (Время ожидания соединения)
Указывается интервал времени (в секундах), в течение которого средства соединения будут ожидать распознавание сервером
Настройка параметров конфигурации Visual FoxPro
449 Таблица П1.11 (окончание)
Параметр
Описание
Idle timeout (Время бездействия)
Определяется время (в минутах), в течение ко торого будет поддерживаться соединение, но не будет производиться никаких действий. Если установлено 0 (по умолчанию), то соединение сразу же разрывается
Query timeout (Время ожидания завершения запроса)
Указывается, сколько секунд приложение будет ждать завершения отправленного запроса. Если за указанное время ответ не пришел, будет вы дано сообщение об ошибке
Wait time (Время ожидания)
Время в миллисекундах, через которое Лис проверяет, завершилось или нет выполнение инструкции SQL
Рис. П1.15. Диалоговое окно Options, вкладка Remote Data
С помощью параметров вкладки Syntax Coloring (Раскраска синтаксических структур (рис. П1.16) можно выделять цветом различные типы текста про грамм. 15 3ак. 1002
Приложение 1
450
Рис. П1.16. Диалоговое окно Options, вкладка Syntax Coloring
Те типы текста, которые "поддаются" раскраске, перечислены в раскры вающемся списке Area (Область): • Comments — комментарии; • Keywords — ключевые слова; • Literals — литералы; • Normal — стандартно; • Operators — операторы; • Strings — строки; • Variables — переменные. Для любого типа текста можно выбрать любой стиль шрифта из раскры вающегося списка Font style (Стиль шрифта): • Automatic — автоматически; • Normal — обычный; • Bold — полужирный; • Italic — курсив; • Bold italic — полужирный курсив. Раскрывающиеся списки Foreground (Цвет шрифта) и Background (Цвет фо на) содержат перечень возможных цветов для любого типа текста.
Настройка параметров конфигурации Visual FoxPro
451
Рис. П1.7. Диалоговое окно Options, вкладка View
С помощью вкладки View (Вид) (рис. П1.16) можно указать, что и как будет отображаться в строке состояния (табл. П1.12). Таблица П1.12. Параметры вкладки View Параметр
Описание
Status bar (Строка состояния)
С помощью этой опции можно указать, отобра жать или не отображать в нижней части экрана строку состояния. Если строка состояния отсут ствует, то все системные сообщения будут ото бражаться в служебном окне в правом верхнем углу экрана
Clock (Часы)
При установке этого флажка в строке состояния будет отображаться системное время
Command results (Результаты команд)
При установке этого флажка в строке состояния будут отображаться результаты выполнения команд
System messages (Системные сообщения)
При установке этого флажка можно разрешить или запретить вывод системных сообщений
Recently used project list (Запомнить список последних проектов)
При установке этого флажка в меню File (Файл) будет отображен список последних четырех про ектов
452
Приложение 1 Таблица П1.12 (окончание)
Параметр
Описание
Open last project on startup (Открывать последний проект при запуске)
При запуске Visual FoxPro будет автоматически открыт последний проект
Что еще сказать про настройку нашего Лиса? Наверное, лишь то, что если после установки всех необходимых параметров ты нажмешь кнопку ОК, все твои установки сохранятся только на время текущего сеанса работы. А вот если щелкнуть на кнопке Set As Default (Установить по умолчанию), уста новленные тобой параметры будут действовать вечно, т. е. до последующего их изменения.
ПРИЛОЖЕНИЕ 2
Возможные значения различных параметров Здесь я расскажу о значениях некоторых параметров, которые ты можешь использовать в своей работе с Visual FoxPro и которые значительно облегчат тебе жизнь. А начну я с клавиш ускоренного доступа к командам системного меню — табл. П2.1. Таблица П2.1. "Горячие" клавиши Меню
Команда меню
"Горячие" клавиши
File (Файл)
New (Создать)
Open (Открыть)
Save (Сохранить)
Print (Печать)