Как сделать, чтобы таблица отчета открывалась на переднем плане поверх документа в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При разработке интерфейсных решений в среде 1С:Предприятие 7.7 программисты часто сталкиваются с неприятным поведением окон. Классический сценарий: в форме документа пользователь совершает двойной клик по строке с товаром, программа формирует печатную форму или отчет, но это новое окно моментально "уходит" на задний план, прячась за активным документом. Чтобы увидеть результат, пользователю приходится совершать лишние действия — сворачивать документ или нажимать сочетание клавиш Ctrl + Tab.

В этой статье мы подробно проанализируем физику этого процесса, выясним причины такого поведения интерфейса платформы и разберем несколько способов решения проблемы: как с использованием популярной внешней компоненты FormEx, так и исключительно штатными средствами платформы.

Почему окно отчета или таблицы уходит на задний план?

Прежде чем переходить к написанию кода, проанализируем ситуацию и поймем, почему так происходит. Когда пользователь дважды кликает по элементу формы (например, текстовому полю ввода товара):

  1. Операционная система Windows передает событие клика платформе 1С.
  2. Платформа (или внешняя компонента) запускает соответствующий обработчик события, в котором написан ваш код открытия отчета.
  3. Код успешно выполняется: создается объект отчета, формируется выходной табличный документ и выводится на экран с помощью метода Показать(). Новое окно визуально открывается на переднем плане.
  4. После этого управление возвращается платформе 1С. Платформа "считает", что стандартная обработка двойного клика на исходной форме документа еще не завершена.
  5. Система принудительно возвращает фокус ввода на элемент документа, по которому кликнул пользователь (например, чтобы выделить текст или активизировать поле ввода).
  6. В результате этого фокус перехватывается, и форма документа мгновенно перекрывает собой только что созданную печатную форму.

Таким образом, наша главная задача — заблокировать стандартную реакцию платформы 1С на клик мыши после того, как наш отчет уже был открыт.

Решение с использованием внешней компоненты FormEx (параметр ФСО)

В большинстве типовых и доработанных конфигураций на платформе 1С 7.7 используется внешняя компонента FormEx, расширяющая возможности работы с формами. Она предоставляет предопределенный обработчик событий мыши ПриДвойномНажатииЛевойКнопки с четырьмя параметрами:

Процедура ПриДвойномНажатииЛевойКнопки(сост, х, у, фсо)

Наиболее важным здесь является четвертый параметр — фсо (Флаг Стандартной Обработки). По умолчанию он равен 1. Если мы внутри процедуры принудительно установим его в значение 0, то компонента FormEx заблокирует стандартное поведение платформы 1С. Фокус не вернется на форму документа, и отчет останется на переднем плане.

Рассмотрим пример реализации такого обработчика:


Процедура ПриДвойномНажатииЛевойКнопки(сост, х, у, фсо)
    // Отключаем стандартную обработку клика платформой 1С
    фсо = 0; 
    
    Если Проведен() = 1 Тогда    
        Если Форма.АктивныйЭлемент() = "Тов" Тогда
            // Подготавливаем параметры для отчета
            глРасшифровка = СоздатьОбъект("СписокЗначений");
            глРасшифровка.Установить("Тов", Тов);
            глФлагРасшифровки = 1;
            
            // Открываем форму отчета
            ОткрытьФорму("Отчет.ИсторияТов", );
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Благодаря строке фсо = 0; в самом начале процедуры, фокус гарантированно останется на открывшемся окне отчета.

Разбор практического примера с перенаправлением фокуса

Посмотрим на более сложную и универсальную процедуру из реальной практики разработки. Предположим, на форме документа есть несколько полей, клики по которым должны вызывать разные действия (например, просмотр информации о коде идентификации ИДН или по товару):


Процедура ПриДвойномНажатииЛевойКнопки(сост, х, у, фсо)
    // Блокируем стандартный фокус платформы
    фсо = 0;
    
    Если Проведен() = 1 Тогда    
        // Обработка клика по полю идентификатора
        Если Форма.АктивныйЭлемент() = "Идн1" Тогда
            ИИ = СоздатьОбъект("Справочник.ИДН");
            Если ИИ.НайтиПоНаименованию(СокрЛП(Идн1), 0, 1) = 1 Тогда
                ОбработкаЯчейкиТаблицы(ИИ.ТекущийЭлемент(), "", "", "");
            КонецЕсли;            
        
        // Обработка клика по полю товара
        ИначеЕсли Форма.АктивныйЭлемент() = "Тов" Тогда
            ОбработкаЯчейкиТаблицы(Тов.ТекущийЭлемент(), "", "", "");
        КонецЕсли;
    КонецЕсли;    
