ГИ ЭКВМ, создание одноуровневого меню


Главная / ЭКВМ / Программы / Примеры

Описание графического интерфейса пользователя (ГИ) следует предварительно изучить по документации. Если кратко, в программе ГИ представляет собой набор структур, связанных описанием переходов между ними и требуемых действий по обработке команд. Структуры (экранные формы) пронумерованы и перечислены в главной таблице меню.

Вид экрана ЭКВМ для пользователя программ с использованием ГИ может быть весьма разнообразным и зависит от комбинации элементов форм и связанных с ними программ обработки. Фактически, он ограничен только вычислительными возможностями ЭКВМ и фантазией самого программиста.

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

Разрешение графического интерфейса (R9200)

Перед началом работы с ГИ необходимо записать число 1 в регистр 9200. Специально запрещать работу ГИ, как правило, не требуется - достаточно не обращаться к его функциям.

Адрес главной таблицы меню (R9201)

Перед началом работы с интерфейсом следует записать адрес главной таблицы в R9201. Изменять его нет необходимости, хотя это и возможно. Таблица состоит из трёхбайтовых записей, содержащих номер формы и адрес начала в памяти. Должна быть ограничена байтом 0FFh в поле номера формы.

Указатели экранной формы (R9202, R9203)

Определяют номер загруженной формы и номер активного элемента. Могут изменяться автоматически при работе ГИ, но могут быть перезаписаны и напрямую - командами РР П 9202, РР П 9203. Изменение значений в программе требуется в том случае, когда команды, связанные с перемещением по системе меню, совершают дополнительные действия (различные проверки, обработка или запись введённых значений и т.п.) и обрабатываются отдельными подпрограммами.

Перед началом работы с ГИ следует записать номер формы и элемента, которые должны быть выбраны при запуске программы.

Регистр действий экранной формы (R9204)

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

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

Период автоматического обновления экрана (R9206)

Имеет значение, если у активного в данный момент элемента установлен соответствующий флаг действия.

Автоматическое обновление удобно, например, при отображении результатов каких-либо измерений: единственное обращение к R9208 ГИ позволит непрерывно обновлять данные с заданной в R9206 периодичностью.

Адрес регистра для ввода числа (R9207)

Используется при вводе чисел через ГИ с использованием экранных форм встроенного программного обеспечения ЭКВМ (далее - ПО) с номерами 253 и 254 (F253, F254). Содержимое указывает номер регистра от 0 до 999 в который будут записаны данные, вводимые через эти формы.

Значение может быть записано в программе командой РР П 9207 или непосредственно в форме, командой LDADR (4Dh). Команда LDADR, как правило, заносится в программу элемента формы, для которого таблица переходов по команде ВВОД содержит переход к F253,0 или F254,0.

Регистр команд интерфейса (R9208)

В этот регистр заносятся значения кодов команд (совпадающих со скан-кодами соответствующих кнопок) которые передаются в форму для обработки: ВЫХОД (32), ВВОД (33), ВЫБОР (34-37). Специальный код 64 вызывает перерисовку формы.

Коды цифровых клавиш 0-F для F253 или 0-9, запятой, минуса, Cx и ВП для F254 передаются в указанные формы встроенного ПО для ввода числовых значений. Проверить необходимость передачи этих кодов можно сравнением содержимого указателя R9202 с номерами указанных форм.

Действия по нажатию каких-либо клавиш (кроме ВЫХОД, ВЫБОР и ВВОД) вне форм ввода числа, если это необходимо, должны определяться в программе специально. Вместо кодов клавиш в R9208 при этом записывается код 64 для перерисовки формы.

Регистр результата выполнения операции (R9209)

Анализируется после записи команды в R9208. При нулевом значении каких-либо дополнительных действий не требуется - как правило, это означает автоматический переход между формами и элементами в системе меню.

При значении 1 следует определить какая команда (R9208), для какого элемента (R9203) и в какой форме (R9202) вызвала требование продолжения обработки. Возврат значения 1 также подразумевает, что действия по обработке интерфейса, включая изменение номера текущей формы и активного элемента, ожидаются от программы, а не совершаются ГИ автоматически.

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

