Я знаю людей, которые в FoxPro для DOS использовали проект только для генерации исполняемого файла. В Visual FoxPro проект - основа всего.
Нажимайте: File - New, по умолчанию вам сразу будет предложено сделать проект - в появившемся меню уже выбран пункт Project. Если вы выбираете кнопку New File придется задать имя проекта, под которым он будет сохранен и вы получите окно проекта.
Есть еще кнопка предполагающая использование Wizard.
Поговорим о проекте, придерживаясь его страниц...
Я полагаю, вы уже представили какие таблицы базы данных вам будут нужны, набросали их структуры. Теперь выберите в окне проекта вкладыш Data, потом New и ... Вот тут нелишним будет напомнить, что Visual FoxPro имеет базу данных (database) и таблицы (table), которые в прошлом нестрого также называли базами данных. База данных Visual FoxPro содержит данные о таблицах входящих в неё и структуру которых мы, собственно, и создаём. Впрочем, таблицы могут быть и свободными, т.е. не входящие, не включенные и не учтенные в файле базы данных (database). При этом они утрачивают так много полезных свойств, что я стараюсь их не отпускать на свободу без крайней необходимости.
Коды (
Стартовый файл
Приложение должно иметь главный файл, с которого оно будет запускаться и который в проекте выделяется жирным написанием. В принципе, это может быть и форма, но я использую обычный программный модуль с именем sysmenu.prg, который располагаю на странице приложения Code в группе Program. Вообще-то, написав один раз “болванку”, я её просто копирую в директорию нового приложения и присоединяю к проекту, после чего остается лишь подредактировать её сообразно конкретной задаче. Нижеприведенный текст sysmenu.prg также взят из реального приложения.
| _screen.AUTOCENTER =.T. | Позиционирование главного окна, когда его видно, |
| *_screen.Left =1 | задание размеров, заголовка, стиля рамки. |
| *_screen.Top =1 | e=2>Подробнее см. описание переменной _screen |
| *_screen.Width=200 | |
| *_screen.Height=50 | |
| _screen.caption=[Просмотр] | |
| _screen.BorderStyle=1 | |
| _screen.Closable=.F. | |
| _screen.ControlBox=.T. | |
| _screen.MaxButton=.T. | |
| _screen.MinButton=.T. | |
| | |
| **-- Releases all Visual FoxPro toolbars | Этот фрагмент кода скрывает инструментальные линейки. |
| DIMENSION ToolBars[11,2] | Формируется массив зарезервированных имен... |
| ToolBars[1,1] = "FORM DESIGNER" | |
| ToolBars[2,1] = "STANDARD" | |
| ToolBars[3,1] = "LAYOUT" | |
| ToolBars[4,1] = "QUERY" | |
| ToolBars[5,1] = "VIEWD ESIGNER" | |
| ToolBars[6,1] = "COLOR PALETTE" | |
| ToolBars[7,1] = "FORM CONTROLS" | |
| ToolBars[8,1] = "DATABASE DESIGNER" | |
| ToolBars[9,1] = "REPORT DESIGNER" | |
| ToolBars[10,1] = "REPORT CONTROLS" | |
| ToolBars[11,1] = "PRINT PREVIEW" | |
| | |
| FOR i = 1 TO ALEN(ToolBars, 1) | ... и организуется цикл для сокрытия инструментов. |
| ToolBars[i,2] = WVISIBLE(ToolBars[i,1]) | |
| IF ToolBars[i,2] | |
| HIDE WINDOW (ToolBars[i,1]) | |
| ENDIF | |
| ENDFOR | |
| | |
| *~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| set date british | Набор некоторых начальных установок. Можно его и не |
| set escape off | делать, но стоит ли для каждого экрана упоминать, |
| set delete on | что safety должно быть off, а delete on ? |
| set notify on | |
| set brstatus off | |
| set status off | |
| set talk off | |
| set echo off | |
| set step off | |
| set safety off | |
| | |
| *~~~~~~~~~~~~~~~~~~~~~~~~~ | |
| | |
| SET SYSMENU OFF | Отключаем системное меню. Что вместо него? Об этом ниже. |
| on key label F2 do form calk | Здесь же можно определить нужные функциональные клавиши. |
| | |
| do form mainscr | Вызов Главной формы (по секрету - она и есть главное меню). |
| read event | Оператор, без которого формы не задерживаются на экране. |
| | |
| Clear events e=1>&& это включено в форму mainscr | Можно это поставить здесь, а можно и в форме. Наличие обязательно, иначе приложение не выгружается из памяти. Наблюдался случай, когда расположение здесь оказалось неэффективным и работало только в кнопке выхода их формы. В Visual FoxPro команда Quit понижена в должности и далеко не все закрывает и заканчивает. |
| close databases | Закрываем базу данных |
| close all | Закрываем всё. |
| clear all | Очищаем всё. В общем изо всех сил готовимся к выходу. |
| quit | Вот теперь и сам выход. |
Другие коды
Это старые добрые PRG-файлы. Без них не обойтись даже в Visual FoxPro. По большей части это пользовательские процедуры и особо сложные модули расчетов. Процедуры - понятно почему: к ним обращаются из разных методов разных объектов и, естественно, их многократные копии ни к чему. Что касается модулей расчетов, то, во-первых, их легче искать, во-вторых, отлаживать не обращаясь к формам и объектам, в-третьих, больше шансов не удалить случайно вместе с объектом. Врочем, я не настаиваю на самостоятельном существовании расчетов.
Возможен и другой подход, основанный на способности Visual FoxPro из метода одного объекта вызывать метод другого. Например, у вас есть несколько полей ввода при выходе из которых введённая информация обрабатывается по одной формуле. Поместить её в LostFocus каждого объекта, естественно, малограмотно. Можно оформить в виде PRG-файла и в нужных местах ссылаться на него, но не много ли чести для одной формулки? А можно её поместить в практически неиспользуемый метод какого-нибудь объекта. Если итог ввода всей информации- ту же сумму - вы показываете в виде изменяемого заголовка метки (пример для начинающих: thisform.label1.caption=str(summa) ), то расчет можно поместить в метод Click для метки (вызов: thisform.label1.click). Вряд ли кто будет “кликать” по числу суммы, но даже если это и случиться, то просто снова всё что надо сложится. Здесь главное для себя логически обосновать выбор объекта и метода, где будет находиться формула, чтобы при необходимости её можно было бы без труда найти.
Документы
Формы
Главный экран
Вот так выглядит главный экран (он же - главное меню) в моем исполнении. Простая многостраничная форма, в которой заголовки страниц выполняют роль линейки меню, опции расположены на страницах и представляют собой метки (Label), для которых выполняется метод Click. Внешняя привлекательность достигается созданием BMP-картинок и размещением их на страницах.
Рабочий экран
Если структура баз определена и сами они созданы - можете воспользоваться Wizard-ом. Он, задав ряд вопросов, создаст сносную экранную форму и расставит куда надо какие надо кнопки. И всё будет работать. Только весь текст, какой там окажется придется перевести на русский.
Я формы всегда создаю вручную. За то они и получаются такие, как мне надо, а не как прописано в базовом визардовском классе от Microsoft.
Формы располагаются в соответствующем разделе на странице проекта Documents. Нажмите кнопку New и получите заготовку для экрана. Начните с создания окружения Data Environment. Все таблицы, которые вы в него поместите будут открываться при вызове формы соблюдая установленные связи и закрываться при её отмене. Вам лишь останется при написании необходимого кода указать select <нужная область по имени таблицы>.
Создав окружение, возвращайтесь в окно построителя экранной формы и наполняйте её нужными вам объектами.
Что такое объект в Visual FoxPro? Отступая от официального трактования скажу, что это - любая закорючка на поле формы, т.е. даже линия, рамка, текст, не говоря уж о полях ввода, кнопках, сетках (grid). Да и сама форма - тоже объект, если исходить из того, что объект имеет свойства и методы. Разница заключается в том, что одни объекты сложные - они в себе содержат другие объекты и в этом случае называются контейнерами, а другие простые - существуют сами по себе.
Свойства. Это некие качества присущие объекту (чайник горячий, шрифт красный, кнопка скрытая). Свойства объектов в процессе работы могут меняться, например, на время заполнения поля какие-то кнопки могут стать недоступными.
Методы. Это то, что можно делать с объектом. По кирпичу можно стукнуть, по кнопке -“кликнуть” - указать мышью и нажать её клавишу. Программно на объект можно указать переведя на него “фокус” - метод SetFocus.
Объектом является и сама экранная форма, причем, объектом-контейнером и имеет собственные свойства и методы. Как изменить цвет фона, размеры окна и прочее легко разобраться самостоятельно. Я же остановлюсь на взаимодействии форм и борьбе с главным окном Visual FoxPro.
Вы наверняка захотите, чтобы ваше приложение в виде исполняемого файла производило впечатление самостоятельной величины, а не некоего хвоста при Visual FoxPro. Для этого (а кроме того и по эстетическим соображениям) надо избавиться от главного окна. Достаточно в файле config.fpw поместить строку SCREEN=OFF и при загрузке приложения от окна FoxPro не останется и следа, но! - очень может быть, что при этом вы не увидите и своего стартового экрана. Почему? Потому, что по умолчанию все создаваемые экраны ориентированы на появление именно в основном окне Visual FoxPro. Нет окна - нет и приложений? Тогда поступайте не по умолчанию. Обратите внимание на следующие свойства формы и задайте им показанные здесь значения:
| AlwaysOnTop | .T. |
| AutoCenter | .T. |
| ShowTips | .T. (если хотите, чтобы возле элементов управления появлялись флажки с подсказками) |
| ShowWindow | 2 - As Top-Level Form |
| WindowType | 0 - Modeless (немодальное) |
Это я делаю практически для всех форм, и они послушно появляются друг над другом на фоне рабочего стола Windows. Все формы управляются одним READ EVENT, упомянутым в стартовом файле.
Уже после написания этих строк случилась заморочка, которая отняла два рабочих дня на свою ликвидацию. Случай, казалось бы, простейший - просмотровый экран с Grid (сеткой)и кнопками управления. При нажатии кнопки “Поиск” вызывается экран поиска по условию поверх просмотрового. Установки окон - описанные выше. Естественно, после нажатия любой кнопки я заставил фокус возвращаться на Grid - это комфортно, т. к. в сетке данные не только просматривались но и должны были редактироваться, в общем, чтобы лишний раз не щелкать мышью, сетка становилась активной после отработки любой кнопки. Программно в метод Click кнопки я записал следующее:
| do form searchform | вызов экрана поиска |
| thisform.refresh | “освежение” родительской формы |
| thisform.grid1.setfocus | установка фокуса на сетку |
Вероятно, человек более искушенный сразу сообразил бы что к чему, когда дочерняя форма вдруг заупрямилась и категорически отказалась появляться поверх родительской невзирая на какие-то ни было установки. Я же понял в чем дело, только включив Отладчик и проследив построчно выполнение кода. Строка thisform.grid1.setfocus не только переводит фокус, но и активизирует форму, в результате чего ранее вызванная searchform пропадает под родительским окном просмотрового экрана. Более общий вывод - программа не задерживается на строке do form searchform, а выполняет весь набор строк кода принадлежащий данному методу. Я объясняю это тем, что всё приложение управляется единственным READ EVENTS, упомянутым в стартовом файле. Стоило поменять последовательность строк на
| thisform.grid1.setfocus | установка фокуса на сетку |
| do form searchform | вызов экрана поиска |
| thisform.refresh | “освежение” родительской формы |
и все стало как надо. И на какую ерунду порой уходит время!
Есть особые случаи, когда главное окно Visual FoxPro необходимо, например, предварительный просмотр отчета (PREVIEW) возможен только в нём. Тогда применяем такой маневр:
| _Screen.Show |
| report form ... preview |
| _Screen.Hide |
т.е. показываем окно Visual FoxPro, выводим на просмотр отчет, скрываем окно.
При этом я не могу отделаться от мысли, что преодолеваю трудности порожденные головокружением от собственного величия разработчиков Visual FoxPro (Microsoft). Ну действительно, когда мыслями весь в сетях, серверах, ODBC-ях, до отчетов ли тут, которые практически не изменялись с версии 2.6 для DOS. Хорошо хоть к пятой версии с главным окном научились бороться...
Отчеты
Разбираясь со всевозможными казусами и заставляя приложение работать как того хочется мне, а не ему, я пришёл к мысли, что не могу с уверенностью сказать кому принадлежит очередной программный “глюк” - моему непрофессионализму или ошибке разработчиков. Пример - печать отчетов.
Документация и пособия скрупулёзно описывают такие команды как SET DEVICE TO, SET PRINT TO, SET CONSOLE OFF, и прочее, чем я пользовался в версиях DOS. В Visual FoxPro (по крайней мере в моём от 21 августа 1996 г. Официальном.) достаточно иметь строку REPORT FORM <Имя отчета> NOCONSOLE TO PRINT - и всё! Когда я её обрамил (как, я думал, принято) командами SET PRINT ON и SET PRINT OFF приложение по завершении просто не выгружалось из памяти. А использование команды SET PRINT TO приводило к неустранимой протяжке пустой страницы после печати. Это что - ошибка Visual FoxPro? Во всяком случае, нигде в документации не предупреждают, что некоторыми командами пользоваться просто нельзя.
Классы
Одним из достоинств объектно-ориентированного программирования и Visual FoxPro, в частности, объявляется возможность использовать готовые классы и создавать собственные.
Отступая от канонов я бы назвал класс набором объектов и их взаимодействий, т. е. некоторый шаблон, который можно использовать в своем приложении. В сущности, все объекты, которые мы вставляем в приложения есть порождение неких классов присущих Visual FoxPro. И практически понимание класса и его роли в программировании отдельно взятого приложения этим можно ограничить. Почему? Позволю себе некоторые рассуждения на эту тему.
Наиболее отчетливо программирование с использованием классов можно прочувствовать на примере Wizard-ов экранных форм. Существует определенный шаблон (класс), который “Волшебник” использует при построении экрана. Строго говоря, там целая куча всяких мелких классиков состоящих в сложных родственных отношениях, но мы на выходе, в виде готовой формы, получаем конструкцию, которая при попытке что-либо изменить в своем внешнем облике невозмутимо заявляет, что породивший ее класс категорически против какого бы то ни было вмешательства в ее личную жизнь. Кроме того, интерфейс вообще получается англоязычным. Насколько это удобно? Удобно (только не английский для престарелой бухгалтерши!), если вы делаете пару десятков экранов без требований к их разнообразию. Классы - враги разнообразия. Они его органически не переваривают. Как достоинство классов разработчиками превозносится Наследование (“... Обеспечивает автоматическое изменение свойств подклассов при изменении свойств базового класса”. Документация.). Но, во-первых, если подклассы используются в разных приложениях, то изменения вступят в силу очевидно только после перекомпиляции приложений, во-вторых, изменения коснуться всех дочерних форм, а если мне этого не надо?
Мнение программистов с которыми я общался таково, что классы, в том числе и созданные пользователями (а может и только они), хороши для разработки крупных проектов в больших программистских коллективах, а одинокий возделыватель нивы программного обеспечения вполне, и с комфортом!, может использовать нечто в роде простых шаблонов. Ну уж если очень хочется можно и собственный класс сделать, только не забудьте очень тщательно продумать то, что он передаст по наследству - его отпрыскам придется самим приспосабливаться к тем местам, где будут работать. Поясню. Если вы оформите как класс набор кнопок - перемещение по записям, печать, поиск, выход - то для формы, в которой печать не нужна, соответствующая кнопка должна отсутствовать. Поэтому, либо родительский класс кнопок должен быть так устроен, чтобы отпрыск позволял скрыть ненужное без обращения к “папе”, либо не оформляйте набор как класс - просто копируйте его откуда-то где он у вас храниться и дальше делайте с ним, что хотите.
Классы в проекте помещаются на одноименную вкладку. Если вы воспользовались Wizard-ом, он сам накидает в проект всё, что нужно.
Прочие (Other)
Меню - без комментариев. Поскольку существующий Wizard и его продукцию не люблю, то и не делаю.
Категорию текстовых файлов попадает файл конфигурации. Если вы его поместите в проект, пользователю в наборе файлов приложения он уже не будет нужен.
Прочие в прочих. Сюда удобно поместить BMP-картинки, которые вы использовали для фона экранных форм. Они после компиляции также окажутся в исполняемом модуле (отчего он изрядно “пополнеет”). А вот звуковые файлы *.WAV в проект включать нет смысла - они в ЕХЕ-шник не включаются и пользователю передаются в явном виде.