При разработке интерфейсов для быстрого ввода данных в 1С:Предприятии 7.7 (например, при потоковом сканировании штрихкодов, кодов маркировки или подборе товаров по артикулу) разработчики часто сталкиваются со штатным поведением платформы: после завершения ввода значения и нажатия клавиши Enter курсор автоматически переходит на следующий элемент формы согласно порядку обхода.
Выясним причину такого поведения и подробно разберем несколько проверенных способов удержания или принудительного возврата фокуса в исходное поле ввода.
Почему метод Активизировать() не срабатывает напрямую в формуле поля: в платформе 1С 7.7 при нажатии клавиши Enter сначала выполняется процедура, привязанная к полю (формула элемента), и лишь затем встроенный механизм платформы переводит фокус на следующий элемент диалога. Если вызвать метод Активизировать() непосредственно внутри процедуры поля, фокус сначала вернется на поле, но затем платформа завершит штатный цикл обработки нажатия клавиши и переведет курсор дальше. Для обхода этого ограничения используются специальные программные приемы.
Рассмотрим наиболее популярный и надежный способ без применения сторонних библиотек — так называемое «ложное закрытие». Суть метода заключается в том, что в обработчике поля мы инициируем закрытие формы методом Форма.Закрыть(0), а в предопределенной процедуре ПриЗакрытии() перехватываем это событие, отменяем закрытие через СтатусВозврата(0) и принудительно активизируем нужное поле.
Разберем по шагам реализацию этого механизма:
ФлагЛожногоЗакрытия).Форма.Закрыть(0).ПриЗакрытии() проверяем флаг: если он установлен, сбрасываем его в 0, отменяем закрытие через СтатусВозврата(0) и вызываем Активизировать("ИмяРеквизита").Посмотрим на пример кода:
Перем ФлагЛожногоЗакрытия;
Процедура ОбработкаВводаШтрихкода()
// Выполняем полезные действия по обработке введенного значения
Если ПустоеЗначение(Штрихкод) = 0 Тогда
Сообщить("Обработан код: " + СокрЛП(Штрихкод));
// Очищаем поле для следующего сканирования
Штрихкод = "";
КонецЕсли;
// Взводим флаг и инициируем закрытие формы
ФлагЛожногоЗакрытия = 1;
Форма.Закрыть(0);
КонецПроцедуры
Процедура ПриЗакрытии()
Если ФлагЛожногоЗакрытия = 1 Тогда
ФлагЛожногоЗакрытия = 0;
СтатусВозврата(0); // Отменяем закрытие формы
Активизировать("Штрихкод", 0); // Передаем точное строковое имя элемента диалога
КонецЕсли;
КонецПроцедуры
Важное замечание по синтаксису метода Активизировать: параметром метода Активизировать(<ИмяРеквизита>, <Режим>) должна выступать строковая константа с именем элемента диалога в кавычках (например, Активизировать("Штрихкод")), либо строковая переменная, содержащая это имя. Передача имени переменной без кавычек является синтаксической ошибкой при позиционировании на элементе.
Проанализируем альтернативный вариант без вызова закрытия формы — использование асинхронного таймера. Платформа 1С 7.7 позволяет запустить процедуру ожидания, которая выполнится уже после того, как платформа завершит стандартную передачу фокуса.
Посмотрим на программную реализацию:
Процедура ВернутьФокусНаПоле()
// Отключаем обработчик ожидания
ОбработкаОжидания("", 0);
// Возвращаем фокус на требуемое поле
Активизировать("Штрихкод", 0);
КонецПроцедуры
Процедура ПриВводеЗначения()
// Обработка логики формы...
Штрихкод = "";
// Запускаем таймер на 1 секунду для отложенного возврата фокуса
ОбработкаОжидания("ВернутьФокусНаПоле", 1);
КонецПроцедуры
Разберем еще один изящный способ: компенсацию перехода курсора вперед с помощью системной эмуляции нажатия комбинации клавиш Shift + Tab (переход к предыдущему элементу). Для этого используем стандартный Windows-объект WScript.Shell.
Рассмотрим пример реализации:
Процедура ПолеВвода()
// Обработка данных
Штрихкод = "";
// Эмулируем возврат назад по списку обхода элементов
Попытка
WshShell = СоздатьОбъект("WScript.Shell");
WshShell.SendKeys("+{TAB}");
Исключение
// Обработка исключения при недоступности COM-объекта
КонецПопытки;
КонецПроцедуры
Если в конфигурации подключена библиотека расширения FormEx, задачу можно решить на низком уровне перехватом клавиатурных событий или управлением окнами:
НажатиеКлавиши отслеживается код клавиши Enter. При его фиксации выполняется нужный код обработки, а штатная реакция платформы на нажатие клавиши подавляется.SetFocus) для немедленной установки фокуса на дескриптор окна (HWND) требуемого поля.Если необходимость удерживать курсор связана с подключением торгового оборудования (сканеров 1D/2D, считывателей DataMatrix или PDF417), оптимальным решением является перевод сканера из режима клавиатурного ввода (Keyboard Wedge / USB HID) в режим эмуляции виртуального COM-порта (USB-CDC / RS-232). При таком подключении данные передаются через специализированный драйвер напрямую в процедуру формы ОбработкаВнешнегоСобытия(Источник, Событие, Данные), что полностью исключает зависимость логики программы от текущего положения курсора на форме.