На примере простого приложения Event Core мы разберем основные этапы работы приложения. Исходный текст можно найти либо на сайте проекта www.freepoc.org, либо скачать отсюда:

Строительные блоки: еще пару слов о процедурах

Прежде чем переходить непосредственно к теме статьи, давайте познакомимся с несколькими замечательными возможностями процедур. Рассмотрим код:

PROC addition:(one%,two%)
LOCAL foo%
foo%=one%+two%
RETURN foo%
ENDP
 

Этот пример наглядно иллюстрирует два важных свойства процедур. Рассмотрим их поподробнее.

Передача параметров процедуре: локальные константы

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

addition:(200,100)
или
addition:(number%,300)
 

one% и two% не надо объявлять как переменные, поскольку они таковыми не являются. Фактически - это константы, существующие только в пределах процедуры. После того как процедура закончена, они удаляются из памяти. Именно поэтому каждый раз при вызове процедуры нужно сообщать ей новые значения этих локальных констант.

Значение, возвращаемое процедурой

Если вместо обычного вызова процедуры использовать конструкцию вида:

gnu%=addition:(100,200)

то в переменную gnu% будет записано значение, которое внутри процедуры стоит справа от слова RETURN. Когда в процедуре встречается это слово, происходит ее завершение (как если бы там стояло ENDP) с возвратом значения стоящего за RETURN. (Если в процедуре отсутствует слово RETURN, то при достижении ENDP процедура возвращает 0.)

Как разворачивается история программы

В предыдущей статье было сказано о близости OPL к простому разговорному языку (Я еще не раз буду возвращаться к этой аналогии). Так вот, программа - это как рассказ. Она имеет свое вступление, главную часть и завершение.

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

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

В "завершении" сохраняется вся нужная информация, очищается память и происходит выход из программы.

С учетом всего вышесказанного главная процедура должна выглядеть как-то так:

PROC main:
GLOBAL exit%
initialise:
exit%=0
DO
main_loop:
UNTIL exit%=1
clean_up:
ENDP
 

Программа состоит из вступления (процедура initialise:), главной части (цикл DO..UNTIL) и завершения (процедура clean_up:).

Обратите внимание на использование глобальной переменной exit%. Если в любой части программы установить ее значение в 1, а затем вернуться в main:, то произойдет выход из главного цикла, выполнится процедура clean_up:, сохраняющая все необходимые данные и очищающая память, и программа завершится.

Давайте рассмотрим каждую часть программы более подробно.

Вступление

Внутри функция initialise: мы выполняем всю рутинную работу.

Где лежат файлы?

Прежде всего, мы пытаемся определить местонахождение "служебных" файлов нашего приложения. Большинство программ используют графические .mbm файлы, поэтому будем искать именно их. Используя имя приложения, которое хранится в одной из системных констант, мы проверяем сначала диск C: (внутренняя память), а затем D: (MMC карты). Если требуемую папку удалось найти, сохраняем путь (path$ и data$). В path$ сохраняется полный путь к .mbm с указанием диска, а data$ - без диска.

Настройки пользователя - .ini файлы

Займемся загрузкой персональных настроек пользователя. Они сохраняются в файле <имя приложения>.ini (в рассматриваемом примере это core.ini). Перейдем к процедуре LoadINIFile:. Если файл существует, открываем его; если нет - устанавливаем настройки по умолчанию и сохраняем их в файл.

Именно здесь нам понадобится переменная data$. Дело в том, что .ini файлы должны обязательно находиться на диске C:. В нашем примере мы храним в .ini файле только один параметр, который определяет громкость звука. Фактически .ini файл - это маленькая база данных. При открытии каждой такой базе присваивается буква, каждому полю в базе данных - временная метка.

OPEN"C:"+data$,A,label%

При открытии нашего ini файла, расположенного на диске C:, мы присваиваем ему метку "A". После этого единственное поле этой базы будет нам доступно (временно) как A.sound_vol%.

Мы можем создать в программе переменную (в том числе и совпадающую по имени с названием поля) и записать туда значение интересующего нас поля:

sound_vol%=A.sound_vol%

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

Сохранение настроек также не вызывает никаких сложностей. Прежде всего, мы должны убедиться, что наше приложение имеет папку на диске C:. После этого с помощью команды DELETE мы удаляем старый (уже не нужный нам) .ini файл и создаем новый (CREATE), куда устанавливаем требуемые значения.

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

Обратите внимание на использование ключевого слова TRAP, которое обозначает любое сообщение об ошибке.

Настройки экрана и панели инструментов

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

gDEFAULTWIN x,y,width,height

Ширина всего экрана составляет 640 пикселей. Левая панель инструментов может быть выключена (0) или включена (1). Ее фактический размер зависит от ее типа (маленькое - 1 - 32px; стандартное - 0 -96 px).

AfSetStatus%:(AfStatusType%)
AfSetstatusVisible%:(AfStatusOn%)

Правая CBA кнопка может либо отображаться всегда(1), либо только при нажатии CBA кнопки (0). Ширина кнопки зависит от размера помещенной на нее надписи (80-130 px).

AfSetCBAVisible%:(AfCVA%)

Заголовок окна устанавливается следующей командой:

AfSetTitle:("Title Here",KAfTitleTypeMainTitle%)

Старайтесь использовать осмысленные имена. Константа KAfTitleTypeMainTitle% указывает на то, что вы создали заголовок главного окна.

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

Настало время отобразить все на экране. Мы создаем одно окно, которое располагается между трех панелей (состояния, заголовка и cba). Это дочернее окно, и бОльший объем работы мы будем проводить именно с ним. Чтобы убедиться в правильности работы окна, разместим не нем картинку с FreEPOC logl. Детально работу с графикой мы рассмотрим в следующем разделе, пока же я позволю себе оставить команды по работе с графикой необъясненными.

