WIN320 — оконный интерфейс
WIN320.DLL — библиотека простого оконного интерфейса для Sprinter в режиме
#81 (320×256, 256 цветов). Это не фреймворк: библиотека даёт набор готовых
блоков — панели, кнопки, поля ввода, списки, скроллбары, прогрессбары,
иконки, чекбоксы и радиокнопки, — из которых приложение на ассемблере,
C (SDCC) или Turbo Pascal собирает интерфейс в стиле GFX Viewer /
Flex Navigator. Рисует всё аппаратный акселератор Sprinter, но это деталь
реализации, а не часть интерфейса.
Общие правила загрузки DLL — в обзоре библиотек.
Два способа работы
Заголовок раздела «Два способа работы»- Декларативный — контролы описываются структурами, ссылки на них
собираются в массив
WinItem[], массив — в окноWinWindow. Окно рисуется одним вызовомwin_draw, а дальше обновляется точечно: приложение меняет состояние контрола, ставит флагWIN_IT_DIRTYи вызываетwin_update— перерисовываются только изменённые элементы. - Императивный — те же структуры передаются напрямую в
win_button,win_panel,win_labelи т. д., без окна и массивов.
Структуры в обоих путях одинаковы: описание кнопки из окна без изменений работает и в прямом вызове.
Быстрый старт (ассемблер)
Заголовок раздела «Быстрый старт (ассемблер)» include "win320.inc"
ld bc,#0050 ; DSS SETVMOD ld a,#81 ; режим 320x256x256 включает приложение rst #10
ld hl,dll_name ; "WIN320.DLL",0 ld a,3 ; DLL — в окно WIN3 call LIBMAN.l_load jp c,load_error ld (dll_handle),hl ; шрифт уже загружен из хвоста DLL
; палитра GUI + очистка экрана цветом рабочего стола ld e,WIN_STYLE_PALETTE|WIN_STYLE_CLEAR ld d,#FF ; #FF = цвет рабочего стола из темы ld b,WIN_STYLE call api jr nz,win_error ...api: ld hl,(dll_handle) call LIBMAN.l_call ; аргументы: A, DE, IX, IY ret c ; CF — ошибка диспетчера libman or a ; ZF по статусу WIN320 retРазбор: приложение включает режим само, загружает DLL в WIN3 (код, данные и
стек лучше держать в WIN0–WIN2) и первым делом вызывает win_style — тот
ставит палитру GUI и заливает экран. Без палитры любой цвет выводится
чёрным, поэтому этот вызов обязателен. Обёртка api — типовой приём: один
раз пишем проверку двух уровней ошибок (CF диспетчера и статус в A,
0 — успех, #20..#28 — коды WIN_ERR_*).
Координаты и тема
Заголовок раздела «Координаты и тема»Каждая рисуемая структура начинается одинаковым заголовком: x, y,
width, height. Координаты отсчитываются от начала отсчёта — по
умолчанию это угол экрана, а при рисовании окна — угол окна. Поэтому диалог
перемещается правкой двух полей WinWindow.x/y, без пересчёта координат
контролов.
Цвета почти никогда не задаются явно: значение #FF в любом цветовом поле
означает «взять из темы». Тема — 18 цветовых ролей (свет и тень 3D-рамок,
тело панелей, фон рабочего стола, текст, поле ввода, выделение, заголовок
окна…), задаётся одним вызовом win_set_theme — и весь интерфейс
перекрашивается.
Декларативное окно
Заголовок раздела «Декларативное окно»window: dw 32,20,256,216 ; x, y, ширина, высота db #FF ; цвет тела — из темы db 0 ; флаги окна db 7 ; число объектов db 2 ; индекс объекта с фокусом dw items ; массив WinItem[] dw title ; заголовок (0 — без полосы заголовка) db #FF ; цвет заголовка — из темы db 0 ; служебное поле
items: ; 8 байт на запись: тип, флаги, id, указатель, user_data db WIN_T_BUTTON, WIN_IT_HIT|WIN_IT_FOCUSABLE|WIN_IT_PRESS db ID_OK dw ok_button ; -> структура WinButton dw 0 ...win_draw рисует окно целиком; win_update перерисовывает только записи с
флагом WIN_IT_DIRTY (и снимает его). Типовой цикл: обработать событие →
изменить состояние контрола → поставить dirty → win_update.
Окно может иметь заголовок с кнопкой закрытия (WinWindow.title +
флаг WIN_WND_CLOSE) — полоса рисуется автоматически, а полный клик по
кнопке закрытия приходит событием WIN_EV_CLOSE.
Модальные диалоги
Заголовок раздела «Модальные диалоги»win_open сохраняет фон под окном в страницы памяти, выделенные приложением
(win_set_backstore), и рисует окно; win_close восстанавливает фон.
Стек до четырёх вложенных окон, строго «последним открыт — первым закрыт».
При ошибке в списке объектов win_open откатывается атомарно — частично
нарисованный диалог на экране не остаётся.
События
Заголовок раздела «События»Два способа опроса, оба через структуру WinTrack (принадлежит приложению):
win_poll— одна неблокирующая итерация: события нет — вернулсяWIN_EV_NONE, можно заняться фоновой работой;win_track— блокирует до события (с флагомWIN_TRK_HALT— экономно, черезHALT).
События: клики левой/правой кнопкой, автоповтор, hover/уход курсора, горячие
клавиши из таблицы WinKey[], произвольные клавиши, смена фокуса, изменение
чекбокса/радио, клик мимо всех объектов, кнопка закрытия окна. Вместе с
событием приходят индекс и id объекта, подобласть (например, стрелка
скроллбара или строка списка) и координаты мыши.
Фокус клавиатуры обслуживает библиотека: Tab/Shift+Tab обходят объекты с
флагом WIN_IT_FOCUSABLE, Enter нажимает сфокусированную кнопку, Space
переключает чекбокс, стрелки ходят по радиогруппе.
Драйвер мыши инициализирует приложение (BIOS RST #30, C=0) — библиотека
только опрашивает его и управляет курсором.
Контролы
Заголовок раздела «Контролы»- Поле ввода (
win_edit) — модальное редактирование прямо в буфере приложения: курсор, Backspace/Delete, Home/End, переход по словам Ctrl+←/→, откат по Esc, позиционирование кликом, режим пароля. - Listbox — строки либо массивом указателей, либо в страницах памяти (до 5461 записи); перерисовка дифференциальная, сдвиг на строку — быстрым аппаратным скроллом.
- Скроллбар — сам пересчитывает ползунок из
first/visible/total; стрелки обслуживаются контролом, hit-test сообщает подобласть. - Прогрессбар — единица — процент; перерисовывается только разница.
- Иконки — 8×8 и 16×16 из страниц памяти приложения, с аппаратной
прозрачностью
#FF; упаковщикwiniconpack.pyсобирает их из PNG/BMP. - Чекбокс и радиокнопки — состояние, эксклюзивность группы, реакция на
мышь и клавиатуру — всё внутри библиотеки, приложению приходит готовое
WIN_EV_CHANGE.
Пример (C, SDCC)
Заголовок раздела «Пример (C, SDCC)»static win_button_t ok = {40, 154, 72, 20, 0xff, 0, 0}; /* x,y,w,h,attr,flags,text */static win_item_t items[7];static win_window_t window = {32, 20, 256, 216, 0xff, 0, 7, 2, 0, 0xff, 0};static win_track_t track;
win320_bind(handle); /* привязать обёртки к DLL */win320_set_text_format(WIN_TXT_ASCIIZ);win320_draw(&window); /* нарисовать окно целиком */for (;;) { if (win320_poll(&track)) break; /* ошибка ABI */ if (track.event == WIN_EV_NONE) continue;/* фоновая работа здесь */ if (track.id == ID_CANCEL) break; items[STATUS_INDEX].flags |= WIN_IT_DIRTY; win320_update(&window, &drawn); /* перерисовать только dirty */}В поставке один и тот же диалог реализован трижды — dialog.asm, dialog.c
и DIALOG.PAS — удобно сравнивать языки. Для Turbo Pascal есть записи и
хелперы LibCall, а формат строк переключается на «байт длины» вызовом
win_set_text_format, так что поля ввода работают прямо со string[n].
Ограничения
Заголовок раздела «Ограничения»- Приложение само включает режим
#81и само переключает видимый экран; библиотека умеет рисовать в любой из двух буферов (win_set_screen). - Данные вызова не должны лежать в окне DLL: на время вызова там подключена
сама библиотека. Изменяемые структуры (окно, буфер редактирования,
WinTrack) — в записываемой RAM, в C их нельзя объявлятьconst. - Библиотека нереентерабельна: не вызывать из обработчиков прерываний.
- Не печатать через консоль DSS в графическом режиме (см. обзор).
Состав поставки
Заголовок раздела «Состав поставки»| Файл | Назначение |
|---|---|
WIN320.DLL |
библиотека; шрифт вшит в хвост файла |
win320.inc |
константы и смещения полей для sjasmplus |
bind/win320.h, bind/win320.lib |
заголовок и обёртки для C (SDCC) |
bind/WIN320.INC |
записи и хелперы для Turbo Pascal |
examples/dialog.asm, dialog.c, DIALOG.PAS |
один диалог на трёх языках |
tools/winiconpack.py |
упаковщик иконок PNG/BMP |
WIN320.EXE |
визуальный тест; приложениям не нужен |