Как исправить блокировку кнопок печати при открытии печатных форм из модальных окон в 1С

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При работе с обычными (неуправляемыми) формами в 1С:Предприятие 8.2 или 8.3 программисты часто сталкиваются с неприятной особенностью: если открыть вспомогательное окно модально, а затем из него попытаться вызвать печать документа, кнопки «Печать» и «Предварительный просмотр» на стандартной панели инструментов становятся недоступными (серыми). Это происходит потому, что модальное окно блокирует весь интерфейс приложения, включая командные панели, которые не принадлежат самому окну.

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

Почему пропадают кнопки в печатной форме?

Давайте проанализируем ситуацию. В обычном интерфейсе (например, в конфигурации «Управление торговлей 10.3») модальность работает по принципу «стека». Когда мы вызываем метод ОткрытьФормуМодально(), поток выполнения кода останавливается, а всё приложение, кроме этого окна, перестает реагировать на действия пользователя.

Если из этой модальной формы вызывается процедура печати (например, через типовой механизм УниверсальныеМеханизмы.НапечататьДокумент()), создаваемое окно с табличным документом автоматически наследует состояние модальности. Поскольку стандартные кнопки печати в обычном интерфейсе вынесены на общую командную панель программы (верхнее меню), они оказываются заблокированными текущим модальным состоянием. Пользователь может нажать Ctrl+P, но визуально интерфейс выглядит нерабочим, что вызывает закономерные вопросы у клиентов.

Решение №1: Переход к «псевдомодальности»

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

Вместо использования ОткрытьФормуМодально() мы откроем форму обычным способом, но программно запретим пользователю переключаться на форму-владелец. Для этого выполним следующий алгоритм:

  1. В вызывающей форме (например, в документе) при открытии вспомогательного окна устанавливаем свойство Доступность в значение Ложь.
  2. Открываем вспомогательную форму немодально, передавая текущую форму в качестве владельца.
  3. При закрытии вспомогательной формы возвращаем доступность владельцу.

Рассмотрим пример кода для основной формы:


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

Теперь в самой вспомогательной форме в обработчике события ПриЗакрытии нам нужно вернуть управление основной форме:


Процедура ПриЗакрытии()
    Если ВладелецФормы <> Неопределено Тогда
        ВладелецФормы.Доступность = Истина;
        // Активируем форму владельца, чтобы она вышла на передний план
        ВладелецФормы.Активизировать();
    КонецЕсли;
КонецПроцедуры

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

Решение №2: Использование обработчика ожидания (Таймер)

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

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

Алгоритм действий в модальной форме:

  1. Пользователь нажимает кнопку «Печать».
  2. Программа сохраняет необходимые параметры печати в переменные модуля или структуры.
  3. Запускается обработчик ожидания с минимальным интервалом (0.1 сек).
  4. Модальная форма закрывается командой Закрыть().
  5. Срабатывает процедура таймера, которая вызывает УниверсальныеМеханизмы.НапечататьДокумент().

Пример реализации:


Перем СтруктураПараметровПечати;

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

Процедура ВыполнитьПечатьПослеЗакрытия() Экспорт
    УниверсальныеМеханизмы.НапечататьДокумент(СтруктураПараметровПечати.Объект, ...);
КонецПроцедуры

Решение №3: Обработка оповещений

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

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

В основной форме (владельце):


Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    Если ИмяСобытия = "ПечатьЗавершена" Тогда
        // Здесь обрабатываем данные, которые вернула форма
        ПоказатьОповещениеПользователя("Печать выполнена для: " + Параметр);
    КонецЕсли;
КонецПроцедуры

Во вспомогательной форме:


Процедура ВыполнитьПечать()
    // Логика печати...
    Оповестить("ПечатьЗавершена", СписокДокументов);
КонецПроцедуры

Безопасность и «подстилание соломы»

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

Если установить ЗакрыватьПриЗакрытииВладельца = Истина для вспомогательной формы, система автоматически очистит цепочку окон. Также важно проверять состояние объекта перед выполнением процедур. Например, если вы печатаете данные из объекта, который может быть изменен в основной форме, пока открыто вспомогательное окно, стоит принудительно устанавливать ТолькоПросмотр = Истина для владельца на время работы с дополнительным функционалом.

Резюмируем: Истинная модальность в обычном интерфейсе 1С 8 — это инструмент, который стоит использовать с осторожностью. Если ваша задача предполагает вывод на экран дополнительных окон (таких как табличные документы), использование Доступность = Ложь в сочетании с немодальным открытием является наиболее стабильным и профессиональным решением, исключающим блокировку пользовательского интерфейса.

← На главную