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