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