Глава 3:BROWSE (часть2)

Простой пример Самая простая демонстрация требует только одной команды BROWSE. Получающееся окно занимает примерно две трети экрана. Если вы хотите, чтобы окно заняло весь экран выполните следующие команды:

DEFINE WINDOW big FROM 0,0 TO 24,79 NONE
BROWSE WINDOW big

Как сделать BROWSE умнее

Первое, что мне хотелось получить от BROWSE, - это возможность автоматического перехода на новую строку после окончания текущей. Такое свойство полезно, когда вы вводите данные и не хотите нажимать клавишу "стрелка вниз" для перехода на новую строку. Для этого потребовалось немного больше усилий чем можно было ожидать (Листинг 3-2 (Реализация автоматического перехода на следующую запись в BROWSE))


Сложный пример

Программа, приведенная в Листинге 3-3 (Экран ввода данных на базе BROWSE), представляет большую часть приложения, разработанного для магазина, торгующего одеждой, с использованием BROWSE как основы для ввода данных. Я не привожу блок программы, отвечающий за ввод платежа (позволяющий вводить различные виды платежей), так как он слишком велик и не относится к теме нашего обсуждения.

Структура программы

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


Я решил включить примеры нескольких процедур анализа ввода. Я вывожу все стили в виде меню, что ускоряет процесс проверки правильности ввода. Размеры, соответствующие каждому стилю, определяются по коду размера, вставленного в код стиля. При запуске программы файл Sizes считывается в двумерный массив. Меню, используемое при проверке правильности ввода размера, формируется из этого массива. Каждый предмет, продаваемый магазином, может поставляться в ограниченном наборе цветов и размеров. Цвета хранятся в файле Styles в поле длиной 100 символов. При анализе ввода соответствующая строка разбивается на десять блоков по 10 символов. Я использовал такой подход, потому что максимальное количество цветов для одного предмета составляет 10.

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

Идентификатор заказчика строится из нескольких (до пяти) букв его фамилии, соединяемых с несколькими (до пяти) буквами имени. Полученная строка урезается до восьми символов и соединяется с двузначным порядковым номером от 01 до 99, предназначенным для исключения возможного дублирования. Похоже, что такая комбинация еще ни разу не подводила.

Экран ввода заказчика я получил генерацией и последующей модификацией полученного кода (Листинг 3-4(Текст программы добавления нового заказчика)).

Структуры файлов и индексы

Многие из полей, приведенных в описаниях структур в Табл. 3-1(Структуры файлов и индексы, использованные в примере), зарезервированы для возможного расширения системы или используются функциями, не включенными в публикуемый пример.

SET SKIP

И, наконец, особый вариант BROWSE, который может быть полезным в некоторых случаях. Команда SET SKIP позволяет устанавливать отношения один-ко-многим между двумя файлами данных. Каждой записи родительского файла может соответствовать несколько записей дочернего файла. Если вы создаете отношения один-ко-многим, то можете использовать BROWSE для просмотра записей из родительского и дочернего файлов. Пример программы приведен в Листинге 3-5( BROWSE с активным SET SKIP )

Для каждой записи родительского файла, появляющейся в окне BROWSE, выводятся все (если они есть) связанные записи из дочернего файла. Родительская запись появляется вместе с первой соответствующей дочерней записью. Все последующие дочерние записи выводятся в строках, расположенных ниже. Все поля кроме первого, соответствующие родительской записи, заменяются на строку из символов _.

Для перехода между родительскими записями вы можете использовать Ctrl-DnArrow/Ctrl-UpArrow.

Заключение

Отладка BROWSE может представлять немало проблем, так как очень много событий происходит одновременно. Кроме того, подобные мощные средства иногда оказываются медленнее по сравнению с кодом, написанным вами. Если скорость для вас имеет принципиальное значение, вам придется написать сокращенный вариант BROWSE самостоятельно, используя одну из предложенных в этой главе методик. Если вы используете BROWSE, простота программирования сэкономит вам немало времени. Не забывайте установить SET RESOURCE OFF перед использованием BROWSE, увеличение скорости весьма заметно.

Листинг 3-4


* Program-ID...: AddCust.PRG
* Purpose......: Adds a new customer IF NOT WEXIST("addcust")
DEFINE WINDOW addcust ;
FROM INT((SROW()-9)/2),INT((SCOL()-68)/2) ;
TO INT((SROW()-9)/2)+8,INT((SCOL()-68)/2)+67 ;
TITLE "Add Customer to Mailing List" ;
NOFLOAT ;
NOCLOSE ;
SHADOW ;
COLOR SCHEME 1
ENDIF

SCATTER MEMVAR BLANK

IF WVISIBLE("addcust")
ACTIVATE WINDOW addcust SAME
ELSE
ACTIVATE WINDOW addcust NOSHOW
ENDIF

@ 0, 12 SAY [(First) (Last)]
@ 1,7 SAY "Name"
@ 1,12 GET m.FirstName ;
DEFAULT " "
@ 1, $+2 GET m.LastName ;
DEFAULT " "
@ 2,12 GET m.address1 ;
SIZE 1,50 ;
DEFAULT " "
@ 3,12 GET m.address2 ;
SIZE 1,50 ;
DEFAULT " "
@ 4,12 GET m.city ;
SIZE 1,25 ;
DEFAULT " "
@ 4,38 GET m.state ;
SIZE 1,2 ;
DEFAULT " " ;
PICTURE "!!"
@ 4,41 GET m.zip ;
SIZE 1,10 ;
DEFAULT " "
@ 5,12 GET m.phone1 ;
SIZE 1,12 ;
DEFAULT " " ;
PICTURE "XXX-XXX-XXXX"
@ 5,41 GET m.phone2 ;
SIZE 1,12 ;
DEFAULT " " ;
PICTURE "XXX-XXX-XXXX"
@ 4,1 SAY "City,State"
@ 5,5 SAY "Phones"
@ 5,25 SAY "(Home)"
@ 5,54 SAY "(Work)"

IF NOT WVISIBLE("addcust")
ACTIVATE WINDOW addcust
ENDIF

READ COLOR ,W+/R

RELEASE WINDOW addcust

IF LEN(ALLTRIM(M.LASTNAME)) <> 0
* Create a unique key for this new customer
M.ID = UPPER ( ;
ALLTRIM ( LEFT ( M.LastName , 5 ) ) ;
+ ALLTRIM ( LEFT ( M.FirstName , 5 ) ) )
SEEK M.ID
M.SEQNO = 0
DO WHILE FOUND()
M.SEQNO = M.SEQNO + 1
M.ID = LEFT(M.ID,8) + TRAN ( M.SEQNO , [@L ##] )
SEEK M.ID
ENDDO
APPEND BLANK
GATHER MEMVAR
mCustomer = M.ID
ELSE
=Alarm()
WAIT WINDOW [Cancelled] TIMEOUT 1
Cancelled = .T.
ENDIF

RETURN