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