Как зафиксировать фокус на поле ввода в управляемой форме 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке интерфейсов в 1С:Предприятии 8.3 на управляемых формах часто возникает задача организации потокового ввода данных. Типичный пример — сканирование штрихкодов или последовательный ручной ввод серийных номеров в специальное текстовое поле. Оператор должен иметь возможность вводить значения одно за другим, не отвлекаясь на постоянное перепозиционирование курсора мыши или повторные нажатия на поле ввода.

Однако стандартное поведение платформы 1С часто препятствует этому. При попытке программно вернуть фокус обратно в поле ввода в событии ПриИзменении разработчики сталкиваются с тем, что курсор все равно перескакивает на следующий по порядку обхода элемент формы. В этой статье мы подробно разберем, почему это происходит, проанализируем внутренние механизмы работы платформы и рассмотрим несколько эффективных способов решения этой проблемы.

Почему стандартный перенос фокуса не работает в событии ПриИзменении?

Для начала выясним причину, по которой простая строчка кода ТекущийЭлемент = Элементы.ПоискКарточки; внутри обработчика события ПриИзменении оказывается неэффективной. Дело в специфике жизненного цикла событий управляемого клиента 1С.

Когда пользователь вводит текст в поле и нажимает клавишу Enter или Tab, платформа выполняет следующую последовательность действий:

  1. Фиксируется изменение текста в поле ввода.
  2. Запускается и отрабатывает код события ПриИзменении. На данном этапе присвоение ТекущийЭлемент = Элементы.ПоискКарточки; действительно отрабатывает, и во время выполнения процедуры фокус формально переносится на наше поле ввода.
  3. Завершение стандартной обработки события платформой. После того как процедура ПриИзменении полностью выполнена, платформа инициирует свое штатное действие перехода к следующему элементу формы в соответствии с установленным порядком обхода.

Таким образом, стандартный механизм перехода платформы срабатывает после завершения работы вашего кода, перетирая назначенное значение свойства ТекущийЭлемент. Именно поэтому прямое присвоение внутри события не дает желаемого результата.

Рассмотрим по шагам четыре различных метода обхода этого ограничения.

Решение 1. Использование отложенного вызова через обработчик ожидания

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

Для этого используется метод клиента ПодключитьОбработчикОжидания с минимальным интервалом вызова и флагом однократного выполнения. Проанализируем пример кода:


&НаКлиенте
Процедура ПоискКарточкиПриИзменении(Элемент)
    
    // Выполняем полезную работу: обработку введенного серийного номера
    ОбработатьВводСерийногоНомера(Объект.ПоискКарточки);
    
    // Подключаем однократный обработчик ожидания с задержкой 0.1 секунды
    ЭтаФорма.ПодключитьОбработчикОжидания("УстановитьТекущийЭлемент", 0.1, Истина);
    
КонецПроцедуры

&НаКлиенте
Процедура УстановитьТекущийЭлемент()
    
    // Возвращаем фокус на поле ввода после завершения всех стандартных переходов
    ТекущийЭлемент = Элементы.ПоискКарточки;
    
КонецПроцедуры

Преимущества метода: Способ гарантированно работает в любых типовых конфигурациях и не требует изменения структуры элементов формы.

Недостатки метода: Поскольку присутствует микрозадержка в 0.1 секунды, визуально пользователь может заметить, как курсор на мгновение перескакивает на следующее поле формы, а затем резко возвращается обратно. Это создает неприятный эффект «мерцания» интерфейса.

Решение 2. Использование свойства «Пропускать при вводе»

Если на форме присутствует всего несколько полей ввода, а оператору при работе с данной формой вообще не требуется переходить в другие поля по клавише Enter или Tab, можно использовать интерактивную настройку элементов в конфигураторе.

Для этого выполним следующие действия:

  1. Откроем управляемую форму в конфигураторе.
  2. Выделим все элементы управления и поля ввода на форме, за исключением нашего поля ПоискКарточки.
  3. В палитре свойств для выбранных элементов найдем свойство «Пропускать при вводе» (в англоязычной локализации — Skip on Input) и установим его в значение Да (Истина).

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

Решение 3. Настройка поведения клавиши Enter для формы

Еще один элегантный способ управления фокусом без использования программного кода — изменение глобальных настроек поведения клавиши ввода для всей управляемой формы.

По умолчанию у любой управляемой формы свойство «Поведение клавиши Enter» настроено в значение «Переход по элементам формы». Чтобы отключить автоматический переход:

  1. Перейдем в свойства самой управляемой формы (самый верхний элемент в дереве элементов).
  2. Найдем свойство «Поведение клавиши Enter».
  3. Изменим его значение на «Не использовать» или «Кнопка по умолчанию».

После этого нажатие клавиши Enter в любом текстовом поле формы не будет приводить к автоматическому прыжку курсора на следующий реквизит. Фокус будет оставаться на текущем поле ввода, и обработчик события ПриИзменении сможет корректно отрабатывать без дополнительных программных костылей.

Решение 4. Перехват события «ОкончаниеВводаТекста»

Для более гибкого управления вводом можно отказаться от обработки события ПриИзменении в пользу события ОкончаниеВводаТекста. Это событие генерируется платформой в момент окончания редактирования текста пользователем, но до того, как система начнет применять стандартные алгоритмы завершения ввода.

Посмотрим на пример реализации данного подхода:


&НаКлиенте
Процедура ПоискКарточкиОкончаниеВводаТекста(Элемент, Текст, ДанныеВыбора, СтандартнаяОбработка)
    
    // Отменяем стандартную обработку платформы, чтобы предотвратить потерю фокуса
    СтандартнаяОбработка = Ложь;
    
    // Записываем введенный текст напрямую в реквизит, так как стандартная обработка отключена
    Объект.ПоискКарточки = Текст;
    
    // Выполняем алгоритм обработки данных
    ОбработатьВводСерийногоНомера(Текст);
    
    // Очищаем поле для ввода следующего серийного номера
    Объект.ПоискКарточки = "";
    
КонецПроцедуры

Важным нюансом при использовании этого метода является свойство поля ввода «Обновление текста редактирования». Если при программном изменении значения поля ввода текст в нем визуально «залипает» или отображается некорректно, рекомендуется установить это свойство в значение «При изменении значения» или «Не использовать». Это гарантирует своевременную очистку поля на экране монитора.

Альтернативный подход: Использование стандартов БСП для сканеров штрихкодов

Проанализируем архитектуру решения в целом. Фиксация фокуса в текстовом поле ввода — это классический обходной путь (workaround), используемый тогда, когда сканер штрихкодов настроен в режиме «эмуляции клавиатуры» (Keyboard Wedge). При таком режиме сканер просто имитирует быстрое нажатие клавиш пользователем на клавиатуре.

Однако этот подход имеет существенный недостаток: если оператор случайно кликнет мышкой мимо поля ввода, процесс сканирования нарушится, а данные могут быть введены в случайное поле формы.

Профессиональным стандартом разработки на платформе 1С является интеграция оборудования через Библиотеку стандартных подсистем (БСП):

При использовании этого стандарта оператору вообще не требуется держать курсор в каком-либо конкретном поле формы. Он может находиться в любом месте интерфейса, прокручивать табличные части или читать описание номенклатуры — при сканировании данные гарантированно попадут в алгоритм обработки без риска потери фокуса.

← На главную