При разработке интерфейсов на управляемых формах 1С программисты часто сталкиваются с задачей циклического ввода данных. Типичный пример — сканирование штрихкодов на складе или в торговом зале. Сценарий выглядит следующим образом: пользователь сканирует код, система обрабатывает данные, очищает поле ввода и должна вернуть курсор (фокус) обратно в это же поле для следующего сканирования. Однако стандартная команда ЭтаФорма.ТекущийЭлемент = Элементы.ИмяЭлемента;, прописанная в обработчике события ПриИзменении, часто не дает ожидаемого результата. В этой статье мы подробно разберем, почему это происходит и как правильно решить проблему.
Рассмотрим стандартную ситуацию. У нас есть реквизит формы (не путать с реквизитом объекта, хотя поведение в данном случае схожее) и соответствующее ему поле ввода на форме. Мы пишем код, который должен очистить поле и вернуть в него фокус:
Процедура ШтрихкодПриИзменении(Элемент)
// Обработка считанного штрихкода
ДействиеСДанными(ЭтаФорма.Штрихкод);
// Попытка очистить поле и вернуть фокус
ЭтаФорма.Штрихкод = "";
ЭтаФорма.ТекущийЭлемент = Элементы.Штрихкод;
КонецПроцедуры
На первый взгляд, код абсолютно логичен. Однако на практике после выполнения этой процедуры фокус все равно переходит на следующий элемент формы в порядке обхода. Почему так происходит? Проанализируем механику работы платформы 1С:Предприятие 8.3.
Когда срабатывает событие ПриИзменении, это означает, что пользователь уже завершил ввод (нажал Enter или перешел в другое поле). Платформа в этот момент уже инициировала процесс смены активного элемента. Ваш программный код выполняется в промежутке между потерей фокуса старым элементом и активацией нового. Установка ТекущийЭлемент внутри обработчика игнорируется, так как после завершения процедуры 1С завершает свой «запланированный» переход к следующему объекту по порядку обхода.
Наиболее надежный и проверенный способ вернуть фокус — это использование механизма ПодключитьОбработчикОжидания. Идея заключается в том, чтобы «отложить» установку фокуса на доли секунды, позволив платформе завершить все стандартные процессы перестроения интерфейса и переходов.
Разберем реализацию этого метода по шагам:
ПриИзменении, где вместо прямой установки фокуса вызовем обработчик ожидания.Посмотрим на пример кода:
&НаКлиенте
Процедура ШтрихкодПриИзменении(Элемент)
// Выполняем полезную работу
ОбработатьВвод(ЭтаФорма.Штрихкод);
// Очищаем данные
ЭтаФорма.Штрихкод = "";
// Вызываем обработчик ожидания.
// Параметры: Имя процедуры, Интервал (0.1 сек), Однократно (Истина)
ПодключитьОбработчикОжидания("УстановитьФокусНаШтрихкод", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура УстановитьФокусНаШтрихкод() Экспорт
ЭтаФорма.ТекущийЭлемент = Элементы.Штрихкод;
КонецПроцедуры
Важный нюанс: Интервал 0.1 секунды практически незаметен для пользователя, но его достаточно для того, чтобы стек событий платформы очистился и команда установки фокуса сработала корректно. Параметр Истина (однократно) критически важен, иначе фокус будет принудительно возвращаться в поле каждые 0.1 секунды, блокируя работу с остальной формой.
Иногда фокус «улетает» на кнопки или другие декоративные элементы, которые пользователю при сканировании не нужны. Чтобы упростить жизнь платформе и минимизировать программные вмешательства, проанализируем свойства элементов формы.
Выясним, какие элементы можно исключить из процесса навигации. У каждого элемента управления (кнопки, поля ввода, таблицы) есть свойство Пропускать при вводе. Если для всех элементов, кроме целевого поля ввода штрихкода, установить это свойство в значение Истина, платформа физически не сможет перевести фокус никуда, кроме как обратно в ваше поле (или на следующий «разрешенный» элемент).
Этот метод хорошо работает в паре с первым решением, создавая максимально стабильный интерфейс для потокового ввода данных.
Зачастую проблема кроется не в коде 1С, а в настройках оборудования. Физические сканеры штрихкодов обычно имитируют нажатие клавиш клавиатуры. По умолчанию после передачи цифр штрихкода сканер отправляет символ Enter (суффикс возврат каретки) или Tab.
Проанализируем поведение системы:
Tab — платформа принудительно перейдет к следующему элементу формы.Enter — 1С попытается завершить редактирование и выполнить команду по умолчанию (например, закрыть форму или нажать кнопку выбора).Если ваша задача — максимально быстрая работа, рекомендуется настроить сканер на работу через Внешнее событие (драйвер устройства ввода). В этом случае фокус вообще не важен: данные попадают в процедуру ВнешнееСобытие формы, обрабатываются программно, а курсор пользователя может оставаться в любом месте. Если же используется эмуляция клавиатуры, то использование ПодключитьОбработчикОжидания остается единственным верным выходом.
Стоит упомянуть ситуацию с мобильным приложением 1С. На мобильных устройствах установка фокуса через ТекущийЭлемент может не вызвать автоматическое появление экранной клавиатуры. В таких случаях программисты иногда используют «двойной вызов»: сначала устанавливают фокус на вспомогательный элемент, а через микро-паузу (обработчик ожидания) — на нужный. Это заставляет операционную систему мобильного устройства корректно перерисовать интерфейс и активировать ввод.
Подведем итоги. Чтобы гарантированно удерживать фокус в нужном поле ввода на управляемой форме 1С, придерживайтесь следующих правил:
ТекущийЭлемент напрямую внутри ПриИзменении, если планируется остаться в том же поле.Используя эти методы, вы обеспечите плавный и предсказуемый пользовательский интерфейс, который будет работать стабильно вне зависимости от сложности формы и логики обработки данных.