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

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

В разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ограничением управляемых форм: отсутствие штатного события ПриАктивизации или ПриПолученииФокуса для обычных полей ввода. В отличие от табличных частей, где событие ПриАктивизацииСтроки или ПриАктивизацииЯчейки позволяет гибко реагировать на действия пользователя, поля ввода «молчат» до тех пор, пока данные в них не будут изменены или ввод не будет завершен. Рассмотрим подробно, как можно обойти это ограничение и реализовать обновление связанных данных (например, таблиц) при обычном перемещении курсора между полями.

Метод 1. Использование обработчика ожидания и анализ текущего элемента

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

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


&НаСервере
Перем ПоследнийАктивныйЭлемент;

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Подключаем обработчик, который будет срабатывать каждую секунду
    ПодключитьОбработчикОжидания("ПроверитьСменуФокуса", 1, Ложь);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьСменуФокуса()
    // Сравниваем текущий элемент формы с сохраненным значением
    Если ЭтаФорма.ТекущийЭлемент <> ПоследнийАктивныйЭлемент Тогда
        // Фокус изменился, выполняем логику обновления
        ПоследнийАктивныйЭлемент = ЭтаФорма.ТекущийЭлемент;
        ОбновитьСвязанныеДанные(ПоследнийАктивныйЭлемент.Имя);
    КонецЕсли;
КонецПроцедуры

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

Метод 2. Использование события ПриНачалеВыбора

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

  1. Установим у нужных полей ввода свойство Кнопка выбора в значение Да.
  2. В обработчике события ПриНачалеВыбора пропишем код, который будет прерывать стандартное открытие формы выбора, но выполнять нашу логику.

&НаКлиенте
Процедура ПолеВвода1ПриНачалеВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    // Отменяем открытие стандартного списка или формы выбора
    СтандартнаяОбработка = Ложь;
    
    // Выполняем обновление таблицы
    ОбновитьТаблицуНаОснованииФокуса(Элемент.Имя);
КонецПроцедуры

Этот метод работает мгновенно при клике по кнопке выбора или нажатии клавиши F4. Чтобы он срабатывал просто при клике в поле, можно скомбинировать его с установкой свойства РежимВыбораИзСписка, но это изменит поведение интерфейса, что не всегда приемлемо.

Метод 3. Использование Native API (Внешние компоненты)

Для тех случаев, когда требуется «промышленное» решение без задержек, используются внешние компоненты. Рассмотрим механизм их работы. Компонента, написанная на C++ или Delphi, подключается к интерфейсному потоку Windows и перехватывает сообщения операционной системы, такие как WM_SETFOCUS.

Посмотрим на алгоритм работы с такой компонентой:

Преимущество: Нулевая задержка и отсутствие лишних циклов опроса (обработчиков ожидания). Недостаток: Трудности с поддержкой в веб-клиенте и необходимость наличия прав на установку библиотек на рабочих станциях пользователей.

Метод 4. Оптимизация через рекурсивный вызов обработчика

Вернемся к идее с таймером. Проанализируем ситуацию: стандартный интервал в 1 секунду кажется медленным. Мы можем попробовать вызвать обработчик как однократный с минимальной задержкой (например, 0.1 сек) в конце самого обработчика.


&НаКлиенте
Процедура ЗапуститьМониторинг()
    // Запуск разового события через минимальный интервал
    ПодключитьОбработчикОжидания("КонтрольФокуса", 0.1, Истина);
КонецПроцедуры

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

Важно: Платформа 1С все равно может ограничивать частоту выполнения интерфейсных задач, чтобы избежать «зависания» формы. Подобный подход следует использовать осторожно, так как он может привести к чрезмерному потреблению ресурсов процессора на стороне клиента.

Метод 5. JavaScript и HTML-документ (для Веб-клиента)

Если ваша конфигурация преимущественно работает в браузере, можно применить современные веб-технологии. Посмотрим на этот сценарий: на форму добавляется невидимое поле ПолеHTMLДокумента. Через него можно внедрить скрипт, который будет отслеживать события focus и blur на элементах страницы.

Этот метод требует глубоких знаний DOM-модели, которую генерирует 1С, так как идентификаторы элементов (ID) могут меняться динамически. Однако, реализовав передачу данных через window.external.Message() (или аналоги в зависимости от версии), можно добиться идеальной реакции в веб-интерфейсе.

Подведение итогов

Выбор метода зависит от ваших приоритетов. Если важна простота и надежность — используйте Метод 1 с интервалом в 1 секунду. Это стандарт де-факто для большинства бизнес-приложений на 1С. Если же требуется моментальная реакция и вы готовы к техническим сложностям — смотрите в сторону Внешних компонент. Разберем еще раз: отсутствие штатного события — это осознанное ограничение платформы для повышения стабильности управляемого интерфейса, поэтому любое решение по его обходу должно быть тщательно протестировано на производительность.

← На главную