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