Изучаем программирование в Gupta Team Developer. Шаг 3 - меню, массивы, диалоги и прокруткаИсточник: Interface Ltd Большаков С.А.
Оглавление
ВведениеЕсли Вы познакомились с первыми двумя статьями данной серии, то, несомненно, обратите внимание на то, что мы изменим стиль изложения материала. Во-первых, Вы уже много знаете для дальнейшей работы, а во-вторых, мы постараемся излагать материал более интенсивно, что позволит нам вместе двигаться быстрее. Для успешного освоения данного материала, который, мы очень надеемся, может служить своеобразным самоучителем программирования на Gupta Team Developer, желательно познакомиться и выполнить задания статей "Шаг 1" и "Шаг 2". Теперь мы будем сначала обозначать цель (в виде готового окна приложения), к которой будем стремиться, а затем будем показывать, как достигается эта намеченная цель, то есть по шагам расскажем, что нужно сделать в программе для выполнения приемов программирования с конкретными объектами интерфейса. Рассмотрим совместно два вопроса: как работать с оконными меню и как вызывать окна диалога. Меню и диалоги TDРабота с оконными меню. Редактор меню и ручной способ настройкиНиже представлено главное окно приложения для изучения принципов построения меню и работы с окнами диалога. Назовем его (приложение) step3_dialog.app. Данное окно типа - Form Window. Меню в TD можно создавать для окон любого класса, кроме окон диалога (Dialog Box). Рис. 1. Окно приложения для изучения меню и окон диалога в TD Для создания меню можно использовать ассистент кодирования или визуальный редактор меню (Component->Menu Editor или "Правая кнопка"-> Menu Editor). Редактор меню, его окно показано на рисунке ниже, позволяет ввести и настроить пункты меню, построить вложенное меню (POPUP), задать порядок пунктов меню, разделители, настроить текст подсказки (Status Text) и определить горячие клавиши для пункта (Accelerator). Кроме этого Вы можете определить состояние пункта меню (доступен или недоступен, помечен или не помечен) с помощью констант, переменных и функций, а также задать вызываемую функцию или запускаемое окно приложения. Работа с редактором меню интуитивно понятна, а результат настроек отображается автоматически в OUTLINE окна и может в дальнейшем редактироваться вручную. Рис. 2. Визуальный редактор меню TD Результат конструирования меню будет занесен в текст разрабатываемой программы, который показан на рисунке ниже. Для наглядности здесь приведено дерево окна (слева), в котором для главного окна (frmFirst) выделена позиция оконного меню (Windows Menu), а справа показан текст построенного меню. Рис. 3. Текстовое редактирование меню в режиме OUTLINE Для наглядности не все пункты меню развернуты (мы их рассмотрим далее) и приведен фрагмент окна ассистента кодирования в режиме добавления новых позиций меню. Можно добавить: новую позицию меню (Menu Item), вложенное меню (Popup Menu), поименованное меню (Named Menu), стандартное меню управления окнами (Windows Menu), строки меню (Menu Row) и колонки меню (Menu Collumn). Последние две позиции позволяют организовать строчное меню в виде нескольких строк, а ниспадающее меню из нескольких колонок. Кроме того, можно в ниспадающем меню вставить разделители (Menu Separator). Рис. 4. Окно приложения для изучения меню и окон диалога в TD На рисунке, представленном ниже дан перечень основных объектов окна приложения, которое мы будем использовать для изучения режимов меню и работы с окнами диалога. Эти объекты соответствуют визуальным объектам окна. Рис. 5. Объекты окна приложения для изучения меню и окон диалога в TD Кнопка pbClose, обеспечивает закрытие окна. Поле dfNumMain служит для ввода целочисленного параметра, передаваемого в диалог. Поле mlStrMain (типа Multiline Field) служит для ввода многострочного параметра, передаваемого в диалог. Поле dfIndic, недоступное для редактирования, используется для индикации изменения строки передаваемой в диалог. Меню. Деактивация и пометка пунктов менюСостоянием меню можно легко управлять в процессе выполнения программы. Для этого могут быть заданы переменные или функции для описателей меню, содержащихся в разделе Menu Settings: Enadled when ("доступно, если") и Checked when ("помечено если"). В этих разделах OUTLINE можно:
Результат такого управления пунктами меню показан на рисунках, расположенных ниже. Пометка меню представлена "галочкой" расположенной перед строкой меню, а недоступность обозначается бледным цветом. Рис. 6. Главное окно с подменю. Ниже дан фрагмент текста программы, содержащий код обработки пункта меню "Диалог". Реакция на активизацию пункта меню приводит к выполнению подпрограммы на языке SAL определенному в разделе Menu Actions. В данном пункте:
Рис. 7. Описание меню вызова окна диалога После возврата из окна диалога:
Установки меню для другого вложенного пункта меню "Вызов диалога" сделаны так, что этот пункт всегда доступен (Enabled when - TRUE) и пометка управляется специальной функцией (MenuCheck), фрагмент которой приведен ниже. Функция работает в режиме триггера (меняет попеременно возвращаемое значение с TRUE на FALSE и обратно). Функция управляет внешним параметром bCheck. Таким образом, "галочка" появляется попеременно в пункте вложенного меню. Рис. 8. Установки меню и функция установки Выключение пункта "Диалог" главного меню выполняется в его процедуре обработки (мы уже об этом говорили выше). Внешний параметр bQuit устанавливается в FALSE. После этого с помощью специальной функции SalDrawMenuBar обновляется состояние пунктов меню. Рис. 9. Выключение пунктов меню с помощью переменной Включение пункта "Диалог" главного меню выполняется следующим аналогичным образом. Параметр bQuit устанавливается в TRUE. Это показано на рисунке, представленном ниже. Рис. 10. Включение пунктов меню с помощью переменной Более сложные операции по управлению меню в TD можно выполнять с помощью библиотеки Visual Toolchest (VT), которую мы предметно рассмотрим в следующих статьях. После того как мы научились, в основном, управлять пунктами меню, рассмотрим, как создавать и вызывать диалоговые окна. Создание и описание окна диалогаВид окна диалога "Пробный диалог", которой мы будем рассматривать представлен ниже на рисунке. В данном окне определены данные, в которых высвечиваются параметры, передаваемые в диалоговое окно. Кроме того, выделен переключатель (Check Box), который для иллюстрации используется для управления кодом возврата из диалога. Рис. 11. Вид вызываемого окна диалога Данные объекты выделены также в дереве приложения на рисунке ниже. Отметим, в древовидной структуре описания объектов размещаются и объекты фонового текста (Background Text) для заголовков полей параметров ("1-й и 2-й параметры"). Рис. 12. Фрагмент дерева приложения для окна диалога dlgTest Самое подробное описание диалогового окна представлено в тексте программы (OUTLINE), которое дано на нижнем рисунке. В первой строке описание дается название формы типа Dialog Box - dlgTest. Рис. 13. Описание окна диалога dlgTest (текст OUTLINE) Рис. 14. Описание параметров окна диалога В разделе Windows Parameters задаются параметры (формальные параметры), которые передаются в окно при его запуске. В качестве параметров могут передаваться любые переменные языка SAL. В нашем случае это: целочисленный параметр nTest и параметр типа длинная строка (Long String) - strTest. Перед параметром strTest стоит префикс Receive, который означает, что данный параметр может быть возвращен в вызывающую процедуру (см. ниже). После запуска окна диалога обрабатывается сообщение SAM_CreateComplete и элементам оконного интерфейса диалога (dfNumber и mlTest) присваиваются значения передаваемых параметров. Значение переключателя кода возврата cbReturn (Check Box) устанавливается по умолчанию в положение FALSE (выключено). Главное окно в момент перед вызовом окна диалога показано на нижнем рисунке. Перед вызовом диалога из главного окна можно вручную задать значения передаваемых параметров, либо использовать значения, задаваемые по умолчанию (44 и " Пример текста, Занимающего две строки! " соответственно). На рисунке они уже занесены в поля ввода "Число:" и "Длинная строка:". Рис. 15. Главное окно с параметрами вызова Для иллюстрации выхода из предложения и вызова диалога создадим вложенное меню (POPUP), подчиненное пункту главного меню "Выход из подменю". Определим наименование пунктов (Menu Item) подменю так: "Выход из приложения" и "Вызов диалога". На рисунке, расположенном ниже, приведен пример описания вложенного меню. Вид этого подменю в раскрытом виде был показан на рисунке выше. Рис. 16. Описание POPUP меню Вызов окна диалога в программе выполняется с помощью функции SalModalDialog. Пример вызова дан ниже на рисунке. Рис. 17. Вызов окна диалога и проверка кода возврата nCount Первый фактический параметр при вызове этой функции задает имя диалога (dlgTest), второй параметр определяет переменную указатель вызывающего окна (hWndForm - это стандартная переменная, определяющая указатель текущего окна, у нас это окно - frmFirst). Третий и четвертый - это необязательные параметры диалога. Таких параметров при описании диалогов можно определить произвольное число. В нашем случае это: dfNumMain - целочисленное поле ввода окна и strCommon переменная окна типа Long String. Код возврата, возвращаемый диалогом, будет записан в специальную переменную (nCount). Анализ данной переменной позволяет выдать сообщение, приведенное ниже. Рис. 18. Сообщение с индикацией кода возврата Строка, возвращаемая из диалога (strCommon), может быть проверена и выведена на экран. Это показано ниже во фрагменте текста. Сначала проверяется изменение параметра и на экран главного окна выдается сообщение индикации изменений (поле - dfIndic, защищенное от редактирования). Поле экрана mlStrMain задается в операторе присваивания, а затем для иллюстрации принятая из диалога строка выводится в окне сообщений (SalMessageBox). Рис. 19. Контроль возвращаемого параметра strCommon Результат вывода приведен на рисунке, расположенном ниже. Рис. 20. Сообщение с индикацией возвращаемого параметра Завершение диалогаЗавершение работы диалогового окна выполняется функцией SalEndDialog. Пример ее вызова в окне диалога показан на рисунке приведенном ниже. Рис. 21. Фрагмент текста завершения диалога с параметром По значению переключателя (cbReturn), который может быть установлен в самом диалоговом окне вручную, код возврата устанавливается в 0 или 1. Данные действия выполняются в разделе Message Actions при реакции на сообщение SAM_Click для кнопки pbClose окна диалога. В результате выполненных действий Вы получите приложение step3_dialog.app, которое для проверки усвоения материала можно скачать здесь. Массивы статические и динамическиеСледующий шаг изучения программирования в TD мы сделаем в направлении знакомства со статическими и динамическими массивами. Отметим, что массивы в TD могут быть статическими и динамическими, с одной размерностью и несколькими размерностями. Размер статического массива фиксирован и определен заранее. Количество элементов в динамических массивах может программно изменяться. В принципе, работа с одноразмерными и много размерными массивами одинакова (нужно указывать несколько индексов для доступа к элементам и несколько размерностей для их описания размерности). Мы остановим, для простоты, свое рассмотрение классом одномерных массивов. Работу с многомерными массивами предлагаем читателю освоить самостоятельно. Ниже дано окно приложения для изучения работы с массивами. Назовем его (приложение) step3_array.app. Рис. 22. Окно приложения для изучения статических массивов TD В данном окне показаны все основные возможности для иллюстрации работы с массивами. Мы будем отдельно рассматривать особенности работы со статическими и динамическими массивами, поэтому представленное окно может со статическими и динамическими массивами (этим управляет радиокнопка - "Тип массива"). Описание и создание массивовВ окне приложения предусмотрено:
Пример описания статических и динамических массивов одной размерности дан на рисунке, расположенном ниже. Рис. 23. Описание статических и динамических целочисленных массивов в TD Массивы могут быть описаны в разделе Windows Variables окна (или приложения). В данном примере описан статический целочисленный массив nStaticArray, размерностью 5 элементов и динамический массив nArray, размерность которого не определяется при описании (вместо размерности поставлена "*"). Описанные здесь же вспомогательные целочисленные переменные nCount и nIndex, которые использованы в программе. Перечень объектов приложения для иллюстрации работы с массивами в TD дан ниже во фрагменте текста. Рис. 24. Объекты окна статических и динамических целочисленных массивов в TD Названия объектов приложения подобраны таким образом, что несложно определить их назначение и соответствие визуальным объектам окна, представленного выше. Здесь мы не будем тратить время на их подробное пояснение, его мы сделаем при описании соответствующих процедур работы с массивами. Функции массивовДля работы с массивами в TD предусмотрены специальные функции, позволяющие получить основные характеристики массива. Это суммирование, формирование среднего, минимального и максимального значения массивов. Рис. 25. Вызов стандартных функций для массивов Во фрагменте текста на рисунке, приведенном выше, показано использование этих стандартных функций для: получения суммы элементов массива (SalArraySum), подсчета среднего значения (SalArrayAvg), нахождения максимума (SalArrayMax) и минимума (SalArrayMin) массива. Заполнение и границы массивовЗаполнение массива выполняется обычным циклом, вид которого приведен ниже. Рис. 26. Заполнение массива последовательностью значений В данном фрагменте текста на языке SAL, первоначально, с помощью функции SalArrayGetUpperBound вычисляется верхняя граница массива (nCount). Так как по умолчанию индексация статического массива выполняется с 0 до N-1, то начальное значение индекса (nIndex) задается равно нулю. Далее с помощью функции SalListClear очищается список (lbArray), в котором в окне предусмотрена индикация значений массива. Далее в цикле присваиваются новые значения элементов массива, для чего используется традиционная, как в СИ, конструкция с индексами: [<индексное выражение>]. Кроме этого, запомненный элемент заносится в список (функция - SalListAdd), изменяется индекс и проверяется на достижения его граничного значения (nIndex >nCount) для завершения цикла (Break). Для изменения или задания границ массива применяется функция SalArraySetUpperBound, которая имеет три параметра. Применение этой функции дано на рисунке ниже. Рис. 27. Динамическое задание границы массива Параметры имеют следующие назначение:
При работе с массивами можно динамически контролировать их размерность для задаваемых индексов. Это, как показано на примере фрагмента текста, приведенного ниже, делается с помощью стандартных функций: SalArrayGetLowerBound, для получения нижней границы массива (dfMasBeg) и SalArrayGetUpperBound, для получения верхней границы массива (dfMasEnd). Рис. 28. Выбор элемента массива с контролем границ Далее в программе проверяются границы массива. При несоответствии индекса границам выдается сообщение о неверном индексе. Наращивание массивовВ программе SAL предусмотрено динамическое наращивание массива. Для этой операции используется также знакомая Вам функция SalArraySetUpperBound. В примере (см. ниже) количество элементов массива наращивается (исходное число - dfMasEnd) на величину dfAddNum, которая задается вручную в соответствующем поле ввода. Отметим, что после добавления новых элементов в динамический массив существующие элементы не изменяют свое значение, поэтому такие массивы можно использовать в алгоритмах с неопределенными граничными значениями. В этом случае массив можно наращивать поэлементно. Отметим также, что в TD обеспечивается автоматическое наращивание при использовании нового значения индекса вне текущих границ массива. Рис. 29. Динамическое изменение верхней границы массива (dfMasEnd) Работа с динамическими массивами аналогична работе со статическими массивами. Окно для изучения динамических режимов в режиме работы с динамическими массивами представлено ниже. Напомним, что нумерация динамических массивов всегда начинается с 0. Рис. 30. Окно изучения массивов в режиме "Динамический" массив Процедура создания и заполнения динамического массива приведена на рисунке ниже. Комментарии в тексте поясняют выполняемые операции. Рис. 31. Чтение размерности динамического массива (dfMasEnd, dfMasBeg) Отметим, что здесь для заполнения и вычисления суммы массива используется механизм сообщений. К кнопкам pbFillArr и pbSumm с помощью функции SalSendMsg посылается сообщение SAM_Click, что имитирует нажатие кнопки. В результате работы над массивами Вы получите приложение step3_array.app, которое для проверки усвоения материала можно скачать здесь. Линейки прокрутки и кнопки режимовДля оживления интерфейса в программах и его большей наглядности можно использовать стандартные объекты TD: линейки прокрутки (Scroll Bar) и режимные кнопки (Option Button). Линейки прокрутки позволяют выполнять индикацию значений целочисленных параметров визуально и плавно изменять эти значения с помощью специальных оконных элементов управления. Ниже представлено главное окно приложения для изучения принципов работы с линейками прокрутки и кнопками режимов. Назовем его (приложение) step3_scroll.app. Рис. 32. Окно приложения для изучения линеек прокрутки Режимные кнопки обеспечивают задание переключателей с фиксированными значениями. Эти объекты, по сути, похожи на переключатели, но имеют другое визуальное представление и более гибкие возможности для построения программного интерфейса. Ниже представлено окно для изучения линеек прокрутки и режимных кнопок в исходном варианте. Для изучения линеек прокрутки используется горизонтальная линейка (можно использовать и вертикальные), в окно встроена индикация границ и текущего положения линейки, предусмотрены операции изменения диапазона прокрутки ("Установить Range") и центрирования положения ("Установить центр"). Изучаются также операции установки позиции ("Установить позицию") и опроса позиции ("Читать позицию"). Режимы кнопки представлены тремя связанными кнопками, одна из которых "Режим 2" специально имеет другой цвет, что позволяет наглядно иллюстрировать позицию переключателя в специальном поле (см. ниже в примерах). На рисунке ниже показаны основные объекты окна для изучения данных объектов. Рис. 33. Объекты окна приложения для изучения линеек прокрутки Кнопки и их названия соответствуют тестируемым операциям (pbClose, pbSetSbRange, pbSetSbCenter, pbSetPos, pbGetPos). Горизонтальная линейка прокрутки названа hScrollBar1 (объект типа Horizontal Scroll Bar). Поля для индикации границ прокрутки: нижней (dfMinSB, dfMin), верхней (dfMaxSB, dfMax) и текущей (dfCurentSB). Специальные поля для установки позиции (dfPos) и чтения позиции (dfCurrPos). Три кнопки режимов: obReg1, obReg2 и obReg3. Для индикации текущего режима используется неизменяемое поле (Data Field) - dfIndicator. После выполнения следующих действий, которые мы рассмотрим в данном подразделе окно видоизмениться. Измененное состояние показано на рисунке ниже. Здесь установлена позиция "33" в линейке прокрутки (нажата кнопка "Установить позицию"), получено значение после опроса позиции после нажатия кнопки "Читать позицию". Также нажата кнопка "Режим 2", причем индикатор "Выбран" не только изменил свое значение, но и цвет. Рис. 34. Изменение позиции, опрос позиции линейки и установка "Режима 2" Рассмотрим теперь, как обеспечить выполнение этих операций программно. Линейки прокруткиНачальные установки линейки прокрутки при запуске окна показаны на рисунке ниже. Начальные границы прокрутки устанавливаются в программе равными единица и сто (1 и 100), а текущее положение задается равным единице (1). Установка диапазона прокрутки выполняется функцией SalScrollSetRange, которая вызывается с пятью следующими параметрами:
Рис. 35. Фрагмент текста начальных настроек линейки прокрутки В программе, при нажатии кнопки "Установить Range", можно изменить диапазон прокрутки. Фрагмент программы, приведенный ниже, это иллюстрирует. Рис. 36. Фрагмент текста изменения диапазона прокрутки Текущее значение устанавливается равным минимальному значению (dfCurentSB), затем задается новый диапазон, и потом с помощью функции SalScrollSetPos устанавливается новая начальная позиция. Отметим, что эта позиция не обязательно должна быть равна 1. Для установки центральной позиции выполняется нижеследующий фрагмент программы. Сначала рассчитывается значение нового текущего положения (среднее), а затем производится установка. Рис. 37. Фрагмент текста установки средней позиции линейки Для получения позиции прокрутки используется функция SalScrollGetPos, текущее значение заносится в переменнуюполу ввода dfCurrPos (фрагмент ниже на рисунке). Рис. 38. Фрагмент текста установки заданной позиции прокрутки (dfCurrPos) Для установки заданной позиции выполняются действия показанные ниже. Предварительно считываются граничные значения границ. Это выполняется функцией SalScrollGetRange, параметры которой аналогичны функции установки новых границ. Рис. 39. Фрагмент текста программной установки Далее выполняется контроль и установка новой позиции. При неверно заданной новой позиции выдается диагностическое сообщение (SalMessageBox). Для того чтобы при манипулировании с линейкой прокрутки информация о перемещениях оперативно отображалась на экране, необходимо обработать сообщение SAM_ScrollBar, для данного объекта. Это сообщение посылается объекту hScrollBar1 при любых манипуляциях с объектом. Код выполняемой операции посылается в первом параметре сообщения (wParam), дополнительная информация, например новая позиция, задается во втором параметре сообщения (lParam). Отмечу, попутно, что при обработке любых доступных сообщений, в том числе и WM автоматически эти параметры всегда становятся доступными в специальных, локализованных, системных переменных (wParam, lParam). При обработке сообщения доступны следующие события с линейкой прокрутки (выполняемая операция определяется константой типа -SB_*):
На рисунке представленном ниже дан фрагмент текста, в котором обрабатываются сообщения линейки прокрутки. Рис. 40. Фрагмент текста обработки сообщения SAM_ScrollBar Если перемещается "движок", то положение текущей позиции (dfCurentSB) меняется на новое в соответствии с параметром lParam. При любых других операциях с линейкой прокрутки поле dfCurentSB заполняется опросом линейки с использованием знакомой нам функции SalScrollGetPos. Режимы кнопкиРабота с кнопками режимов достаточно проста. После нажатия на кнопку она меняет свое состояния ("вжатое" состояние), а связанные с ней другие кнопки режима свое состояние восстанавливают. Для такого эффекта данные объекты должны быть расположены рядом в тексте OUTLINE. В нашем примере, три кнопки (obReg1 - "Режим 1", obReg2 - "Режим 2", obReg3 - "Режим 3"), предназначены для выбора одного из трех режимов (это очень похоже на применение радиокнопок). При нажатии на кнопку "Режим 2" кроме этого меняется и цвет текста в поле индикатора - dfIndicator. Если режим включен то переменная, соответствующая его имени, принимает булевский тип TRUE, в противном случае - FALSE. Первоначально в поле индикатора передается текст на кнопке выбранного режима с помощью функции SalGetWindowText, а затем устанавливается цвет текста (по умолчанию или красный для второго режима). Рис. 40. Фрагмент текста манипулирования режимами с индикацией цветом Это только один из вариантов работы с кнопками режимов. Далее, проверить работу с другими вариантами и пофантазировать на тему построения оригинального программного интерфейса мы предоставляем читателю самому. В результате изучения линеек прокрутки и режимов Вы получите приложение step3_scroll.app, которое для проверки успешности усвоения материала можно скачать здесь. ЗаключениеВ следующей статье этого цикла мы рассмотрим работу со списками и таблицами, а также начнем осваивать основы работы с БД в рамках TD. Для этого мы ознакомимся с работой встроенного в TD приложения DataBase Explorer и утилиты администратора БД SQLTalk. |