Главная часть приложения

Выше мы уже рассматривали простой цикл. В данном примере тоже используется два вложенных DO...UNTIL цикла. Этот прием полезен для приложений, которые выполняются "уровень за уровнем". Внешний цикл может выглядеть как-то так:

exit%=0
DO
load_the_next_level:
initialise_level:
level_completed%=0
DO
play_the_game:
UNTIL level_completed%=1
UNTIL exit%=1
 
 

Такой подход позволяет получить компактное приложение с хорошо выраженной структурой.

Главный цикл

Я не представляю как в двух словах объяснить этот материал. Лучшее что Вы можете сделать - понять что происходит и оставить все как есть.

Системные команды

Первым делом программа смотрит, требовал ли компьютер выполнить какое-либо действие. Компьютер передает сообщение в виде строки текста. Получить его можно так:

c$=GETCMD$

Нас будут в первую очередь интересовать три события.

IF LEFT$(c$,1)=KGetCmdLetterExit$
Exit:
 

Это сообщение требует немедленно закрыть приложение. Вы можете воспользоваться командой STOP для аварийного закрытия приложения, однако более правильно было бы самостоятельно организовать закрытие приложение с сохранение всех необходимых данных, именно поэтому мы вызываем процедуру Exit:

ELSEIF LEFT$(c$,1)=KGetCmdLetterBackup$
Exit:
 
 

Данное сообщение информирует приложение о начале выполнения операции резервного копирования системы. Приложение закрывается аналогичным образом.

ELSEIF LEFT$(c$,1)=KGetCmdLetterBroughtToFGround$

Программа снова получила управление. Необходимо перезагрузить переменные и обновить экран.

Обработка нажатия клавиш

Система решает, было ли нажатие клавиши, которое необходимо обработать. Если было, вызывается процедура обработки g_kbddrv:.

Нажатие CBA кнопок

Если была нажата CBA кнопка, вызывается XXXXX-CBA подпрограмма, определяется какая кнопка была нажата и в зависимости от результата вызывается связанная с ней процедура. Это call-back функция, поэтому Вы не можете завершить из нее приложение. В связи с этим возникают проблемы при нажатии кнопки CLOSE.

Обработка нажатий клавиш (g_kbddrv:)

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

Первые секции опрашивают состояние служебных клавиш, таких как Shift, Ctrl, Fn. Следующая строка регистрирует нажатие клавиши menu. Если эта кнопка была нажата, вызывается процедура g_menu:, которая вернет нам соответствующую выбранному пункту горячую клавишу.

Рассмотрим также два специальных события: переключение Инфракрасного порта в состояние вкл/выкл и запрос помещения ярлыка на рабочий стол. Вы должны добавить их в Menu. Как видите эти две процедуры не входят в состав нашего примера. В самом начале примера происходит подключение нескольких файлов:

INCLUDE"AppFrame.oxh"
INCLUDE"System.oxh"
INCLUDE"DBase.oxh"
INCLUDE"SendAs.oxh"
 
 

Это OPL Extension Header файлы, которые ссылаются на OPX объекты - небольшие куски откомпилированного C++ кода, которые могут вызываться из OPL программы. OPX обычно работает напрямую с процессором. После подключения (INCLUDE) с OPX процедурами можно работать в обычном для OPL режиме.

Более подробно с OPX мы познакомимся позже, а сейчас давайте займемся обработкой конкретных клавиш. Приведенный ниже код проверяет, была ли нажата клавиша "A".

ELSEIF Key&amp;=%A
g_About:
 
 

Обратите внимание на два момента. Во-первых, перед буквой A стоит символ %. Поскольку Key& - числовая переменная, она не может сравниваться со строкой. Знак процента перед буквой возвращает ее код (%A=97). Вы, конечно, могли сразу сравнить Key& с 97, но согласитесь, что предложенная конструкция более наглядна. Во-вторых, %A и %a - это не одно и то же, поскольку заглавные и строчные буквы имеют различные коды.

Процедура меню

Работать с меню очень просто. Сначала мы должны инициализировать меню. Для этого используется команда mINIT. После этого мы с помощью mCARD создаем пункты меню первого уровня.

mCARD"File","Create new file...",%n,"Open File",%o
 

Первая строка определяет заголовок меню, следующие пары строк определяют название пункта меню и его горячую кнопку. Обратите внимание на знак % перед буквами.

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

Если Вы хотите создать многоуровневое меню, создайте сначала все подменю, а затем сошлитесь на них при создании главного меню с помощью символа ">":

mCASC"Databases","Create",%c,"Query...",%u
mCARD"File","Databases>",16
 

Число 16 соответствует стрелке.

Завершение

Для того чтобы остановить OPL приложение достаточно выполнить команду STOP. Однако перед завершением необходимо выполнить несколько операций (процедура exit:). В частности надо сохранить настройки пользователя и закрыть все созданные графические окна. Только после этого можно вызывать команду STOP.

Подведем итог

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


Это вольный перевод статьи"Part 2: Understanding the Event Core" By Ewan Spence.
Перевод:aRix




Наши соцсети

Подписаться Facebook Подписаться Вконтакте Подписаться Twitter Подписаться Google Подписаться Telegram

Популярное

Ссылки

Новости [1] [2] [3]... Android/ iOS/ J2ME[1] [2] [3]) Android / Архив

Рейтинг@Mail.ru Яндекс.Метрика
MobiLab.ru © 2005-2018
При использовании материалов сайта ссылка на www.mobilab.ru обязательна