При разработке интерфейсов в «1С:Предприятие 8» перед программистом часто встает задача оптимизации юзабилити (удобства использования) формы. Типичный сценарий: пользователю необходимо быстро ввести последовательность фиксированных данных — например, код страны, код оператора и номер телефона, разнесенные по разным полям, либо серийный номер прибора, состоящий из нескольких сегментов. Заставлять пользователя каждый раз нажимать клавишу Enter или Tab для перехода к следующему полю неудобно и замедляет работу.
В этой статье мы подробно разберем, как реализовать автоматический переход на следующее поле ввода в управляемых формах сразу после того, как текущее поле заполнилось до предела. Мы рассмотрим особенности работы платформенных событий, разберем изящное решение через обработчики ожидания и проанализируем альтернативные варианты, включая эмуляцию клавиш ОС и специфику работы на мобильных клиентах.
Прежде чем перейти к написанию кода, давайте разберем физику процесса ввода данных в управляемых формах. Когда пользователь набирает символы в поле ввода, эти данные еще не записаны в связанный реквизит формы. Они находятся в так называемом буфере редактирования элемента управления. Запись в реквизит и срабатывание события ПриИзменении происходят только тогда, когда элемент управления теряет фокус (например, при нажатии Tab, Enter или клике мышью в другое место).
Следовательно, использовать событие ПриИзменении для автоматического перехода невозможно, так как оно само по себе требует этого самого перехода. Нам нужно событие, которое срабатывает на каждый чих пользователя — то есть при вводе каждого отдельного символа. Таким событием является ИзменениеТекстаРедактирования.
Рассмотрим базовый сценарий. У нас есть поле ввода на форме, предназначенное для ввода кода оператора связи (ровно 3 символа). Назовем его КодОператора. Следующее поле ввода называется НомерТелефона.
Для реализации перехода выполним следующие шаги по шагам:
КодОператора в конфигураторе.ИзменениеТекстаРедактирования и нажмем на лупу для создания обработчика на клиенте.Давайте посмотрим на пример реализации процедуры обработчика:
&НаКлиенте
Процедура КодОператораИзменениеТекстаРедактирования(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, СтандартнаяОбработка)
// Проверяем длину введенного текста. Нам нужно ровно 3 символа.
Если СтрДлина(Текст) = 3 Тогда
// Пробуем передать фокус на следующее поле
ЭтаФорма.ТекущийЭлемент = Элементы.НомерТелефона;
КонецЕсли;
КонецПроцедуры
Важное примечание: Обратите внимание, что в коде анализируется переменная Текст, которая передается в параметры процедуры платформой, а не сам реквизит формы. Попытка проверить длину через СтрДлина(Объект.КодОператора) вернет неверный результат (или пустую строку), так как значение реквизита еще не обновилось.
При тестировании вышеописанного простого кода вы можете столкнуться с неприятной особенностью платформы 1С. В момент смены фокуса через присвоение ЭтаФорма.ТекущийЭлемент внутри события изменения текста, системный поток ввода еще обрабатывает нажатие последней клавиши. Это может приводить к следующим багам:
Чтобы обойти это ограничение, мы применим профессиональный прием — однократный обработчик ожидания с минимальным таймаутом. Это позволит платформе корректно завершить все внутренние процессы отрисовки текущего поля и лишь затем, в микропаузе, переключить фокус.
Давайте разберем по шагам правильную архитектуру этого решения:
Посмотрим на пример программного кода:
&НаКлиенте
Перем ИмяСледующегоЭлементаФормы; // Переменная модуля для хранения цели перехода
&НаКлиенте
Процедура КодОператораИзменениеТекстаРедактирования(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, СтандартнаяОбработка)
// Задаем лимит символов для текущего поля
ПредельнаяДлина = 3;
Если СтрДлина(Текст) >= ПредельнаяДлина Тогда
// Запоминаем, куда нам нужно перейти
ИмяСледующегоЭлементаФормы = "НомерТелефона";
// Подключаем однократный обработчик ожидания с задержкой 0.1 секунды
ПодключитьОбработчикОжидания("ВыполнитьПереходНаСледующееПоле", 0.1, Истина);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьПереходНаСледующееПоле() Экспорт
// Проверяем, заполнено ли имя целевого элемента
Если ЗначениеЗаполнено(ИмяСледующегоЭлементаФормы) Тогда
Попытка
// Устанавливаем фокус на целевой элемент
ЭтаФорма.ТекущийЭлемент = Элементы[ИмяСледующегоЭлементаФормы];
Исключение
ЗаписьЖурналаРегистрации("Интерфейс", УровеньЖурналаРегистрации.Предупреждение, , ,
"Не удалось перейти на элемент: " + ИмяСледующегоЭлементаФормы);
КонецПопытки;
// Очищаем переменную, чтобы избежать повторных ложных срабатываний
ИмяСледующегоЭлементаФормы = "";
КонецЕсли;
КонецПроцедуры
Этот подход гарантирует стабильное поведение интерфейса на любых компьютерах, независимо от их производительности и загруженности процессора.
Существует альтернативный способ, который избавляет разработчика от необходимости жестко прописывать имена следующих элементов в коде формы. Если на вашей форме правильно настроен порядок обхода (свойство элементов формы ПорядокОбхода), то переход к следующему полю логично выполнять так же, как это делает клавиша Tab.
Для этого мы можем использовать возможности операционной системы Windows и отправить виртуальное нажатие клавиши в активное окно приложения.
Рассмотрим пример реализации этого метода:
&НаКлиенте
Процедура КодОператораИзменениеТекстаРедактирования(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, СтандартнаяОбработка)
Если СтрДлина(Текст) = 3 Тогда
#Если ТонкийКлиент Или ТолстыйКлиент Тогда
Попытка
// Создаем COM-объект для работы с оболочкой Windows
WshShell = Новый COMОбъект("WScript.Shell");
// Отправляем команду нажатия клавиши TAB
WshShell.SendKeys("{TAB}");
Исключение
// Обработка исключения, если COM-объект заблокирован политиками безопасности
ЭтаФорма.ТекущийЭлемент = Элементы.НомерТелефона;
КонецПопытки;
#Иначе
// Резервный вариант для веб-клиента или других ОС
ЭтаФорма.ТекущийЭлемент = Элементы.НомерТелефона;
#КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важное предупреждение: Данный метод является платформозависимым. Он отлично зарекомендовал себя в корпоративных сетях на базе ОС Windows под управлением Тонкого или Толстого клиента 1С. Однако он совершенно недееспособен в Web-клиенте (через браузеры), на рабочих станциях под управлением Linux, macOS, а также на мобильных устройствах.
Чтобы автоматизация выглядела завершенной и не вызывала раздражения у операторов ввода, обязательно обратите внимание на следующие сопутствующие свойства целевых полей ввода:
НомерТелефона), установите это свойство в значение Истина или Авто. Это позволит пользователю сразу же начать набирать цифры без необходимости совершать дополнительный клик мышкой для активации текстового курсора внутри поля.Истина. При переходе фокуса старый текст автоматически выделится, и первый же нажатый символ сотрет его.Если вы разрабатываете мобильное приложение на платформе «1С:Предприятие», автоматический переход по полям требует повышенной осторожности. На мобильных устройствах программная смена фокуса заставляет операционную систему скрывать экранную клавиатуру для старого поля и мгновенно инициализировать ее для нового.
Это может приводить к визуальному «морганию» экрана, микрофризам интерфейса и непроизвольному сворачиванию клавиатуры. На мобильной платформе рекомендуется:
Мы детально разобрали все нюансы реализации автоматического перехода между элементами управляемой формы 1С. Использование события ИзменениеТекстаРедактирования в связке с микро-обработчиком ожидания является наиболее надежным, кроссплатформенным и безопасным решением для любых прикладных задач.