Значения от 2 до 6 не должны возникать в отлаженной программе и означают ту или иную ошибку при программировании интерфейса.

Значение 7 возникает при возврате из формы встроенного ПО (F253 или F254) в ту форму, из которой они были вызваны. Проверка кода может требоваться для совершения каких-либо дополнительных действий, кроме автоматически совершаемой записи числа в регистр. Например, для приведения числа к нужному виду, для ограничения разрядности или диапазона вводимых значений и т.п. В программах не использующих ввода чисел через F253 и F254 значение 7 возникать не может и должно обрабатываться наряду с ошибками ГИ.



Структура программ, использующих ГИ

При организации одноуровневой или иерархической системы меню работа с ГИ состоит в проверке нажатых клавиш (R9029), передачи их кода в функцию R9208, что вызывает перерисовку формы на графическом экране, и проверке результата выполнения через R9209. Эти действия производятся циклически. Остальные необходимые действия в программе совершаются по условиям в зависимости от содержимого R9209 и указателей R9202, R9203.

Команды интерфейса, связанные с переходом по условиям или косвенными обращениями к памяти данных, позволяют произвольно изменять структуру и вид меню во время выполнения программы.

Программы, требующие вывода списков с изменяемым содержимым - например, файловые менеджеры - могут использовать команду вывода строки с косвенной адресацией TXTK (57h) или вывода строки из памяти двоичных данных TXTB (55h). Разумеется, программа предварительно должна сформировать текстовые строки в нужной области памяти.

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

Программы, требующие вывода динамических изображений - например, игровые - предполагают использование команд загрузки графических координат из регистров данных - LDX (68h) и LDY (69h). Неизменяемые изображения можно выводить при помощи команд DRAWP (54h) и DRAWB (56h). Путём определения собственного шрифта со спрайтами, используя команды TYPE (65h), ATYPE (4Eh) и команды вывода строки с косвенной адресацией TXTK (57h) можно создавать динамические анимированные изображения. Комбинация различных атрибутов графического вывода позволяет накладывать изображения друг на друга с учётом масок.

Имеется много разновидностей программ, структуру которых проще показать на примерах, чем описывать в общем виде. Тем более, что обычно используется комбинация различных методов работы с ГИ.

Ограничения на размер формы

Ограничение на размер формы в 256 байт, определяемое однобайтовым смещением элементов команд и таблиц, преодолевается при помощи команд вызова подпрограммы LCALL (70h) и возврата RETUL (71h). Эти команды позволяют переносить части программ ГИ в произвольное место памяти.

Для уменьшения размера формы можно рекомендовать объединение совпадающих веток программ ГИ внутри при помощи команд подпрограмм MCALL (66h), RETUM (67h) и переходов JM (38h) JNEZ (01h).

Разбор форм в ГИ выполняется достаточно быстро, однако не рекомендуется загромождать их излишними командами или избыточным числом элементов. Во многих случаях разумнее создать несколько отдельных небольших форм.


Пример программы 1

Следующий пример демонстрирует работу с ГИ в программе, выводящей одноуровневое меню с возможностью выбора одного из пунктов. Текст программы снабжён комментариями и демонстрирует основные приёмы программирования ГИ.

пример одноуровневого меню ГИ ЭКВМ

Файл программы primgui1.mkp на ЯМК - 346 байт, КС 38885/219

Текст программы primgui1.mkl для кросс-компилятора

Примечание. Вряд ли программы с ГИ имеет смысл разрабатывать без помощи кросс-средств (хотя в принципе это, конечно, возможно). Соответственно, текст программы на языке МК отдельно не приводится.

.CHARSET 1251
; Файл primgui1
; Пример работы с графическим интерфейсом пользователя
; Пример простого меню из шести пунктов
; Версия 1.2

; Регистры памяти
; RA - для временного хранения данных

; ====================================================== Начало программы
.ORG 0	
A0:	
	CX		; Обнулить RX и сбросить признак ввода числа
	2 PP M 9010	; Инициализировать графический экран

	1 PP M 9200	; 1 - разрешение графического интерфейса
	0 PP M 9202	; текущая форма - 0 
	PP M 9203	; активный элемент - 0
	.NUMT TFORM
	PP M 9201	; главная таблица форм TFORM

