В практике разработчика 1С иногда возникают ситуации, которые кажутся мистическими: один и тот же код ведет себя безупречно под отладкой, но ломает логику работы пользователя в обычном режиме. Одной из самых неприятных проблем такого рода является спонтанная потеря фокуса ввода. Рассмотрим ситуацию, когда после выполнения кода в обработчике ПриПолученииДанных курсор вместо того, чтобы остаться в поле подбора, «вылетает» в главное меню программы или на родительское окно. Проанализируем, почему это происходит и как это победить.
Разберем механизм работы платформы. В обычном режиме «1С:Предприятие» выполнение кода и отрисовка интерфейса происходят в очень плотном взаимодействии с очередью системных сообщений операционной системы Windows. Когда срабатывает событие ПриПолученииДанных, платформа выполняет целый каскад действий: расчет оформления строк, установку картинок, изменение цветов фона.
В версиях платформы 8.3.26 и 8.3.27 был изменен алгоритм обработки сообщений Windows Messages, отвечающих за фокус элементов. В момент интенсивной перерисовки табличной части возникает конфликт приоритетов, и операционная система ошибочно передает фокус на верхний уровень иерархии — в главное меню. Именно поэтому при наборе текста у пользователя начинают открываться подменю «Сервис» или «Файл».
Почему же под отладкой всё работает? Когда мы ставим точку останова, выполнение потока прерывается. В этот момент фокус принудительно удерживается конфигуратором или системным отладчиком. После нажатия F5 платформа восстанавливает состояние окон из кэша, что фактически выполняет «принудительную» активацию нужного элемента. Таким образом, пауза в отладке дает платформе время корректно завершить системные процессы перерисовки, которые в обычном режиме «пролетают» с ошибкой фокуса.
Если ваша конфигурация (например, УТ 10.3) работает на «проблемных» версиях платформы и вы не можете оперативно их обновить, можно использовать метод принудительного восстановления фокуса. Суть метода заключается в том, чтобы переключить фокус на вспомогательный элемент и тут же вернуть его обратно. Рассмотрим пример реализации такой процедуры:
Процедура ВосстановитьФокусВвода(Форма, ВспомогательныйЭлемент) Экспорт
// Сохраняем текущий активный элемент
ТекЭл = Форма.ТекущийЭлемент;
// Временно переключаем фокус на другой элемент (например, на дату или кнопку)
Форма.ТекущийЭлемент = ВспомогательныйЭлемент;
// Возвращаем фокус на исходный элемент
Форма.ТекущийЭлемент = ТекЭл;
КонецПроцедуры
В коде формы подбора, сразу после добавления строки или в конце процедур оформления, вызовем это восстановление. Проанализируем пример вызова:
// Пример вызова в обработчике события
ВосстановитьФокусВвода(ЭтаФорма, ЭлементыФормы.ДатаДокумента);
Этот метод заставляет платформу заново пересчитать координаты и состояние фокуса для нужного нам поля.
Как мы выяснили, проблема часто кроется в микро-задержках отрисовки. Мы можем искусственно разнести во времени процесс визуального обновления строки и процесс активации поля. Для этого идеально подходит ПодключитьОбработчикОжидания. Посмотрим, как это реализовать по шагам.
Шаг 1. Создадим экспортную процедуру в модуле формы, которая будет отвечать только за активацию поля ввода.
Процедура ПринудительноВернутьФокус() Экспорт
ЭтаФорма.Активизировать();
ТекущийЭлемент = ЭлементыФормы.ПолеПоискаНоменклатуры;
КонецПроцедуры
Шаг 2. В коде, где происходит потеря фокуса (например, после завершения цикла в ТоварыПриПолученииДанных или в процедуре подбора), добавим вызов обработчика с минимальной задержкой.
// Устанавливаем задержку в 0.1 секунды.
// Этого достаточно, чтобы платформа завершила отрисовку интерфейса.
ПодключитьОбработчикОжидания("ПринудительноВернутьФокус", 0.1, Истина);
Использование параметра Истина гарантирует, что обработчик сработает только один раз. Этот метод эффективно эмулирует то «ожидание», которое происходит при отладке, и фокус гарантированно возвращается в нужное поле.
Проанализируем ситуацию с точки зрения системного администрирования. Если программные методы не помогают, стоит рассмотреть изменение версии платформы 1С:Предприятие:
Иногда потеря фокуса сопровождается эффектом «залипшей клавиши Alt». Программа начинает воспринимать ввод символов как горячие клавиши меню. Если вы столкнулись именно с этим, попробуйте программно вызвать закрытие любого невидимого вспомогательного окна или использовать объект WScript.Shell для эмуляции нажатия клавиши Esc, что сбросит состояние меню. Однако, использование внешних объектов — это крайний метод, и мы рекомендуем в первую очередь использовать обработчик ожидания, так как он наиболее естественен для событийной модели 1С.
Подводя итог, скажем: если ваш код ведет себя странно в обычном режиме — ищите проблему в очередности событий интерфейса. Использование небольших пауз через обработчики ожидания позволяет обойти большинство «детских болезней» новых версий платформы и обеспечить пользователю комфортную работу без лишних кликов мышкой.