КонецПроцедуры

В данном коде используется вызов предопределенной функции ОбработкаЯчейкиТаблицы, которая эмулирует расшифровку и открывает соответствующие формы. За счет сброса флага фсо новые окна без проблем отображаются поверх родительского документа.

Решение проблемы штатными средствами 1С 7.7 (без внешних компонент)

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

Способ 1. Отложенный запуск через Обработку Ожидания

Это классический и самый надежный прием ("костыль") в среде разработчиков 1С 7.7. Идея заключается в том, чтобы разделить во времени процесс клика пользователя и процесс открытия нового окна. Мы запускаем таймер с минимальным интервалом времени (например, 1 секунда). За эту секунду платформа успевает завершить все свои внутренние обработчики клика и распределить фокусы. Когда таймер срабатывает, открывается наше окно и гарантированно остается сверху.

Реализуем этот алгоритм по шагам:

  1. В формуле элемента формы или в процедуре, привязанной к событию клика, прописываем установку таймера:

Процедура ПриКликеНаЭлемент()
    // Запускаем отложенную процедуру через 1 секунду
    Форма.ОбработкаОжидания("ОткрытьОтчетОтложено", 1);
КонецПроцедуры
  1. В модуле формы документа создаем саму процедуру открытия. Важно первым делом отключить таймер, иначе процедура будет вызываться циклически каждую секунду:

Процедура ОткрытьОтчетОтложено()
    // Отключаем обработку ожидания
    Форма.ОбработкаОжидания("", 0);
    
    // Выполняем стандартное открытие отчета
    глРасшифровка = СоздатьОбъект("СписокЗначений");
    глРасшифровка.Установить("Тов", Тов);
    глФлагРасшифровки = 1;
    ОткрытьФорму("Отчет.ИсторияТов", );
КонецПроцедуры

Способ 2. Принудительная активизация метода Показать()

Если ваш отчет формирует печатную форму в виде объекта Таблица, проанализируем синтаксис системного метода вывода таблицы:

Показать(<Заголовок>, <ИмяФайла>, <Активизировать>)

Обратим внимание на третий параметр — <Активизировать>. Он принимает числовые значения:

Несмотря на то, что единица установлена по умолчанию, в некоторых релизах платформы явное указание этого параметра заставляет операционную систему корректно перестроить порядок отображения окон (Z-order). Попробуйте переписать код вывода таблицы следующим образом:

Таб.Показать("История движения товара", , 1);

Способ 3. Использование модального режима

Если бизнес-логика позволяет заблокировать интерфейс программы до тех пор, пока пользователь не закроет отчет, лучшим решением будет использование модального окна. Модальные формы всегда открываются поверх всех остальных окон и не позволяют переключить фокус на родительский документ.

Для реализации этого подхода используем метод ОткрытьФормуМодально:

ОткрытьФормуМодально("Отчет.ИсторияТов", КонтекстПараметров);

Аналогия в современных версиях платформы (1С:Предприятие 8.x)

Для разработчиков, которые переходят с платформы 1С 7.7 на управляемые формы 1С 8.3, будет полезно знать, что эта концепция сохранилась практически без изменений, но стала более структурированной. В событиях выбора (например, при двойном клике по ячейке динамического списка или табличной части) всегда доступен параметр СтандартнаяОбработка.

Установив его в значение Ложь, вы запрещаете платформе выполнять штатные действия по перехвату фокуса. Пример на управляемых формах 1С 8.3:


&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    // Отключаем стандартное поведение (аналог фсо = 0 в 7.7)
    СтандартнаяОбработка = Ложь; 
    
    // Открываем свою форму или отчет поверх текущего окна
    ПараметрыФормы = Новый Структура("Ключ", ВыбраннаяСтрока);
    ОткрытьФорму("Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента", ПараметрыФормы);
КонецПроцедуры

Резюме

Мы подробно разобрали проблему скрытия окон таблиц и отчетов под форму документа в 1С 7.7. Использование флага стандартной обработки фсо = 0 в компоненте FormEx является наиболее элегантным решением. В случае отсутствия внешних компонент используйте надежный метод отложенного вызова через ОбработкаОжидания().

← На главную