Почему событие сканера штрихкодов срабатывает повторно в основной форме РМК и как это исправить?

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

При разработке расширений или доработке конфигураций на базе 1С:Розница 2.2 программисты часто сталкиваются с задачей перехвата события сканирования штрихкода. Например, при считывании алкогольной продукции необходимо перехватить код товара, открыть собственную формальную обработку для ввода акцизной марки, считать марку сканером и передать данные обратно в рабочее место кассира (РМК).

Однако на практике возникает проблема: после сканирования марки в подчиненной форме обработка успешно завершается, но затем форма РМК также получает внешнее событие с прочитанной маркой и повторно вызывет обработчик. Проанализируем причину такого поведения платформы «1С:Предприятие» и разберем практические способы решения этой задачи.

Выясним причину двойного срабатывания события

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

В форме РМК обработчик внешнего события обычно содержит проверку функции ВводДоступен():


&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)
    Если ВводДоступен() Тогда
        ПодключаемоеОборудованиеРТКлиент.ВнешнееСобытиеОборудованияРМК(ЭтотОбъект, Источник, Событие, Данные);
    КонецЕсли;
КонецПроцедуры

Двойной перехват возникает из-за сочетания двух факторов:

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

Способ 1. Асинхронное закрытие формы через обработчик ожидания (Рекомендованный)

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

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


&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)
    Если ВводДоступен() Тогда
        // Обрабатываем считанный штрихкод/марку
        РезультатСканирования = ОбработатьШтрихкодУстройства(Источник, Событие, Данные);
        Если РезультатСканирования.Успех Тогда
            СохраненныеДанныеМарки = РезультатСканирования.Значение;
            // Подключаем однократный обработчик ожидания для безопасного закрытия
            ПодключитьОбработчикОжидания("АсинхронноеЗавершениеОбработки", 0.1, Истина);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура АсинхронноеЗавершениеОбработки()
    // Передаем данные форме-владельцу и закрываем текущую форму
    ОповеститьОВыборе(СохраненныеДанныеМарки);
КонецПроцедуры

Благодаря задержке в 0.1 секунды событие сканера успевает полностью «погаснут» в контексте подчиненной формы, и форма РМК не получает устаревший сигнал.

Способ 2. Блокировка окна владельца при открытии подчиненного окна

Если подчиненная форма должна полностью перехватывать ввод кассы, открываем ее с установкой режима блокировки окна владельца. В этом случае для формы РМК вызов ВводДоступен() вернет Ложь на весь период работы с маркой.

Разберем пример открытия формы с передачей параметров:


ПараметрыФормы = Новый Структура();
ПараметрыФормы.Вставить("ДанныеСШК", РезультатПроверки);

РежимОткрытия = РежимОткрытияОкнаУправляемойФормы.БлокироватьОкноВладельца;
ОткрытьФорму("Обработка.МояОбработкаВводаМарки.Форма.Форма", ПараметрыФормы, ЭтаФорма, , , , , РежимОткрытия);

Способ 3. Управление подключением через МенеджерОборудованияКлиент

При использовании Библиотеки Подключаемого Оборудования (БПО) можно явно управлять списком форм, подписанных на внешние события сканера. При открытии подчиненной обработки отключаем от событий форму РМК, а при закрытии — восстанавливаем подключение.

В форме-владельце (РМК) перед открытием обработки вызываем отключение:


МассивТипов = Новый Массив;
МассивТипов.Добавить("СканерШтрихкода");
МенеджерОборудованияКлиент.ОтключитьОборудованиеПоТипу(ЭтаФорма.УникальныйИдентификатор, МассивТипов);

ОткрытьФорму("Обработка.МояОбработкаВводаМарки.Форма.Форма", ПараметрыСШК, ЭтаФорма);

В подчиненной форме в процедуре ПриОткрытии подписываем ее УИД на прием событий торгового оборудования:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    МассивТипов = Новый Массив;
    МассивТипов.Добавить("СканерШтрихкода");
    МенеджерОборудованияКлиент.ПодключитьОборудованиеПоТипу(ЭтаФорма.УникальныйИдентификатор, МассивТипов);
КонецПроцедуры

При закрытии подчиненной формы выполняем обратную процедуру: отключаем подчиненную форму и повторно подключаем главную форму РМК.

← На главную