Адрес: ул. Б. Очаковская 32 Москва Россия
Наши официальные канал и чат в telegram, группа в ВКонтакте

Yabasic: работа с клавиатурой, мышью и графикой — шпаргалка и типовые ошибки

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

Разговоры на любые темы касающихся языка Бейсик и его диалектов. Общение с администрацией и прочее
Аватара пользователя
Anton
Site Admin
Сообщения: 141
Зарегистрирован: Чт фев 08, 2024 7:03 pm
Откуда: Москва

Yabasic: работа с клавиатурой, мышью и графикой — шпаргалка и типовые ошибки

Сообщение Anton »

Yabasic: работа с клавиатурой, мышью и графикой — шпаргалка и типовые ошибки
  1. Инициализация графического режима: обязательная последовательность

    Перед любым взаимодействием с клавиатурой или мышью (даже в открытом графическом окне!) необходимо вызвать clear screen. Без этого inkey$ или inkey$(timeout) упадут с ошибкой “need to call 'clear screen' first”.

    Правильный порядок запуска:

    Код: Выделить всё

    open window width, height
    clear screen          ← строго перед первым inkey$
    backcolor r,g,b
    clear window          ← очистка самого окна
    ... дальше можно рисовать и ждать клавиши/мышь
    Если программа возвращается в главное меню через goto restart, перед меткой restart снова вставьте clear screen (иначе при повторном входе будет та же ошибка).
  2. Работа с клавиатурой в графическом окне

    В Yabasic есть два режима чтения клавиш:
    • Блокирующийinkey$ без аргументов. Останавливает выполнение и ждёт нажатия любой клавиши. Возвращает строку, описывающую клавишу (например, "a", "enter", "f1", "backspace"). Используется, когда программа должна ждать действия пользователя (поле ввода, пауза).
    • Неблокирующийinkey$(timeout). Ждёт не дольше timeout секунд, если ничего не нажато – возвращает пустую строку "". Нужен для циклов опроса, чтобы параллельно рисовать или проверять мышь.
    Главная проблема, выявленная на практике: Enter в графическом окне иногда «залипает» или не ловится при коротком нажатии, особенно после предыдущих вызовов inkey$.

    Надёжный рецепт для поля ввода (пошагово):
    1. Перед входом в цикл ввода очистить буфер клавиатуры от «застрявших» кодов: while inkey$(0.01) <> "" : wend
    2. Внутри цикла использовать блокирующий inkey$ (без таймаута) – он гарантированно дождётся физического нажатия.
    3. Проверять клавишу и по имени, и по коду (для надёжности в разных ОС и версиях Yabasic):
      • Enter: char$ = "enter" или char$ = chr$(13)
      • Backspace: char$ = "backspace" или char$ = chr$(8)
    4. Запрещать пустой ввод: если буфер пуст и нажат Enter, издать beep и не выходить из цикла.
    5. После набора числа один Enter мгновенно завершает ввод.
    Этот подход полностью устранил «кучу нажатий Enter» и неработающий Backspace.
  3. Обработка мыши

    Мышиные события поступают только через inkey$ с тайм-аутом (блокирующий вызов мышь не обрабатывает). При движении или клике функция возвращает строку вида "MB1d+0:0123,0456" (левая кнопка нажата, координаты).

    Канонический цикл опроса мыши:

    Код: Выделить всё

    while условие
        k$ = inkey$(0.1)                // небольшой таймаут для отзывчивости
        if left$(k$, 2) = "MB" then
            b = mouseb(k$)              // положительное = нажата, отрицательное = отпущена
            x = mousex(k$)
            y = mousey(k$)
            if b = 1 then               // реагируем только на нажатие левой кнопки
                if точка(x,y) внутри_кнопки then действие
            endif
        endif
    wend
    Особенности:
    • События приходят при каждом движении мыши, даже без клика. Поэтому проверяйте b = 1, иначе действие будет срабатывать на движение.
    • Функции mousex, mousey, mouseb без аргументов работают только с последней строкой от inkey$. Лучше всегда передавать им ту строку, которую вы только что получили.
    • Таймаут 0.1 (или даже 0.05) даёт хорошую реакцию на клики и не перегружает процессор.
  4. Графические примитивы и текст

    Рисование:
    • line, rectangle, circle, fill rectangle, clear rectangle и т.д. – всё работает как в справочнике.
    • Перед заливкой задавайте цвет через color r,g,b.
    • Для фона окна сначала установите backcolor r,g,b, затем clear window (или clear window заполнит фон заданным цветом).
    • Начало координат по умолчанию – левый верхний угол. Можно изменить через window origin "cc".
    Вывод текста:
    • Команда text x, y, "строка", "выравнивание", "шрифт"обратите внимание на скобки! В отличие от многих языков, text не оборачивается в скобки. Лишняя ) в конце строки вызывает трудноуловимые синтаксические ошибки (типа пропажи endif).
    • Выравнивание – двухсимвольная строка: первый символ по горизонтали (l, c, r), второй по вертикали (t, c, b). Например, "cc" – центр по обоим осям.
    • Шрифты: используйте имена без суффиксов типа b (bold) или i (italic) – они не поддерживаются. Правильно: "swiss14", "swiss24", "swiss12". Размер указывается после названия гарнитуры слитно (swiss14). Если шрифт не найден, берётся системный по умолчанию.
    Форматирование чисел:
    • Для вставки числа в строку: str$(число, "###,###,###", " ,") – формат с обязательным указанием разделителя групп. Второй аргумент – шаблон: # обозначает цифру, запятая в шаблоне – это символ разделителя тысяч (будет заменён на пробел из третьего аргумента). Шаблон должен быть достаточно длинным, иначе Yabasic выведет # вместо цифр. Для чисел до 999 миллионов используйте "###,###,###".
    • Формат с плавающей точкой: str$(rate, "%.2f") – стандартный C‑формат.
    • print using "########.00"; number требует точку с запятой после строки формата, а не запятую (это частая ошибка). В графическом режиме print using неактуален, используйте str$.
  5. Построение GUI из подручных средств

    Кнопка:
    1. Нарисовать прямоугольник fill rectangle x1,y1, x2,y2 с цветом кнопки.
    2. Вывести текст по центру: text (x1+x2)/2, (y1+y2)/2, "Надпись", "cc", "swiss14b" (используйте простой шрифт без b, но bold не критичен – он игнорируется, шрифт останется обычным).
    3. Для проверки попадания мыши написать функцию: if mousex >= x1 and mousex <= x2 and mousey >= y1 and mousey <= y2 then return true
    Переходы между экранами:
    • Удобно использовать метку restart и команду goto restart для возврата в главное меню.
    • Важно: перед меткой restart обязательно вызвать clear screen, затем clear window и перерисовать всё меню. Иначе inkey$ в главном цикле откажется работать.
    Ожидание действия в конце расчёта: После вывода результатов рисуйте кнопки и входите в бесконечный цикл опроса мыши с небольшим inkey$(0.1). При клике на Back – goto restart, на Exit – close window + end.
  6. Синтаксические ловушки и частые ошибки
    1. Лишние закрывающие скобки в texttext 60, 100, "Hello", "lc", "swiss14") ← ошибка! Интерпретатор запутается и выдаст что-то вроде «a closing endif is expected before wend». Убирайте скобку в конце.
    2. Запятая вместо точки с запятой в print usingprint using "###.##", x – неверно. Правильно: print using "###.##"; x.
    3. Пропущенный clear screen – любой вызов inkey$ (даже в графическом режиме) требует предварительного clear screen. Иначе программа упадёт.
    4. Однострочный if в цикле без then/endif – хотя Yabasic разрешает однострочный if, в сложных циклах лучше всегда использовать многострочный вариант с endif, чтобы парсер не путал блоки. Например, if условие then действие endif на отдельных строках.
    5. Недостаточный размер форматной строки в str$ – если число не влезает в шаблон, выводятся символы #. Увеличьте количество # в формате.
    6. Кодировка файла с русским текстом – Yabasic под Windows понимает только кодировку ANSI (Windows‑1251). Если файл сохранён в UTF‑8, русские буквы превратятся в нечитаемые символы или вызовут синтаксическую ошибку. При использовании русского языка обязательно сохраняйте .yab-файл в ANSI. Английский текст работает в любой кодировке.
  7. Типовой шаблон для графического приложения

    Код: Выделить всё

    open window W, H
    clear screen
    backcolor фоновый_цвет
    clear window
    
    label main
        clear screen
        clear window
        рисовать_меню()
        mode = 0
        while mode = 0
            k$ = inkey$(0.1)
            if left$(k$,2)="MB" then
                b = mouseb(k$) : x = mousex(k$) : y = mousey(k$)
                if b=1 and inside(кнопка1) then mode=1
                if b=1 and inside(кнопка2) then mode=2
                if b=1 and inside(выход) then close window : end
            endif
        wend
        if mode=1 then подпрограмма_вклада()
        if mode=2 then подпрограмма_ипотеки()
        goto main
    end
    В каждой подпрограмме:
    • clear window
    • Вывести заголовки и поля ввода (через свою функцию input_number).
    • Выполнить расчёт, вывести результаты с кнопками Back/Exit.
    • Войти в цикл мыши, аналогичный главному, где Back отправляет на goto main.
  8. Резюме

    Ключ к быстрой разработке на Yabasic — соблюдение чёткой последовательности инициализации, использование блокирующего inkey$ для ввода и неблокирующего для опроса мыши, аккуратность с синтаксисом text/print using и внимательность к кодировкам. Язык не прощает вольностей, но если следовать этим правилам, можно создавать симпатичные оконные утилиты без внешних библиотек и сложных фреймворков.