Как понять, что реквизит находится в режиме редактирования и не дать обработчику ожидания прервать ввод

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

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

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

Метод 1. Анализ текущего элемента формы

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

Рассмотрим пример кода, который можно вставить в начало вашей процедуры-обработчика:


&AtClient
Procedure ИмяВашегоОбработчикаОжидания()
    
    // Проверяем, какой элемент сейчас активен
    АктивныйЭлемент = ЭтаФорма.ТекущийЭлемент;
    
    // Если это поле ввода, велика вероятность, что пользователь что-то печатает
    Если ТипЗнч(АктивныйЭлемент) = Тип("ПолеФормы") Тогда
        Если АктивныйЭлемент.Вид = ВидПоляФормы.ПолеВвода Тогда
            // Пропускаем выполнение, если не хотим прерывать ввод
            Возврат;
        EndIf;
    EndIf;
    
    // Основная логика обработчика
    // ...
    
EndProcedure

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

Метод 2. Использование событий «АвтоПодбор» и флагов активности

Более точный способ — отслеживать реальное нажатие клавиш. В 1С Управляемых формах нет глобального события нажатия клавиши, но мы можем использовать событие АвтоПодбор, которое срабатывает при каждом изменении текста пользователем.

Разберем алгоритм реализации по шагам:

  1. Создадим на форме клиентскую переменную (или реквизит формы типа Булево) с именем ПользовательРедактируетДанные.
  2. В событии АвтоПодбор для критически важных полей будем устанавливать этот флаг в значение Истина.
  3. В событии ПриИзменении или ОкончаниеВводаТекста будем сбрасывать флаг в Ложь.

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


&AtClient
Var ПользовательРедактируетДанные; // Переменная модуля

&AtClient
Procedure ПриОткрытии(Отказ)
    ПользовательРедактируетДанные = Ложь;
EndProcedure

&AtClient
Procedure ПолеВводаАвтоПодбор(Элемент, Текст, ДанныеВыбора, Параметры, Ожидание, СтандартнаяОбработка)
    ПользовательРедактируетДанные = Истина;
    // Можно также запустить таймер сброса этого флага через 5 секунд простоя
EndProcedure

&AtClient
Procedure ПолеВводаПриИзменении(Элемент)
    ПользовательРедактируетДанные = Ложь;
EndProcedure

В самом обработчике ожидания теперь достаточно проверять значение этой переменной. Это гарантирует, что пока идет активный набор, код 1С не будет перехватывать управление.

Метод 3. Защита табличных частей

Если ваша проблема связана с тем, что обработчик ожидания обновляет динамический список или таблицу, из-за чего закрывается режим редактирования строки, используйте специализированные события таблиц. Выясним, как это работает на примере ПередНачаломИзменения.

Для табличной части или таблицы формы мы можем использовать следующие обработчики:

Этот метод считается наиболее надежным для предотвращения потери данных в многострочных частях документов, так как 1С четко фиксирует начало и конец транзакции редактирования строки.

Метод 4. Альтернативный подход через Оповещения

Зачастую разработчики используют ПодключитьОбработчикОжидания для обновления данных, которые могли измениться в другой форме. Рассмотрим ситуацию: зачем нам таймер, который "дергает" сервер каждые 5 секунд, если можно использовать механизм Оповестить?

Вместо постоянного опроса системы, попробуем внедрить событийную модель:

  1. В форме, которая меняет данные, вызываем метод Оповестить("ДанныеИзменены", ПараметрыОбновления);.
  2. В нашей форме реализуем обработчик ОбработкаОповещения.
  3. Внутри этого обработчика проверяем, редактирует ли пользователь что-то прямо сейчас (используя методы описанные выше).

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

Метод 5. Использование поля HTML-документа (для продвинутых задач)

Проанализируем экзотический, но крайне эффективный метод для веб-клиента или сложных интерфейсов. Если нам нужно отслеживать активность пользователя абсолютно во всей форме (движение мыши, нажатия любых клавиш), мы можем поместить на форму невидимое ПолеHTMLДокумента.

С помощью небольшого JavaScript-кода внутри HTML-контейнера можно перехватывать события onkeydown или onmousemove и передавать информацию обратно в 1С через изменение location.href или специальные методы взаимодействия с контейнером. Это позволит реализовать полноценный детектор "Idle Time" (времени простоя), как в профессиональных операционных системах, и запускать ваши обработчики только тогда, когда пользователь действительно отошел от компьютера.

Резюме и рекомендации

Выяснив причины, по которым ПодключитьОбработчикОжидания может мешать пользователю, мы рекомендуем придерживаться следующей стратегии:

  1. Всегда проверяйте ЭтаФорма.ТекущийЭлемент в первой строке обработчика.
  2. Для длинных интервалов (более 30 секунд) используйте проверку ЭтаФорма.Модифицированность. Если форма изменена, возможно, стоит отложить автоматическое обновление.
  3. Если ваша задача — обновление списков, рассмотрите возможность увеличения интервала до комфортных 60-120 секунд. Это даст пользователю достаточно времени на ввод данных без прерываний.
  4. Используйте флаги в событиях АвтоПодбор, если работа идет с текстовыми полями, где важен каждый символ.

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

← На главную