Пособие перекочевало на этот сайт в "пожарном" порядке, поэтому прошу прощения за неаккуратное исполнение. :(

ОГЛАВЛЕНИЕ

Часть 1. С чего начать?

Проект
Наполнение проекта
Базы данных (Data)
Коды (Code)
Документы (Documents)
Классы (Classes)
Прочие (Other)

Часть 2. Мелочи работы

Переносимость между платформами
Распространение приложения
Вопросы и ответы
Чем  заменить наш привычный SAY для экрана?
Какие свойства определяют цвет?
Что определяет размер и выравнивание текста в Grid?
Как избежать выделения всей ячейки (функция «К»)?
Как уменьшить число страниц в форме?
Как создать просматриватель MEMO-полей?
В каком случае нужен набор форм?
Где разместить условие отбора данных для Grid?
Где определять переменные, упоминаемые в свойствах таблицы?
Как остановить форму на экране, если нет меню?
Как вызывать вспомогательные окна?
Как заставить обновляться экран, если прокручиваем элемент управления "Grid"?
Чем отличается внедренный объект от связанного?
Как бороться с главным окном?
Разное
Отчёт (версия 3.0)
Конвертация приложений из 2.6 для DOS в 3.0 для Windows
Проект
Экраны
Как перемещаться между элементами экрана?
Отчеты
Прочее
Спотыкашки версии 5.0 в
Создание меню

Пользовательские функции

Число прописью
Преобразование числа в строку с пробелами
Звук

Часть 3. Последовательность событий

 

        Часть 1. С чего начать?

            Начинать надо с проекта.

Проект

           

Я знаю людей, которые в FoxPro для DOS использовали проект только для генерации исполняемого файла. В Visual FoxPro проект - основа всего.

            Нажимайте: File - New, по умолчанию вам сразу будет предложено сделать проект - в появившемся меню уже выбран пункт Project. Если вы выбираете кнопку New File придется задать имя проекта, под которым он будет сохранен и вы получите окно проекта.

            Есть еще кнопка предполагающая использование Wizard.

            Честно скажу - после написания этих строк впервые решил её попробовать. Оказалось, что с помощью Волшебника проект можно сделать со структурой директорий, в которые потом Visual FoxPro будет разносить программы, базы, отчеты, но это же можно сделать и без волшебника.  Wisard-ы вообще отдельный разговор - вероятно, это хорошая вещь, но пока с их помощью мне не удалось сделать что-нибудь сложнее справочника.

           

Наполнение проекта

            Поговорим о проекте, придерживаясь его страниц...

Базы данных (Data)

            Я полагаю, вы уже представили какие таблицы базы данных вам будут нужны, набросали их структуры. Теперь выберите в окне проекта вкладыш Data, потом New и ... Вот тут нелишним будет напомнить, что Visual FoxPro имеет базу данных (database) и таблицы (table), которые в прошлом нестрого также называли базами данных.  База данных Visual FoxPro содержит данные о таблицах входящих в неё и структуру которых мы, собственно, и создаём. Впрочем, таблицы могут быть и свободными, т.е. не входящие, не включенные и не учтенные в файле базы данных (database).  При этом они утрачивают так много полезных свойств, что я стараюсь их не отпускать на свободу без крайней необходимости. Подробнее см. официальную документацию и её многочисленные пересказы.

 

 

Коды (Code)

Стартовый файл

            Приложение должно иметь главный файл, с которого оно будет запускаться и который в проекте выделяется жирным написанием. В принципе, это может быть и форма, но я использую обычный  программный модуль с именем sysmenu.prg, который  располагаю на странице приложения Code в группе Program. Вообще-то, написав один раз «болванку», я её просто копирую в директорию нового приложения и присоединяю к проекту, после чего остается лишь подредактировать её сообразно конкретной задаче. Нижеприведенный текст sysmenu.prg также взят из реального приложения.

_screen.AUTOCENTER =.T.

Позиционирование главного окна, когда его видно,

*_screen.Left =1

задание размеров, заголовка, стиля рамки.

*_screen.Top =1

Подробнее см. описание переменной _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 && это включено в форму  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). Вряд ли кто будет «кликать» по числу суммы, но даже если это и случиться, то просто снова всё что надо сложится. Здесь главное для себя логически обосновать выбор объекта и метода, где будет находиться формула, чтобы при необходимости её можно было бы без труда найти.

 

Документы (Documents)

Формы

Главный экран

           

