Пособие перекочевало на этот сайт в "пожарном" порядке, поэтому прошу прощения за неаккуратное исполнение. :(
ОГЛАВЛЕНИЕ
Часть 1. С чего начать?
Проект
Наполнение
проекта
Базы данных (Data)
Коды (Code)
Документы (Documents)
Классы (Classes)
Прочие (Other)
Часть 2. Мелочи работы
Переносимость
между платформами
Распространение приложения
Вопросы и ответы
Чем заменить наш привычный SAY для экрана?
Какие свойства определяют цвет?
Что определяет размер и выравнивание текста в Grid?
Как избежать выделения всей ячейки (функция «К»)?
Как уменьшить число страниц в форме?
Как создать просматриватель MEMO-полей?
В каком случае нужен набор форм?
Где разместить условие отбора данных для Grid?
Где определять переменные, упоминаемые в свойствах таблицы?
Как остановить форму на экране, если нет меню?
Как вызывать вспомогательные окна?
Как заставить обновляться экран, если прокручиваем элемент управления "Grid"?
Чем отличается внедренный объект от связанного?
Как бороться с главным окном?
Разное
Отчёт (версия 3.0)
Конвертация
приложений из 2.6 для DOS в 3.0 для Windows
Проект
Экраны
Как перемещаться между элементами экрана?
Отчеты
Прочее
Спотыкашки версии 5.0 в
Создание меню
Пользовательские функции
Число прописью
Преобразование числа в строку с пробелами
Звук
Часть 3. Последовательность событий
Начинать надо с проекта.
Я знаю людей, которые в FoxPro для DOS использовали проект только для генерации исполняемого файла. В Visual FoxPro проект - основа всего.
Нажимайте: File - New, по умолчанию вам сразу будет предложено сделать проект - в появившемся меню уже выбран пункт Project. Если вы выбираете кнопку New File придется задать имя проекта, под которым он будет сохранен и вы получите окно проекта.
Есть еще кнопка предполагающая использование Wizard.
Честно скажу - после написания этих строк впервые решил её попробовать. Оказалось, что с помощью Волшебника проект можно сделать со структурой директорий, в которые потом Visual FoxPro будет разносить программы, базы, отчеты, но это же можно сделать и без волшебника. Wisard-ы вообще отдельный разговор - вероятно, это хорошая вещь, но пока с их помощью мне не удалось сделать что-нибудь сложнее справочника.
Поговорим о проекте, придерживаясь его страниц...
|
|
Я полагаю, вы уже представили какие таблицы базы данных вам будут нужны, набросали их структуры. Теперь выберите в окне проекта вкладыш Data, потом New и ... Вот тут нелишним будет напомнить, что Visual FoxPro имеет базу данных (database) и таблицы (table), которые в прошлом нестрого также называли базами данных. База данных Visual FoxPro содержит данные о таблицах входящих в неё и структуру которых мы, собственно, и создаём. Впрочем, таблицы могут быть и свободными, т.е. не входящие, не включенные и не учтенные в файле базы данных (database). При этом они утрачивают так много полезных свойств, что я стараюсь их не отпускать на свободу без крайней необходимости. Подробнее см. официальную документацию и её многочисленные пересказы.
Приложение должно иметь главный файл, с которого оно будет запускаться и который в проекте выделяется жирным написанием. В принципе, это может быть и форма, но я использую обычный программный модуль с именем 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). Вряд ли кто будет «кликать» по числу суммы, но даже если это и случиться, то просто снова всё что надо сложится. Здесь главное для себя логически обосновать выбор объекта и метода, где будет находиться формула, чтобы при необходимости её можно было бы без труда найти.
|
|
Главный экран
Вот так выглядит главный экран (он же - главное меню) в моем исполнении. Простая многостраничная форма, в которой заголовки страниц выполняют роль линейки меню, опции расположены на страницах и представляют собой метки (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-ом, он сам накидает в проект всё, что нужно.
Меню - без комментариев. Поскольку существующий Wizard и его продукцию не люблю, то и не делаю.
Категорию текстовых файлов попадает файл конфигурации. Если вы его поместите в проект, пользователю в наборе файлов приложения он уже не будет нужен.
Прочие в прочих. Сюда удобно поместить BMP-картинки, которые вы использовали для фона экранных форм. Они после компиляции также окажутся в исполняемом модуле (отчего он изрядно «пополнеет»). А вот звуковые файлы *.WAV в проект включать нет смысла - они в ЕХЕ-шник не включаются и пользователю передаются в явном виде.
Не рискну утверждать, что эти «мелочи» типичны для 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 при наработанном опыте и лучшем качестве продукта всё пошло гораздо легче и с меньшими проблемами.
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
Рамка - не нашёл
Размер и выравнивание текста в Спокойной ячейке определяется 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. Но надо помнить, что исчезнет последняя страница, причем, вместе с содержимым.
В форме. Создать EditBox и кнопку его вызова, в свойство Click которой поместить код: thisform.Поле.Refresh - иначе содержимое поля не будет обновляться и Thisform.Поле.visible=.T. - при нажатии на кнопку поле становится видимым. Источником данных для поля EditBox должно быть МЕМО-поле соответствующей таблицы.
Отключать поле можно поместив в метод DblClick кнопки следующий код: thisform.Поле_примечаний.visible=.F.
Когда нужно работать с несколькими формами создание набора является оптимальным решением. Формы при этом (пока) видны все, но можно ненужные в данный момент сворачивать в иконку. На выходе обязательно указать ThisFormSet.Release, чтобы закрылось действительно всё.
Версия 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 той области, в которой работает родительская программа
В свойство 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, таблица откроется вторично в новой области
Подход к отчету.
Форма имеет свое окружение, которое не хочет принадлежать отчету. Созданные в этом окружении возвратные отношения не распространяются на отчет. Возвратные отношения в окружении устанавливаются легко и просто..., но это не значит, что в этой среде может работать все что угодно.
Создание отчетов.
Целесообразно делать для отчета свою среду данных с нужными связями. Сильно расширяют возможности отчета пользовательские функции, которые в ряде случаев гораздо эффективнее встроенных возможностей.
При выводе отчета на печать до него надо сохранить образ экрана в переменной, а после - восстановить. Опцию NOCONSOLE можно не ставить - отчет по мере распечатки выводится в текущее окно, и если оно достаточно велико, то получается весьма информативно.
Конечно, начинать надо с проекта. При попытке открыть его включается конвертор (или конвертатор?). Перед конвертацией из исходной директории надо удалить файлы с расширением 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, пусть и по старому проверенному алгоритму.
Если их мало, значит я просто через что-то перешагнул, а до чего-то не дошёл...
В сгенерированном меню строка следующего содержания:
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
Знание последовательности выполняемых событий трудно переоценить, ибо зачастую необъяснимые ошибки работы приложения бывают связаны с тем, что программный код в событиях выполняется не в той последовательности в какой хотелось бы разработчику, а в той какую задаёт порядок самих событий. Например, в нижеприведенном списке легко увидеть, что сначала инициализируется страница в объекте 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()