Как правильно обрабатывать внешние события сканера ШК в нескольких формах и почему метод ВводДоступен возвращает Ложь

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

При разработке функционала для работы с торговым оборудованием в конфигурациях на обычных формах (например, УТ 10.3) разработчики часто сталкиваются с ситуацией, когда данные со сканера штрихкода обрабатываются не в той форме, которая активна в данный момент, или не обрабатываются вовсе. Центральную роль в этой логике играет метод ВводДоступен(). Рассмотрим подробно, как работает этот механизм, почему он может давать сбои в режиме отладки или терминального доступа, и как правильно спроектировать архитектуру приложения для стабильной работы со сканером.

Механизм работы ВнешнееСобытие() и подписки на торговое оборудование

Разберем, как устроена подсистема торгового оборудования в типовых решениях. Когда мы вызываем метод ПолучитьСерверТО().ПодключитьКлиента(ЭтаФорма), мы фактически регистрируем текущую форму в глобальном массиве слушателей событий. Это означает, что при срабатывании сканера платформа 1С разошлет оповещение ВнешнееСобытие() во все формы, которые были подключены этим методом и еще не закрыты. Для настройки интеграции оборудования через этот механизм можно использовать обработку обслуживания сканеров через драйвер NativeAPI.

Проанализируем типовой код обработки события в форме:


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

Здесь проверка Если Не ВводДоступен() Тогда Возврат; служит фильтром. Поскольку событие прилетает во все открытые формы (и в основную, и в модальную произвольную), эта строка должна отсекать неактивные окна, чтобы штрихкод обработало только то окно, с которым сейчас работает пользователь.

Почему ВводДоступен() возвращает Ложь в режиме отладки

Выясним причину, по которой программисты часто получают неверные результаты при тестировании. Если вы установите точку останова на строке с вызовом ВводДоступен(), то при активации сканера фокус системы переключится с окна 1С:Предприятие на окно Конфигуратора (в отладчик). В этот момент для платформы интерактивный ввод в форму становится недоступен, и метод закономерно возвращает Ложь.

Важный вывод: для корректной проверки работы фокуса нельзя использовать точки останова непосредственно на проверке. Вместо этого рекомендуется использовать Сообщить() или запись в журнал регистрации для мониторинга состояния метода в реальном времени без прерывания работы интерфейса.

Особенности работы в терминальной среде (Citrix и RDP)

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

Также стоит учитывать задержки передачи данных. В условиях Citrix событие от COM-объекта (драйвера сканера) может прийти быстрее, чем Windows успеет обновить статус фокуса окна после того, как пользователь кликнул по нему. В таких случаях данные "проглатываются" из-за срабатывания оператора Возврат.

Проблема модальных окон и "фантомных" обработчиков

Проанализируем ситуацию из практики: открыта основная форма, из нее модально открывается произвольная форма (например, форма авторизации или выбора характеристик). Если в обеих формах вызван метод ПодключитьКлиента(ЭтаФорма), возникают следующие риски:

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

Альтернативные подходы к архитектуре обработки событий

Если стандартный механизм с ВводДоступен() работает нестабильно, рассмотрим более надежные способы организации работы:

1. Использование механизма Оповестить()

Вместо того чтобы подписывать каждую форму на торговое оборудование, можно реализовать схему "Диспетчера":

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

2. Проверка через ТекущееОкно()

В новых версиях платформы 8.3 для более точного определения активности окна можно попробовать проанализировать статус окна через коллекцию окон приложения. Это более трудоемкий путь, требующий использования методов ЭтаФорма.ТекущееОкно().Активно(), но он дает более точный результат, чем ВводДоступен(), который слишком чувствителен к системному фокусу ОС.

3. Буферизация данных

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

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

Для стабильной работы в УТ 10.3 придерживайтесь следующих правил:

  1. Всегда вызывайте ОтключитьКлиента(ЭтаФорма) в процедуре ПриЗакрытии().
  2. Если используете ВводДоступен(), помните, что он вернет Ложь, если поверх формы открыто любое другое окно (даже системное предупреждение).
  3. Для отладки событий сканера используйте запись в текстовый файл или ЖурналРегистрации, чтобы не перехватывать фокус окном конфигуратора.
  4. В терминальных средах проверьте настройки проброса портов и убедитесь, что драйвер сканера на стороне сервера корректно определяет состояние сессии.

Соблюдение этих принципов позволит избежать "фантомных" срабатываний и обеспечит надежный ввод данных даже в сложных многооконных интерфейсах на базе обычных форм.

← На главную