A1:	64		; Код принудительной перерисовки формы
A2:	PP M 9208	; Перерисовать форму
	PP RM 9209	; Результат выполнения формы

	MA		; Сохранить в RA
	P X!=0	A5	; Перейти, если не требуется обработки	

	1 - 
	P X!=0	A4	; Перейти, если требуется обработка
	
	; Далее простейшая обработка ошибки интерфейса 
	; при этом RX содержит число от 2 до 6 
	; или 7 - ввод числа, который здесь не используется 
	; и функций таблиц 
	; при этом RX содержит минус 1

A3:	.NUM STR1	; Вывести "Ошибка" в строку комментариев
	PP M 9026
	CX ENT ENT ENT	; Очистить стек
	RMA		; Вывести код в RX
	R/S		; Останов

A4:	; Обработка результата выполнения формы

	.NUMT TOF0	; Загрузить таблицу обработки элементов формы 0
	PP M 9042	; в регистр 9042 для последующей работы с функциями таблиц


	PP RM 9203	; форма единственная, обрабатывается только ВВОД
			; поэтому проверяется только номер активного элемента
	
	PP M 9211	; считать адрес подпрограммы обработки действия из таблицы 
			; по номеру элемента
			; внимание - действие выполняется по команде записи в регистр
	
	MA		; Сохранить в RA
	P X!=0	A5	; Обработчик не определён (содержит нулевой адрес) - ничего не делать
			; Эта проверка здесь лишняя, но полезна для примера
			; Таким образом можно исключать ненужные элементы в таблице

	K GSB A		; Перейти к подпрограмме обработки
	P GOTO A1	; Вернуться к перерисовке формы, поскольку подпрограмма может изменять её вид

A5:	; Опрос клавиатуры
	; Других причин для перерисовки формы здесь нет, иначе следовало проверить их 
	; и перейти к A1 при необходимости

	PP RM 9029	; Считать код клавиши
	MA		; Сохранить в RA
	K NOT		; инверсия (0FFh -> 0)
	P X!=0 A5	; если нет нажатия - продолжать опрос
	RMA
	P GOTO A2	; Передать код нажатой клавиши в форму

STR1:	.TEXT "\nОшибка\0"

TOF0:	; адреса подпрограмм для обработки нажатия ВВОД при активном элементе 0-5
	.DA OF0E0, OF0E1, OF0E2, OF0E3, OF0E4, OF0E5

OF0E0:	; Обработка команды ВВОД для элемента 0
	110		; частота
OF0E0A: ENT
	50		; продолжительность 0,5 сек
	PP M 9052	; звук - как пример действия
	RTN		; выйти из подпрограммы

OF0E1:	; Обработка команды ВВОД для элемента 1
	220
	P GOTO OF0E0A

OF0E2:	; Обработка команды ВВОД для элемента 2
	440
	P GOTO OF0E0A

OF0E3:	; Обработка команды ВВОД для элемента 3
	880
	P GOTO OF0E0A

OF0E4:	; Обработка команды ВВОД для элемента 4
	1760
	P GOTO OF0E0A

OF0E5:	; Обработка команды ВВОД для элемента 5
	3520
	P GOTO OF0E0A

;===== Главная таблица форм
TFORM:
	.DB 0	; в этой программе только одна форма (с номером 0)
	.DA F0	; адрес начала формы 0

	.DB END	; конец таблицы

;===== Форма 0
	.BASE		; смещения в таблицах и переходах указываются относительно начала формы
F0:	; Заголовок формы
	.FORM 5, F0DE, F0PI, F0PO, F0PL, F0PR, F0RI, F0KM ; таблица смещений
	; максимальный номер элемента 5 (хотя всего их 6, считая нулевой)
	; Примечание: расположение остальных полей структуры в пределах формы 
	; может быть произвольным

F0DE:	;таблица флагов действий
	.DB 13,13,13,13,13,13
	; В двоичном виде 13 это 00 00 11 01 - установлены флаги "выбор" + "ввод с обработкой" 
	; См. описание в документации.
	; Примечание: в общем случае значения могут быть различными для каждого элемента формы,
	; но здесь это не требуется
				 
