25 | 06 | 2017

Глава 13:Загадки AppGen (часть1)

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

Подобные желания-соображения отчасти продиктованы высокой стоимостью разработки программного обеспечения. Я отвергаю половину предложений, потому что потенциальный заказчик рассчитывает получить, скажем, Lotus 1-2-3 и заплатить не больше розничной цены пакета. 1-2-3 обошелся в 2 миллиона долларов, если учитывать только написание кода и отладку, при том, что разработчики имели определенный задел в начале работы - исходные тексты конкурирующей фирмы. Людям страшно не хочется платить деньги; они предпочитают поискать более простое решение проблемы.

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

Будущее уже настало?

Действительно, генераторы существуют - Genifer, UI2, Stage, FoxApp. Шаблоны генератора Stage разработаны очень тщательно и, благодаря сложной структуре словаря данных, позволяют получить бесконечные вариации генерируемого кода. Smart Templates, разработанные Management Factware, просто великолепны и, вполне возможно, будут включены в состав FoxPro в ближайшем будущем. Что же касается FoxApp, то этот генератор вы получаете вместе с FoxPro бесплатно, так что по меньшей мере одна программа такого типа у вас уже есть.

И все-таки каждый из пакетов (за исключением Smart Templates) генерирует приложение, выглядящее подобно родителю. Вы, конечно, можете переписать шаблоны, но это чертовски непросто изучать два языка: FoxPro и язык шаблона.

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

В этой статье я собираюсь показать как просто модифицировать генератор FoxApp и его напарника GenScrn для добавления им свойств, которые мне хотелось бы иметь.

Что нам нужно

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

Так что первой задачей было присоединить функцию к разработке, написанной для FoxPro 2. В прежние времена я сам задавал порядок всех полей GET на экране. Теперь FoxPro использует переменную _CurObj, что значительно облегчает дело. Для того чтобы вывести порядковый номер поля мне необходимо знать их положение. Счетчик полей у меня есть, а координат не было.

Я решил использовать два массива ROWS(I) и COLS(I), где I - порядковый номер поля. В массивах будут храниться координаты полей. При нажатии определенной клавиши сгенерированная программа выполнит следующую функцию:


FUNCTION JumpTo
SAVE SCREEN
FOR I=1 TO m.Numflds
@ rows(I),cols(I) SAY "[" + + "]"
ENDFOR
@24,0 GET GoWhere PICTURE [##] RANGE 1, NumFlds
READ
IF GoWhere <> 0
_CurObj=GoWhere
ENDIF
RESTORE SCREEN


Конструктор экранов FoxPro знает где расположены поля ввода и хранит их в файле с расширением .SCX в полях с именами VPOS и HPOS. Мне было необходимо модифицировать программу генерации экранов так, чтобы она создавала массивы и назначала клавишу вызова функции. Генерируемый код направляется в файл с расширением .SPR.

Программа <имя экрана>.SPR создается GENSCRN.PRG. Вы можете назначить вашу собственную программу генерации, включив в CONFIG.FP следующую строку:

_Genscrn=C:\Foxapps\mygen.prg

Не забудьте только убрать из AUTOEXEC.BAT строку:

SET FOXPROCFG=C:\FOXPRO2\CONFIG.FP

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

Как FoxApp создает код

FoxApp использует описание приложения из файла экрана. Вначале идет установочный код, за которым следуют определения SAY и GET, после чего размещается закрывающий код.

Вернемся к нашей проблеме. Мне было нужно создать массивы ROWS и COLS для использования с функцией. Я нашел какой участок Genscrn создает код для полей GET (Листинг 13-1). Код поля GET - 15, и я установил фильтр на ObjType=15, чтобы затем в цикле SCAN...ENDSCAN считать все записи, относящиеся к GET, и создать два массива: ROWS(I) и COLS(I). Кроме того, я записал в переменную NumFlds число полей.

Функция JumpTo представлена в Листинге 13-2. Код очень похож на тот, что я использую при создании циклических READ, основанных на использовании массивов, за тем исключением, что в своей программе "F2" я использую Readkey(), которая здесь нам не потребуется.

В качестве "горячей клавиши" мне хотелось бы использовать F2. Оказалось, что клавиши F2-F5 зарезервированы FoxApp для перехода между записями. Не понимаю, почему они не использовали Ctrl-N для перехода на следующую запись и т. д., хотя может быть потому, что эта комбинация зарезервирована самим FoxPro. Мне это доподлинно известно, потому что я потратил несколько часов, пытаясь переназначить эту комбинацию. Не трудитесь: Уолт знает свое дело (видимо, имеется ввиду Уолтер Кеннамер - один из создателей FoxPro, - прим. пер.).

У нас осталось Ctrl-G (Go To), и я был рад, увидев, что это работает (Ctrl-J /Jump/ не работает). Итак, я задал ON KEY LABEL Ctrl-G DO JumpTo, и мой прототип заработал.

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

Компиляция модифицированной программы Genscrn прошла без проблем, и после генерации полученная программа работала! Я был просто счастлив.

Следующим шагом было использование нововведения в FoxApp. После того как я сгенерировал приложение оказалось, что программа работает по своим принципам. Если я назначал переход к полю 8, курсор переходил к полю 2, если я назначал переход к полю 10, он оказывался в поле 4. В этом была какая-то закономерность. Программа увеличивала номер каждого поля на 6.

Оказывается, что FoxApp создает код для панели управления Appctrl перед тем как создаются поля ввода вашего экрана. В окне панели управления 6 кнопок и оказывается, что ваш экранный объект под #1 фактически имеет #7. Понимаете в чем дело? В листинге 13-2 вы найдете исправления. Теперь код работает независимо от того чем он был создан: генератором экранов или FoxApp.

Теперь нужно было добавить Ctrl-G в меню, создаваемое FoxApp. Это привело меня ко второму этапу работы и заняло больше времени, чем я предполагал. Взгляните на приведенный в Листинге 13-1 и Листинге 13-2 код и позже мы продолжим обсуждение загадок AppGen.

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

Код в Листинге 13-1 инициализирует массивы, используемые процедурой, выводящей номера всех полей вашего экрана. В Листинге 13-2 приведен код, записывающий функцию JumpTo в закрывающий код, где размещаются все функции, вызываемые при работе с экраном.

Модификации GenScrn

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

Затем я добавил функцию JumpTo. Помните, что мы сейчас создаем выходной файл, и запись в него реализуется командами \ \\. В данном случае нет необходимости писать какие-либо модификации, функция всегда выглядит одинаково.

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

Я оставил три строки отладочного кода и, если вы захотите, можете снять комментарии и посмотреть, что получится. Они служат как напоминание возможности восстановить системное меню и "горячие клавиши" перед переходом в окно трассировки.

Я открыл конструктор экранов и создал код, приведеный в Листинге 13-3.