Вот так выглядит главный экран (он же - главное меню) в моем исполнении. Простая многостраничная форма, в которой заголовки страниц выполняют роль линейки меню, опции расположены на страницах и представляют собой метки (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? Во всяком случае, нигде в документации не предупреждают, что некоторыми командами пользоваться просто нельзя.

Классы (Classes)

            Одним из достоинств объектно-ориентированного программирования и Visual FoxPro, в частности, объявляется возможность использовать готовые классы и создавать собственные.

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

            Наиболее отчетливо программирование с использованием классов можно прочувствовать на примере Wizard-ов экранных форм. Существует определенный шаблон (класс), который «Волшебник» использует при построении экрана. Строго говоря, там целая куча всяких мелких классиков состоящих в сложных родственных отношениях, но мы на выходе, в виде готовой формы, получаем конструкцию, которая при попытке что-либо изменить в своем внешнем облике невозмутимо заявляет, что породивший ее класс категорически против какого бы то ни было вмешательства в ее личную жизнь. Кроме того, интерфейс вообще получается англоязычным. Насколько это удобно?  Удобно (только не английский для престарелой бухгалтерши!), если вы делаете пару десятков экранов без требований к их разнообразию. Классы - враги разнообразия. Они его органически не переваривают. Как достоинство классов разработчиками превозносится Наследование («... Обеспечивает автоматическое изменение свойств подклассов при изменении свойств базового класса». Документация.). Но, во-первых, если подклассы используются в разных приложениях, то изменения вступят в силу очевидно только после перекомпиляции приложений, во-вторых, изменения коснуться всех дочерних форм, а если мне этого не надо?

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

            Классы в проекте помещаются на одноименную вкладку. Если вы воспользовались Wizard-ом, он сам накидает в проект всё, что нужно.

           

Прочие (Other)

            Меню - без комментариев. Поскольку существующий Wizard  и его продукцию не люблю, то и не делаю.

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

            Прочие в прочих. Сюда удобно поместить BMP-картинки, которые вы использовали для фона экранных форм. Они после компиляции также окажутся в исполняемом модуле (отчего он изрядно «пополнеет»). А вот звуковые файлы *.WAV в проект включать нет смысла - они в ЕХЕ-шник не включаются и пользователю передаются в явном виде.

Часть 2. Мелочи работы

            Не рискну утверждать, что эти «мелочи» типичны для Visual FoxPro в целом. На самом деле многие из подобных заморочек характерны лишь для определенных версий или их альфа-бета-вариантов. Тем не менее считаю необходимым рассказать о том, с чем встретился, и если у вас не возникнет таких проблем, то тем лучше для вас.

Переносимость между платформами

Если вы установили Visual FoxPro 3.0 под Windows 3.11, то при переходе на Windows 95:

1. Некоторые шрифты в формах перестают изменять атрибуты (толщину).

2. Меняется цвет оформления активной строки GRID.

3. Меняется полезная площадь окна (даже при одинаковом разрешении) - самое громоздкое изменение.

4. Русский текст в PRG перестал быть русским. То же происходит при переинсталляции FoxPro в Windows 95. Переинсталляция необходима, ибо из Windows 3.11 FoxPro  наследует что-то 16-битное. Нужна даже не переинсталляция, а при переходе на Windows 95 надо FoxPro  удалить, потом поставить заново.

Распространение приложения

            Версия Visual FoxPro 3.0 позволяет сделать приложение для Windows 3.11 и 95, версия 5.0 - только для 95.

Для самой первой установки надо сделать  дистрибутивный набор дискет вашего приложения. В дальнейшем у заказчика можно будет менять ЕХЕ-шник  и / или, если изменяли структуру какой-либо таблицы, файл самой таблицы *.dbf и файлы базы данных -  *.dbc, *.dct, *.dcx.

Вопросы и ответы

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

            Большинство вопросов возникло по версии 3.0, т.к. освоение Visual FoxPro я начинал именно с неё. При переходе на версию 5.0 при наработанном опыте и лучшем качестве продукта всё пошло гораздо легче и с меньшими проблемами.

Чем  заменить наш привычный SAY для экрана?

            1. Меткой. Её заголовок Caption может отражать любую информацию, представленную в строковом виде. Недостаток - трудно сделать разделение порядков для чисел.

            2. Объект TextBox, для которого свойство ReadOnly=.T..

            В LostFocus того объекта, по которому движемся, записываем ThisForm.Text1.Refresh - для освежения результата. И что замечательно! - работают коды форматирования (например - разделение порядков в числах). Шаблон (999,999,999,999.99) прописывается в InputMask.

Какие свойства определяют цвет?

TextBox

BackColor - цвет фона
ForeColor - цвет букв

Grid

Спокойная ячейка - ячейка, на которой не сосредоточено ничье внимание

            Текст - Column.ForeColor
            Фон - Column.BackColor
            Рамка - не нашёл

Ячейка после Click  - ячейка, на которой кликнули мышью или начали ввод с клавиатуры

            Текст - Text.ForeColor
            Фон - Text.BackColor
            Рамка - не нашёл

Ячейка в фокусе - ячейка, на которую встали Таb или курсором (SetFocus)

            Текст - Text.SelectedForeColor
            Фон - Text.SelectedBackColor
            Рамка - не нашёл

Что определяет размер и выравнивание текста в Grid?

Размер и выравнивание текста в Спокойной ячейке определяется Column.Size|Alig... ,  в ячейках Focus & Grid - Text.Size|Alig...

Как избежать выделения всей ячейки (функция «К»)?

            Версия 3.0. Выделения всей ячейки аналогично функции "К" можно избежать, если Grid.Highlight=.F.В этом случае нельзя задавать перемещение курсора в начало поля командой Keyboard [{Home}], т.к. он и так встает в начало поля.

            Версия 5.0 По умолчанию ячейка не выделяется. Поэтому, чтобы, наоборот, её выделить, в свойство Format  ставим  букву К.

Как уменьшить число страниц в форме?

Версия 3.0. «...Внезапно понадобилось уменьшить число страниц. Изменил  в родительском классе, но форма перестала загружаться - дает ошибку загрузки с посылом на поле возникновения ошибки. Пришлось открыть форму как базу и вручную искать и удалять все упоминания об удаленной странице. Причем, при удалении упоминания Page4  из поля Parent и последующем открытии формы, все записи относящиеся к измененному диапазону исчезли автоматически.»

Версия 5.0. Изменить значение свойства PageCount в PageFrame. Но надо помнить, что исчезнет последняя страница, причем, вместе с содержимым.

Как создать просматриватель MEMO-полей?

В форме. Создать EditBox и кнопку его вызова, в свойство Click которой поместить код: thisform.Поле.Refresh - иначе содержимое поля не будет обновляться и Thisform.Поле.visible=.T.  - при нажатии на кнопку поле становится видимым. Источником данных для поля EditBox должно быть МЕМО-поле соответствующей таблицы.

Отключать поле можно поместив в метод DblClick кнопки следующий код: thisform.Поле_примечаний.visible=.F.

В каком случае нужен набор форм?

Когда нужно работать с несколькими формами создание набора является оптимальным решением. Формы при этом (пока) видны все, но можно ненужные в данный момент сворачивать в иконку. На выходе обязательно указать ThisFormSet.Release, чтобы закрылось действительно всё.

Где разместить условие отбора данных для Grid?

Версия 3.0.

1. Если просто условие поместить в выражение индекса базы данных, то Grid  ведет себя крайне странно - оставляет пробелы в строках, которые не попадают в диапазон.

2. Правильное решение - в свойствах таблицы в курсоре в Filter пишется нужное условие. НО! Потом такой фильтр нельзя отменить, его можно только переопределить, задав в тексте новое значение одной или обоих границ.

Где определять переменные, упоминаемые в свойствах таблицы?

            См. Часть 3 - последовательность выполнения свойств и методов.

            Условие в свойствах окружения идентично предложению SET FILTER, и чтобы его изменить в тексте процедуры (PRG) соответственно задавать Set Filter To “Условие”.

 Как остановить форму на экране, если нет меню?

Из основной программы форма (набор форм) запускается Do form ... noread. Следующей строкой следует READ EVENTS. На кнопке выхода из формы в числе прочего в самом конце присутствует команда CLEAR EVENTS.

Как вызывать вспомогательные окна?

            Если  нужно вызывать вспомогательные окна, то можно сделать их в виде других форм с именами  Form2, Form3 и т.д. и вызывать по функциональной клавише или кнопкой. Тип окна надо задать модальный. При его закрытии выполнятся все операции следующие за вызовом формы.

            Версия 3.0. Если мы хотим задать некие переменные, например,  для поиска, то нельзя задавать имя m.имя_поля, потому что это то имя, которое FoxPro использует сам, работая с полями базы как переменными памяти. Однако, для 5.0 это утверждение несправедливо - там нормально различаются переменные и поля.

            Практика также показала, что тип окна может быть Modeless. В этом случае хорошо работает такая конструкция:

- В родительской программе:

select  той области, в которой будет работать вспомогательное окно

do form «имя формы вспомогательного окна»

read event   - это заставляет вспомогательное окно остаться на экране, если нет read event в стартовом файле - см. Часть 1.

select  той области, в которой  работает родительская программа

Как заставить обновляться экран, если прокручиваем элемент управления "Grid" ?

            В свойство AfterRowColChange записываем обновление экрана ThisForm.Refresh и  

в свойство ScrollEvent - êîä:

            if nDirection=0

              keyboard [{UPARROW}]

              endif

              if nDirection=1

              keyboard [{DNARROW}]

              endif

            Это подменяет нажатие элемента прокрутки перемещением с помощью курсора, на которое реагирует свойство AfterRowColChange.

           

Чем отличается внедренный объект от связанного?

            На примере таблицы Excel. Внедренная таблица прописывается в приложение, позволяет себя редактировать, но не более того. По сути, это некий инструмент, внедренный в приложение.

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

            Из документации по Excel: “Связь и внедрение  это два метода обмена данными между документами Microsoft Excel и документами, созданными в других приложениях. Связь более предпочтительна, если требуется динамическое обновление данных, то есть в тот момент, когда данные изменяются в исходном документе, а внедрение  если надо изменять данные или их формат внутри другого приложения.”

            Между прочим, имеете место конфликт FoxPro  3.0 с EXCEL 7.0 .

Как бороться с главным окном?

            В файле конфигурации CONFIG.vfp добавьте строку SCREEN=OFF -  она сделает главное окно невидимым. Но оно понадобиться, если вы, например, захотите вывести отчет на предварительный просмотр. Тогда в любом месте главное окно можно показать командой _SCREEN.SHOW и после снова скрыть _SCREEN.HIDE.

Разное

            Сохранять промежуточные результаты обязательно!!! Ошибка в базе формы может не пустить в саму форму. Возможно появление "Синтаксическая ошибка" без всякого ее адреса. Такое может быть вызвано неправильным назначением источника данных в сетке или чем-нибудь еще...

В окружении данных есть метод BeforeOpenTableEvent - сюда можно помещать условия открытия таблиц.

В сетке задавать источник данных надо как ALIAS, ибо если задать TABLE, таблица откроется вторично в новой области

Отчёт (версия 3.0)

Подход к отчету.

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

Создание отчетов.

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

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

Конвертация приложений из 2.6 для DOS в 3.0 для Windows

Проект

Конечно, начинать надо с проекта. При попытке открыть его включается конвертор (или конвертатор?). Перед конвертацией из исходной директории надо удалить файлы с расширением SPR и MPR, которые будут распознаны как программные и нужные и, соответственно, включены в проект. Вспомним, что в версии 3.0 они не нужны.

                   

Экраны

            Экран (форма) переносятся в таком виде, в каком были нарисованы. Чтобы придать ей вид подобающий WINDOWS, можно задать следующие свойства:

            BorderStyle =3

            Closable =.T.

            MaxButton = .T.

            MinButton = .T.

            Movable = .T.

            Кнопки, известные в DOS как Невидимые кнопки, в среде WINDOWS преобразуются в набор Command Group. Для сохранения функциональности достаточно заменить его одной командной кнопкой с свойство Click которой перенести то, что в DOS-варианте помещалось в предложении Valid для той же кнопки. Свойство Click заменяет DOS-конструкцию «если кнопка была нажата, то переменная принимает значение 1».

Как перемещаться между элементами экрана?

            Элементарно. ThisForm.ИмяОбъекта.SetFocus. Штучка именуемая _curobj оставлена ,по-моему, для ностальгических воспоминаний.

Отчеты

            Переносятся без проблем с сохранением функциональности и почти сохраняя внешний вид. Конечно, имеет смысл добавить шрифтовой красивости Windows.

Прочее

            Впрочем, я пришёл к убеждению, что конвертировать старые приложения есть смысл в исключительном случае. Гораздо больше функциональности и очарования приобретёт приложение созданное заново в Visual FoxPro, пусть и по старому проверенному алгоритму.

Спотыкашки версии 5.0 в...

            Если их мало, значит я просто через что-то перешагнул, а до чего-то не дошёл...

Создание меню

            В сгенерированном меню строка следующего содержания:

DEFINE PAD _rj70lc349 OF _MSYSMENU PROMPT "Лицевые счета" COLOR SCHEME 3 KEY ALT+Л, "" 

покажет ошибку из-за «ALT+Л» - здесь должна быть латинская буква, т.е. - «ALT+L»

 Пользовательские функции

            Вряд ли разработчик со стажем не имеет функции представления числа прописью, но всё же привожу здесь её и парочку других - а вдруг кому-то пригодится? К тому же они отлажены именно под Visual FoxPro.

Число прописью

* Функция: PROPIS() for WINDOWS    (С) И. Ульман

*  Тип возвpащаемого значения  -  С;    expN = 0.00 - 999999999.99

*  Обpащение  PROPIS(<expN>,0) печать в одну строку

*             PROPIS(<expN>,1) 1 строка двухстрочной печати

*             PROPIS(<expN>,2) 2 строка двухстрочной печати

*  Пример:       ? PROPIS(101.10,0)    && Результат: сто один pуб. 00 коп.

PARAMETERS x, s

PRIVATE kop, num, st, sbst, i, Sum

* падежи

cmln=right(STR(INT(x/1000000)),1)

cmln1=right(STR(INT(x/1000000)),2)

DO CASE

CASE cmln=[0] or (cmln>=[5] and cmln<=[9]) or (cmln1>=[11] and cmln1<=[19])

textmln=[миллионов ]

CASE cmln=[2] or cmln=[3] or cmln=[4]

textmln=[миллиона ]

CASE cmln=[1]

textmln=[миллион ]

EndCASE

ctys=right(STR(INT(x/1000)),1)

ctys1=right(STR(INT(x/1000)),2)

DO CASE

CASE ctys=[0] or (ctys>=[5] and ctys<=[9]) or (ctys1>=[11] and ctys1<=[19])

texttys=[тысяч ]

CASE ctys=[2] or ctys=[3] or ctys=[4]

texttys=[тысячи ]

CASE ctys=[1]

texttys=[тысяча ]

EndCASE

ckop=right(STR(100*(x-INT(x))),1)

ckop1=right(STR(100*(x-INT(x))),2)

DO CASE

CASE ckop=[0] or (ckop>=[5] and ckop<=[9]) or (ckop1>=[11] and ckop1<=[19])

textkop=[ копеек]

CASE ckop=[2] or ckop=[3] or ckop=[4]

textkop=[ копейки]

CASE ckop=[1]

textkop=[ копейка]

EndCASE

crub=right(STR(INT(x)),1)

crub1=right(STR(INT(x)),2)

DO CASE

CASE crub=[0] or (crub>=[5] and crub<=[9]) or (crub1>=[11] and crub1<=[19])

textrub=[рублей ]

CASE crub=[2] or crub=[3] or crub=[4]

textrub=[рубля ]

CASE crub=[1]

textrub=[рубль ]

EndCASE

kop= SUBSTR(STR(100+100*(x-INT(x)),3),2,2)+textkop

x= ROUND(INT(x),0)

IF x= 0

STORE 'ноль ' TO Sum

ELSE

st= SUBSTR(STR(1000000000+x,10),2,9)

STORE ' ' TO Sum

i= 1

DO WHILE i <= 3

sbst= SUBSTR(st,3*i-2,3)

IF sbst= '000'

i= i+1

LOOP

ENDIF

num= VAL(SUBSTR(sbst,1,1))

IF num # 0

STORE Sum+_100_900(num)+' ' TO Sum

ENDIF

num= VAL(SUBSTR(sbst,2,2))

IF num>=10 .AND. num <=19

STORE Sum+_10_19(num)+' ' TO Sum

ELSE

num= VAL(SUBSTR(sbst,2,1))

IF num # 0

STORE Sum+_20_90(num)+' ' TO Sum

ENDIF

num= VAL(SUBSTR(sbst,3,1))

IF num # 0

IF num= 1 .AND. i= 2

STORE Sum+'одна ' TO Sum

ELSE

IF num= 2 .AND. i= 2

STORE Sum+'две ' TO Sum

ELSE

STORE Sum+_1_9(num)+' ' TO Sum

ENDIF

ENDIF

ENDIF

ENDIF

IF i= 1

STORE Sum+textmln TO Sum

ENDIF

IF i= 2

STORE Sum+texttys TO Sum

ENDIF

i= i+1

ENDDO

ENDIF

STORE LTRIM(Sum+textrub+kop) TO Sum

Sum=upper(left(sum,1))+right(sum,len(sum)-1)

DO CASE

CASE s=0

RETURN Sum

CASE s=1

RETURN IIF(at([тысяч],sum,1)#0,left(sum,at([тысяч],sum,1)+5),sum)

CASE s=2

RETURN IIF(at([тысяч],sum,1)#0,right(sum,len(sum)-at([тысяч],sum,1)-5),[ ])

EndCASE

FUNCTION _1_9

PARAMETER N

DO CASE

            CASE N=1

            RETURN [один]

            CASE N=2

            RETURN [два]

            CASE N=3

            RETURN [тpи]

            CASE N=4

            RETURN [четыpе]

            CASE N=5

            RETURN [пять]

            CASE N=6

            RETURN [шесть]

            CASE N=7

            RETURN [семь]

            CASE N=8

            RETURN [восемь]

            CASE N=9

            RETURN [девять]

ENDCASE

FUNCTION _10_19

PARAMETER N

DO CASE

            CASE N=10

            RETURN [десять]

            CASE N=11

            RETURN [одиннадцать]

            CASE N=12

            RETURN [двенадцать]

            CASE N=13

            RETURN [тpинадцать]

            CASE N=14

            RETURN [четыpнадцать]

            CASE N=15

            RETURN [пятнадцать]

            CASE N=16

            RETURN [шестнадцать]

            CASE N=17

            RETURN [семнадцать]

            CASE N=18

            RETURN [восемнадцать]

            CASE N=19

            RETURN [девятнадцать]

ENDCASE

FUNCTION _20_90

PARAMETER N

DO CASE

            CASE N=2

            RETURN [двадцать]

            CASE N=3

            RETURN [тpидцать]

            CASE N=4

            RETURN [соpок]

            CASE N=5

            RETURN [пятьдесят]

            CASE N=6

            RETURN [шестьдесят]

            CASE N=7

            RETURN [семьдесят]

            CASE N=8

            RETURN [восемьдесят]

            CASE N=9

            RETURN [девяносто]

ENDCASE

FUNCTION _100_900

PARAMETER N

DO CASE

      CASE N=1

            RETURN [сто]

            CASE N=2

            RETURN [двести]

            CASE N=3

            RETURN [тpиста]

            CASE N=4

            RETURN [четыpеста]

            CASE N=5

            RETURN [пятьсот]

            CASE N=6

            RETURN [шестьсот]

            CASE N=7

            RETURN [семьсот]

            CASE N=8

            RETURN [восемьсот]

            CASE N=9

            RETURN [девятьсот]

ENDCASE

Преобразование числа в строку с пробелами

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

FUNCTION Probel

*******************************

* Пользовательская функция: Преобразование числа в строку с пробелами

* (С) 1993 Игорь Ульман

* Обращение: PROBEL(<expN1>,expN2,expN3),

*            где expN1 - число, expN2 - размер поля вывода, expN3 - 1-результат с десятыми, 0-целое число

* Возвращает строку с разделительными пробелами

* !!!!!!!! Десятичные знаки возвращает с точностью ТОЛЬКО до сотых!

PARAMETERS n,size,r

* целая часть

cel=alltrim(str(int(n)))

if r=1

* дробная часть

drob=alltrim(substr(str(n-int(n),4,2),3,2))

endif

* длина целой части

dlina=len(alltrim(str(int(n))))

* количество пробелов

prob=int(dlina/3)

* длина неполного начала строки

lhome=dlina-prob*3

if lhome#0

* неполное начало строки

home=left(cel,lhome)

hod=0

else

home=left(cel,3)

hod=1

endif

string=alltrim(home)  && начальная строка

for prohod=hod to prob

string=string+[ ]+substr(cel,lhome+prohod*3+1,3)

endfor

If r=1

StringExit=alltrim(string)+[.]+drob

Else

StringExit=alltrim(string)

Endif

RETURN space(size-len(StringExit))+StringExit

Звук

            Это исключительно Visual FoxPro-шная функция. Своим рождением она обязана, во-первых, тому, что  Visual FoxPro работает со звуковыми файлами и, во-вторых, моей лени писать каждый раз самостоятельный вызов звукового файла. А так достаточно указать do sound with имя.wav .

Procedure SOUND

Parameter soundF

if file(&SoundF)

SET BELL TO &SoundF, 0

?? CHR(7)

SET BELL TO

endif

 

Часть 3. Последовательность событий.

            Знание последовательности выполняемых событий трудно переоценить, ибо зачастую необъяснимые ошибки работы приложения бывают связаны с тем, что программный код в событиях выполняется не в той последовательности в какой хотелось бы разработчику, а в той какую задаёт порядок самих событий. Например, в нижеприведенном списке легко увидеть, что сначала инициализируется страница в объекте PageFrame и только потом сам PageFrame. Что, казалось бы, совершенно не логично, но на самом деле последовательность событий подчиняется правилу «от частного к общему».

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

Кстати, ничего подобного почему-то нет в официальной документации. Видимо сочли ненужным...  

            Экранная форма «Thisform» содержит PageFrame с четырьмя страницами. Объекты расположены как на страницах, так и на основном поле формы. За описанием событий отсылаю к документации.

screen.Paint()

screen.Paint()

Form.LOAD

Thisform.Load()

screen.Paint()

screen.Paint()

Dataenvironment.INIT

Thisform.dataenvironment.cursor1.Init()

Thisform.dataenvironment.cursor2.Init()

Thisform.dataenvironment.cursor3.Init()

В окружении формы открыто восемь таблиц, а инициализация окружения происходит после таблиц - «от частного к общему»!

 
Thisform.dataenvironment.cursor5.Init()

Thisform.dataenvironment.cursor6.Init()

Thisform.dataenvironment.cursor4.Init()

Thisform.dataenvironment.cursor7.Init()

Thisform.dataenvironment.cursor8.Init()

Thisform.dataenvironment.Init()

Содержимое Page1.INIT

Кнопки и сетка на одной странице обрабатываются согласно порядку объектов на этой странице.

 
Thisform.pageframe1.Page1.text1.Init()

Thisform.pageframe1.Page1.источник.Init()

Thisform.pageframe1.Page1.label1.Init()

Thisform.pageframe1.Page1.Кнопка «Искать».Init()

Thisform.pageframe1.Page1.grid1.column1.header1.Init()

Thisform.pageframe1.Page1.grid1.column1.text1.Init()

Thisform.pageframe1.Page1.grid1.column1.Init()

Thisform.pageframe1.Page1.grid1.column2.header1.Init()

Thisform.pageframe1.Page1.grid1.column2.text1.Init()

Thisform.pageframe1.Page1.grid1.column2.Init()

Thisform.pageframe1.Page1.grid1.column3.header1.Init()

Thisform.pageframe1.Page1.grid1.column3.text1.Init()

Thisform.pageframe1.Page1.grid1.column3.Init()

Thisform.pageframe1.Page1.grid1.column4.header1.Init()

Thisform.pageframe1.Page1.grid1.column4.text1.Init()

Thisform.pageframe1.Page1.grid1.column4.Init()

Thisform.pageframe1.Page1.grid1.column5.header1.Init()

Thisform.pageframe1.Page1.grid1.column5.text1.Init()

Thisform.pageframe1.Page1.grid1.column5.Init()

Thisform.pageframe1.Page1.grid1.column7.header1.Init()

Thisform.pageframe1.Page1.grid1.column7.text1.Init()

Thisform.pageframe1.Page1.grid1.column7.Init()

Thisform.pageframe1.Page1.grid1.Init()

Thisform.pageframe1.Page1.command1.Init()

Thisform.pageframe1.Page1.Кнопка «Добавить».Init()

Thisform.pageframe1.Page1.Init()

Содержимое Page2.INIT

Thisform.pageframe1.Page2.Кнопка «Автомобиль».Init()

Thisform.pageframe1.Page2.list1.Init()

Thisform.pageframe1.Page2.ввод.Init()

Thisform.pageframe1.Page2.grid1.column1.header1.Init()

Thisform.pageframe1.Page2.grid1.column1.text1.Init()

Thisform.pageframe1.Page2.grid1.column1.Init()

Thisform.pageframe1.Page2.grid1.column2.header1.Init()

Thisform.pageframe1.Page2.grid1.column2.text1.Init()

Thisform.pageframe1.Page2.grid1.column2.Init()

Thisform.pageframe1.Page2.grid1.column3.header1.Init()

Thisform.pageframe1.Page2.grid1.column3.text1.Init()

Thisform.pageframe1.Page2.grid1.column3.Init()

Thisform.pageframe1.Page2.grid1.Init()

Thisform.pageframe1.Page2.text1.Init()

Thisform.pageframe1.Page2.Кнопка «Искать».Init()

Thisform.pageframe1.Page2.Init()

Содержимое Page3.INIT

Thisform.pageframe1.Page3.lblсумма3.Init()

Thisform.pageframe1.Page3.txtsumma.Init()

Thisform.pageframe1.Page3.chkvarnds53.Init()

Thisform.pageframe1.Page3.приходникразбитый.Init()

Thisform.pageframe1.Page3.новыйсчет.Init()

Thisform.pageframe1.Page3.печать.Init()

Thisform.pageframe1.Page3.выход.Init()

Thisform.pageframe1.Page3.калькулятор.Init()

Thisform.pageframe1.Page3.optiongroup1.услуги.Init()

Thisform.pageframe1.Page3.optiongroup1.штрафы.Init()

Thisform.pageframe1.Page3.optiongroup1.товар.Init()

Thisform.pageframe1.Page3.optiongroup1.посредничество.Init()

Thisform.pageframe1.Page3.optiongroup1.Init()

Thisform.pageframe1.Page3.optiongroup2.наличные.Init()

Thisform.pageframe1.Page3.optiongroup2.безналичные.Init()

Thisform.pageframe1.Page3.optiongroup2.Init()

Thisform.pageframe1.Page3.label1.Init()

Thisform.pageframe1.Page3.text1.Init()

Thisform.pageframe1.Page3.приходныйодин.Init()

Thisform.pageframe1.Page3.label2.Init()

Thisform.pageframe1.Page3.text2.Init()

Thisform.pageframe1.Page3.label4.Init()

Thisform.pageframe1.Page3.Init()

Содержимое Page4.INIT

Thisform.pageframe1.Page4.strana.Init()

Thisform.pageframe1.Page4.station.Init()

Thisform.pageframe1.Page4.km.Init()

Thisform.pageframe1.Page4.id_sostav.Init()

Thisform.pageframe1.Page4.label7.Init()

Thisform.pageframe1.Page4.label8.Init()

Thisform.pageframe1.Page4.label1.Init()

Thisform.pageframe1.Page4.label2.Init()

Thisform.pageframe1.Page4.label3.Init()

Thisform.pageframe1.Page4.label4.Init()

Thisform.pageframe1.Page4.label5.Init()

Thisform.pageframe1.Page4.label6.Init()

Thisform.pageframe1.Page4.тарифндс.Init()

Thisform.pageframe1.Page4.тариф.Init()

Thisform.pageframe1.Page4.сумма_авто.Init()

Thisform.pageframe1.Page4.сумма_авто_безндс.Init()

Thisform.pageframe1.Page4.сумма_ох.Init()

Thisform.pageframe1.Page4.сумма_ох_безндс.Init()

Thisform.pageframe1.Page4.сумма_полностью.Init()

Thisform.pageframe1.Page4.сумма_полностью_безндс.Init()

Thisform.pageframe1.Page4.label9.Init()

Thisform.pageframe1.Page4.чистый_тариф.Init()

Thisform.pageframe1.Page4.чистый_тариф_безндс.Init()

Thisform.pageframe1.Page4.text9.Init()

Thisform.pageframe1.Page4.label10.Init()

Thisform.pageframe1.Page4.text10.Init()

Thisform.pageframe1.Page4.label11.Init()

Thisform.pageframe1.Page4.text3.Init()

Thisform.pageframe1.Page4.text4.Init()

Thisform.pageframe1.Page4.label12.Init()

Thisform.pageframe1.Page4.label13.Init()

Thisform.pageframe1.Page4.обновить.Init()

Thisform.pageframe1.Page4.text1.Init()

Thisform.pageframe1.Page4.label14.Init()

Thisform.pageframe1.Page4.text2.Init()

Thisform.pageframe1.Page4.label15.Init()

Thisform.pageframe1.Page4.shape1.Init()

Thisform.pageframe1.Page4.shape2.Init()

Thisform.pageframe1.Page4.shape3.Init()

Thisform.pageframe1.Page4.shape4.Init()

Thisform.pageframe1.Page4.shape5.Init()

Thisform.pageframe1.Page4.shape6.Init()

Thisform.pageframe1.Page4.shape7.Init()

Thisform.pageframe1.Page4.shape8.Init()

Thisform.pageframe1.Page4.Init()

Thisform.pageframe1.Init()

Содержимое PageFrame1.INIT

Thisform.lblномер_сч2.Init()

Thisform.lblдата_сче4.Init()

Thisform.txtbill43.Init()

Thisform.txtdate44.Init()

Thisform.txtpayer.Init()

«Отказ», «новая» и прочее - это названия управляющих кнопок, занесенные в проект именно в таком написании.

 
Thisform.txtwork.Init()

Thisform.отказ.Init()

Thisform.новая.Init()

Thisform.предыдущая.Init()

Thisform.следующая.Init()

Thisform.станция.Init()

Thisform.Кнопка «Автомобиль».Init()

Thisform.Init()

Activate-When-GotFocus-LostFocus - фрагмент содержит то, что связано с этими событиями

Thisform.pageframe1.Page1.Activate()

Thisform.Activate()

Thisform.следующая.When()

Thisform.GotFocus()

Thisform.следующая.GotFocus()

Thisform.pageframe1.Page1.grid1.When()

Thisform.следующая.LostFocus()

Thisform.pageframe1.Page1.grid1.column1.text1.When()

Thisform.pageframe1.Page1.grid1.column1.text1.GotFocus()

Thisform.pageframe1.Page1.grid1.column1.text1.Message()

Прочие

Thisform.Paint()

Thisform.pageframe1.Page1.grid1.AfterRowColChange(1)

Thisform.Paint()

Thisform.pageframe1.Page1.grid1.column1.text1.Click()

Thisform.pageframe1.Page1.grid1.Valid()

Thisform.pageframe1.Page1.command1.When()

Thisform.pageframe1.Page1.grid1.BeforeRowColChange(1)

Thisform.pageframe1.Page1.grid1.column1.text1.RangeLow()

Thisform.pageframe1.Page1.grid1.column1.text1.RangeHigh()

Thisform.pageframe1.Page1.grid1.column1.text1.Valid()

Thisform.pageframe1.Page1.grid1.column1.text1.LostFocus()

Thisform.Paint()

Thisform.pageframe1.Page1.command1.GotFocus()

Thisform.Paint()

Нажатие на кнопку «Ввод» для Form.PageFrame.Page1

Thisform.pageframe1.Page1.command1.Click()

Thisform.Paint()

Thisform.pageframe1.Page1.Deactivate()

Thisform.pageframe1.Page1.text1.UIEnable(.F.)

Thisform.pageframe1.Page1.источник.UIEnable(.F.)

Thisform.pageframe1.Page1.label1.UIEnable(.F.)

Thisform.pageframe1.Page1.Кнопка «Искать».UIEnable(.F.)

Thisform.pageframe1.Page1.grid1.UIEnable(.F.)

Thisform.pageframe1.Page1.command1.UIEnable(.F.)

Thisform.pageframe1.Page1.Кнопка «Добавить».UIEnable(.F.)

Код кнопки «Ввод» заканчивается активизацией Page2 и передачей управления на неё

Thisform.pageframe1.Page2.Activate()

Thisform.pageframe1.Page2.Кнопка «Автомобиль».UIEnable(.T.)

Thisform.pageframe1.Page2.list1.UIEnable(.T.)

Thisform.pageframe1.Page2.ввод.UIEnable(.T.)

Thisform.pageframe1.Page2.grid1.UIEnable(.T.)

Thisform.pageframe1.Page2.text1.UIEnable(.T.)

Thisform.pageframe1.Page2.Кнопка «Искать».UIEnable(.T.)

Thisform.pageframe1.Page1.command1.Valid()

Thisform.pageframe1.Page1.command1.When()

Thisform.Paint()

Thisform.Paint()

Thisform.следующая.When()

Thisform.GotFocus()

Thisform.следующая.GotFocus()

Thisform.Paint()

Thisform.отказ.When()

Thisform.следующая.LostFocus()

Thisform.отказ.GotFocus()

Thisform.Paint()

Нажатие на кнопку «Отказ» -  выход из формы

Thisform.отказ.Click()

Thisform.отказ.Valid()

Form.DESTROY

Thisform.Destroy()

Thisform.Кнопка «Автомобиль».Destroy()

Thisform.станция.Destroy()

Thisform.следующая.Destroy()

Thisform.предыдущая.Destroy()

Thisform.новая.Destroy()

Thisform.отказ.Destroy()

Thisform.txtwork.Destroy()

Thisform.txtpayer.Destroy()

Thisform.txtdate44.Destroy()

Thisform.txtbill43.Destroy()

Thisform.lblдата_сче4.Destroy()

Thisform.lblномер_сч2.Destroy()

Form.pageframe1.Destroy()

Thisform.pageframe1.Page4.Destroy()

Thisform.pageframe1.Page4.shape8.Destroy()

Thisform.pageframe1.Page4.shape7.Destroy()

Thisform.pageframe1.Page4.shape6.Destroy()

Thisform.pageframe1.Page4.shape5.Destroy()

Thisform.pageframe1.Page4.shape4.Destroy()

Thisform.pageframe1.Page4.shape3.Destroy()

Thisform.pageframe1.Page4.shape2.Destroy()

Thisform.pageframe1.Page4.shape1.Destroy()

Thisform.pageframe1.Page4.label15.Destroy()

Thisform.pageframe1.Page4.text2.Destroy()

Thisform.pageframe1.Page4.label14.Destroy()

Thisform.pageframe1.Page4.text1.Destroy()

Thisform.pageframe1.Page4.обновить.Destroy()

Thisform.pageframe1.Page4.label13.Destroy()

Thisform.pageframe1.Page4.label12.Destroy()

Thisform.pageframe1.Page4.text4.Destroy()

Thisform.pageframe1.Page4.text3.Destroy()

Thisform.pageframe1.Page4.label11.Destroy()

Thisform.pageframe1.Page4.text10.Destroy()

Thisform.pageframe1.Page4.label10.Destroy()

Thisform.pageframe1.Page4.text9.Destroy()

Thisform.pageframe1.Page4.label9.Destroy()

Thisform.pageframe1.Page4.сумма_полностью_безндс.Destroy()

Thisform.pageframe1.Page4.сумма_полностью.Destroy()

Thisform.pageframe1.Page4.сумма_ох_безндс.Destroy()

Thisform.pageframe1.Page4.сумма_ох.Destroy()

Thisform.pageframe1.Page4.сумма_авто_безндс.Destroy()

Thisform.pageframe1.Page4.сумма_авто.Destroy()

Thisform.pageframe1.Page4.тариф.Destroy()

Thisform.pageframe1.Page4.тарифндс.Destroy()

Thisform.pageframe1.Page4.label6.Destroy()

Thisform.pageframe1.Page4.label5.Destroy()

Thisform.pageframe1.Page4.label4.Destroy()

Thisform.pageframe1.Page4.label3.Destroy()

Thisform.pageframe1.Page4.label2.Destroy()

Thisform.pageframe1.Page4.label1.Destroy()

Thisform.pageframe1.Page4.label8.Destroy()

Thisform.pageframe1.Page4.label7.Destroy()

Thisform.pageframe1.Page4.id_sostav.Destroy()

Thisform.pageframe1.Page4.km.Destroy()

Thisform.pageframe1.Page4.station.Destroy()

Thisform.pageframe1.Page4.strana.Destroy()

Thisform.pageframe1.Page3.Destroy()

Thisform.pageframe1.Page3.label4.Destroy()

Thisform.pageframe1.Page3.text2.Destroy()

Thisform.pageframe1.Page3.label2.Destroy()

Thisform.pageframe1.Page3.приходныйодин.Destroy()

Thisform.pageframe1.Page3.text1.Destroy()

Thisform.pageframe1.Page3.label1.Destroy()

Thisform.pageframe1.Page3.optiongroup2.Destroy()

Thisform.pageframe1.Page3.optiongroup2.безналичные.Destroy()

Thisform.pageframe1.Page3.optiongroup2.наличные.Destroy()

Thisform.pageframe1.Page3.optiongroup1.Destroy()

Thisform.pageframe1.Page3.optiongroup1.посредничество.Destroy()

Thisform.pageframe1.Page3.optiongroup1.товар.Destroy()

Thisform.pageframe1.Page3.optiongroup1.штрафы.Destroy()

Thisform.pageframe1.Page3.optiongroup1.услуги.Destroy()

Thisform.pageframe1.Page3.калькулятор.Destroy()

Thisform.pageframe1.Page3.выход.Destroy()

Thisform.pageframe1.Page3.печать.Destroy()

Thisform.pageframe1.Page3.новыйсчет.Destroy()

Thisform.pageframe1.Page3.приходникразбитый.Destroy()

Thisform.pageframe1.Page3.chkvarnds53.Destroy()

Thisform.pageframe1.Page3.txtsumma.Destroy()

Thisform.pageframe1.Page3.lblсумма3.Destroy()

Thisform.pageframe1.Page2.Destroy()

Thisform.pageframe1.Page2.Кнопка «Искать».Destroy()

Thisform.pageframe1.Page2.text1.Destroy()

Thisform.pageframe1.Page2.grid1.Destroy()

Thisform.pageframe1.Page2.grid1.column3.Destroy()

Thisform.pageframe1.Page2.grid1.column3.text1.Destroy()

Thisform.pageframe1.Page2.grid1.column3.header1.Destroy()

Thisform.pageframe1.Page2.grid1.column2.Destroy()

Thisform.pageframe1.Page2.grid1.column2.text1.Destroy()

Thisform.pageframe1.Page2.grid1.column2.header1.Destroy()

Thisform.pageframe1.Page2.grid1.column1.Destroy()

Thisform.pageframe1.Page2.grid1.column1.text1.Destroy()

Thisform.pageframe1.Page2.grid1.column1.header1.Destroy()

Thisform.pageframe1.Page2.ввод.Destroy()

Thisform.pageframe1.Page2.list1.Destroy()

Thisform.pageframe1.Page2.Кнопка «Автомобиль».Destroy()

Thisform.pageframe1.Page1.Destroy()

Thisform.pageframe1.Page1.Кнопка «Добавить».Destroy()

Thisform.pageframe1.Page1.command1.Destroy()

Thisform.pageframe1.Page1.grid1.Destroy()

Thisform.pageframe1.Page1.grid1.column7.Destroy()

Thisform.pageframe1.Page1.grid1.column7.text1.Destroy()

Thisform.pageframe1.Page1.grid1.column7.header1.Destroy()

Thisform.pageframe1.Page1.grid1.column5.Destroy()

Thisform.pageframe1.Page1.grid1.column5.text1.Destroy()

Thisform.pageframe1.Page1.grid1.column5.header1.Destroy()

Thisform.pageframe1.Page1.grid1.column4.Destroy()

Thisform.pageframe1.Page1.grid1.column4.text1.Destroy()

Thisform.pageframe1.Page1.grid1.column4.header1.Destroy()

Thisform.pageframe1.Page1.grid1.column3.Destroy()

Thisform.pageframe1.Page1.grid1.column3.text1.Destroy()

Thisform.pageframe1.Page1.grid1.column3.header1.Destroy()

Thisform.pageframe1.Page1.grid1.column2.Destroy()

Thisform.pageframe1.Page1.grid1.column2.text1.Destroy()

Thisform.pageframe1.Page1.grid1.column2.header1.Destroy()

Thisform.pageframe1.Page1.grid1.column1.Destroy()

Thisform.pageframe1.Page1.grid1.column1.text1.Destroy()

Thisform.pageframe1.Page1.grid1.column1.header1.Destroy()

Thisform.pageframe1.Page1.Кнопка «Искать».Destroy()

Thisform.pageframe1.Page1.label1.Destroy()

Thisform.pageframe1.Page1.источник.Destroy()

Thisform.pageframe1.Page1.text1.Destroy()

Form.UNLOAD

Thisform.Unload()

Thisform.dataenvironment.AfterCloseTables()

Thisform.dataenvironment.Destroy()

Thisform.dataenvironment.cursor8.Destroy()

Thisform.dataenvironment.cursor7.Destroy()

Thisform.dataenvironment.cursor4.Destroy()

Thisform.dataenvironment.cursor6.Destroy()

Thisform.dataenvironment.cursor5.Destroy()

Thisform.dataenvironment.cursor3.Destroy()

Thisform.dataenvironment.cursor2.Destroy()

Thisform.dataenvironment.cursor1.Destroy()

screen.Paint()

screen.Paint()