F0PI:	
F0PO:	; Таблицы перехода по выходу и входу здесь объединены
	; и заполнены формальными значениями
	; поскольку команда ВЫХОД не обрабатывается, 
	; а ВВОД обрабатывается отдельно (см. флаги действий).
	; Для экономии места можно было вообще не использовать значений, даже формальных,
	; а записать в заголовке, например, нулевые смещения для этих таблиц.
	; Но это менее наглядно в примере и чревато труднораспознаваемыми ошибками 
	; при указании неверных значений флагов действий.
	.DB 0,0,0,1,0,2,0,3,0,4,0,5
	; В общем же случае по командам ВВОД и ВЫХОД возможен переход между формами, 
	; первый байт пары значений - номер формы, второй - элемента

F0PL:	; Таблица переходов по команде "Выбор влево" (и вверх)
	.DB 5,0,1,2,3,4
	; это номера элементов внутри формы - куда перейти с текущего
	; например, с 0 на 5, с 1 на 0 и т.д.

F0PR:	; Таблица переходов по команде "Выбор вправо" (и вниз)
	.DB 1,2,3,4,5,0
	; это номера элементов внутри формы - куда перейти с текущего
	; например, с 0 на 1, с 1 на 2 и т.д.

F0RI:	; основная программа экранной формы 
	.TYPE 0		; шрифт 0
	.TAB 32, 0 		; позиция (X=32,Y=0), координата Y - сверху-вниз 
	.TXTP 16, F0TZ		; TXTP - вывести строку из области памяти программ
				; атрибут 16 - перерисовка, расстояние между символами 1
				; F0TZ адрес строки с наименованием формы

	.TAB 0, 9		; позиция (0,9)
	.SQU 0, 127, 1		; прямоугольник (127,1) - это линия

	.TAB 2, 10 		; позиция (2,10)
	.TXTP 16,F0T0		; TXTP - вывести строку из области памяти программ
				; атрибут 16 - перерисовка, расстояние между символами 1
				; F0T0 - адрес строки с описанием первого пункта (т.е. нулевого элемента)

				; далее аналогично
	.TAB 2, 19 			
	.TXTP 16, F0T1

	.TAB 2, 28 
	.TXTP 16, F0T2

	.TAB 2, 37 
	.TXTP 16, F0T3

	.TAB 2, 46 
	.TXTP 16, F0T4

	.TAB 2, 55 
	.TXTP 16, F0T5

	.END			; конец основной программы

F0KM:	; Таблица смещений программ элементов команды
	; Эти программы выполняются после основной программы формы
	; и указывают на точку входа для активного элемента
	.DBB F0KM0, F0KM1, F0KM2, F0KM3, F0KM4, F0KM5

F0KM0:	.TAB 0, 10	; установить позицию (0,10) для элемента 0
	.JM F0KME	; перейти к F0KME - общей части программ
	 
			; далее аналогично
F0KM1:	.TAB 0, 19
	.JM F0KME
F0KM2:	.TAB 0, 28
	.JM F0KME
F0KM3:	.TAB 0, 37
	.JM F0KME
F0KM4:	.TAB 0, 46
	.JM F0KME
F0KM5:	.TAB 0, 55
				; из последнего элемента переходить не требуется 
				; далее общая часть программ
F0KME:	.SQU 3, 64, 9		; в указанной ранее позиции нарисовать
				; прямоугольник размером 64 на 9
				; с атрибутами 3 - XOR
				; в итоге - инверсия текста сообщения
	.END			; конец программ элементов

;======= Тексты строк к структуре формы не относятся 
;        и могут располагаться в произвольном месте памяти
		
F0TZ:	.TEXT "Пример меню\0"
F0T0:	.TEXT "Пункт 1\0"
F0T1:	.TEXT "Пункт 2\0"
F0T2:	.TEXT "Пункт 3\0"
F0T3:	.TEXT "Пункт 4\0"
F0T4:	.TEXT "Пункт 5\0"
F0T5:	.TEXT "Пункт 6\0"

.ENDP


Пример программы 2

Нетрудно заметить, что выход из предыдущей программы возможен только через нажатие "С/П". Для программы с ГИ это допустимо, но можно сделать и лучше.

