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