Добавим к программе корректное завершение работы при нажатии клавиши "ВЫХОД". Для этого достаточно внести несколько мелких изменений.

Прежде всего при обработке результата выполнения следует проверить, какая команда выполнялась. Для этого нужно дополнить начало программы обработки считыванием содержимого R9208:

A4:	; Обработка результата выполнения формы
	; Для обработки команды ВЫХОД проверяется R9208
	PP RM 9208
	MA
	32 -
	P X!=0 A6	; Перейти к A6 при коде команды 32 - ВЫХОД
	1 -
	P X!=0 A41	; Перейти к A41 при коде команды 33 - ВВОД
	RMA
	P GOTO A3	; Перейти к ошибке - обработчик команды отсутствует
	; Примечание - можно проигнорировать, тогда вместо A3 перейти к A5
A41:

Обработка команды ВВОД в A41 выполняется так же, как и в предыдущей программе.

Дополнительно нужно составить программу обработки команды выхода:

A6:	; Действия при команде ВЫХОД
	; В этом примере обработчик будет простейшим: 
	; вывод сообщения, останов программы и перезапуск при повторном старте
	.NUM STR2	; Вывести "Выход" в строку комментариев
	PP M 9026
	R/S
	P GOTO 0

Не забыв добавить к тексту строку:

STR2:	.TEXT "\nВыход\0"

Кроме того, в таблицу флагов действий формы 0 вместо кода 13 (00001101 - выбор + ввод с обработкой) следует записать 61 (00111101 - выбор, ввод и выход с обработкой).

F0DE:	;таблица флагов действий
	.DB 61,61,61,61,61,61

Больше никаких изменений не требуется. Эта программа будет завершаться при нажатии кнопки "ВЫХОД" с выводом сообщения в строке комментариев и перезапускаться с нулевого адреса при нажатии "С/П". Размер программы увеличился всего на 37 байт, из которых 7 байт занимает текстовая строка, а ещё 7 - команды её вывода.

Файл программы primgui2.mkp на ЯМК - 384 байта, КС 33647/33

Текст программы primgui2.mkl для кросс-компилятора



Пример программы 3

Программа работает, но для перехода от одного пункта к другому иногда приходится несколько раз подряд нажимать одну из кнопок "ВЫБОР", затем "ВВОД". Это медленно и не всегда удобно. Дополним программу обработкой нажатия цифровых кнопок от "0" до "6". Причём "0" будет дублировать команду "ВЫХОД", а кнопки от "1" до "6" - вызывать переход на соответствующий пункт меню и немедленное выполнение нужного действия. За основу возьмём предыдущий пример.

Для начала требуется дополнить блок опроса клавиатуры проверкой кода клавиши на принадлежность к требуемому диапазону (добавления к программе выделены в комментариях):

A5:	; Опрос клавиатуры
	; Других причин для перерисовки формы здесь нет, иначе следовало проверить их 
	; и перейти к A1 при необходимости

	PP RM 9029	; Считать код клавиши
	MA		; Сохранить в RA
	K NOT		; инверсия (0FFh -> 0)
	P X!=0 A5	; если нет нажатия - продолжать опрос
	RMA
	;+++++++++++++++++++++++
	; Проверить, является ли считанное значение кодом цифровой клавиши от 1 до 6
	7 - 
	P X>=0 A7	; Если код клавиши от 0 до 7 - перейти к A7
	RMA		; Иначе восстановить его
	;+++++++++++++++++++++++
	P GOTO A2	; Передать код нажатой клавиши в форму

Дополнительно потребуется составить блок обработки:

A7:	; Действия при нажатии клавиш 0-6 - значение в RA
	RMA
	P X!=0 A6	; Нажатие 0 - выход
	; Вычесть единицу из номера пункта 1-6 и установить номер активного элемента 0-5
	1 -
	PP M 9203
	; Перейти на обработку команды ВВОД для установленного активного элемента формы
	P GOTO A41

Других изменений не требуется. А столь полезное дополнение увеличило размер программы всего на 18 байт.

Файл программы primgui3.mkp на ЯМК - 402 байта, КС 56517/133

Текст программы primgui3.mkl для кросс-компилятора



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


НПП "СЕМИКО" (383) 271-01-25 (многоканальный)