Как в обычных формах отловить закрытие подчиненной формы без изменения ее кода

Программист 1С v8.3 (Обычные формы)
← На главную

При разработке в среде 1С:Предприятие 8 на базе обычных форм программисты часто сталкиваются с задачей: нужно открыть форму (например, типового отчета или документа), дождаться, пока пользователь завершит с ней работу, и после ее закрытия выполнить определенные действия в исходной обработке. Ситуация осложняется, когда код открываемой формы менять нельзя (например, это типовой объект конфигурации на поддержке). Рассмотрим, как решить эту задачу, используя стандартные механизмы платформы.

Проблема использования стандартных событий

В управляемых формах (так называемый «Такси» или УФ) для подобных целей существует параметр ОписаниеОповещенияОЗакрытии. В обычных же формах такой механизм отсутствует. Попытки передать в структуру параметров экспортную процедуру, как это пробовал сделать автор темы, не увенчаются успехом: система просто проигнорирует этот параметр, так как механизм обратного вызова (callback) в старом интерфейсе не реализован на уровне ядра.

Разберем два рабочих сценария решения этой проблемы.

Метод 1: Использование модального режима открытия

Это самый простой и надежный способ «остановить» выполнение кода в основной обработке до момента закрытия вызванного окна. Рассмотрим этот метод на примере кода автора, когда нужно выбрать документ и открыть его форму.

Алгоритм действий:

  1. Получаем форму выбора документа.
  2. Открываем ее модально, чтобы получить выбранный объект.
  3. Получаем форму конкретного документа.
  4. Открываем форму документа методом ОткрытьМодально().

Проанализируем пример кода:


Процедура КнопкаВыполнитьНажатие(Кнопка)
    // 1. Получаем и настраиваем форму выбора
    ФормаВыбора = Документы.РегламентированныйОтчет.ПолучитьФормуВыбора();
    ФормаВыбора.ДокументСписок.Отбор.НаименованиеОтчета.ВидСравнения = ВидСравнения.Равно;
    ФормаВыбора.ДокументСписок.Отбор.НаименованиеОтчета.Значение = "Декларация по НДС";
    ФормаВыбора.ДокументСписок.Отбор.НаименованиеОтчета.Установить();
    
    // 2. Открываем форму выбора модально
    ВыбДок = ФормаВыбора.ОткрытьМодально();
    
    Если ЗначениеЗаполнено(ВыбДок) Тогда
        // 3. Получаем форму самого документа
        ФормаДок = ВыбДок.ПолучитьФорму();
        
        // 4. Открываем форму документа МОДАЛЬНО
        // Выполнение кода ПРИОСТАНОВИТСЯ на этой строке
        ФормаДок.ОткрытьМодально();
        
        // 5. Этот код выполнится ТОЛЬКО ПОСЛЕ ЗАКРЫТИЯ формы ФормаДок
        Сообщить("Форма была закрыта. Выполняем действия по сохранению...");
        // Здесь можно вызвать процедуру записи или оповещения
        ВыполнитьДействияПослеЗакрытия();
    КонецЕсли;
КонецПроцедуры

Преимущества: Простота реализации. Код выполняется последовательно, не нужно использовать дополнительные переменные или таймеры.

Недостатки: Модальный режим блокирует весь интерфейс 1С. Пользователь не сможет переключиться на другое окно программы, пока не закроет форму отчета.

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

Если блокировка интерфейса недопустима, нам придется использовать «немодальное» открытие в связке с периодической проверкой состояния формы. Для этого мы будем использовать свойство формы Открыта().

Разберем по шагам, как это реализовать:

  1. Объявим переменную на уровне модуля формы, чтобы ссылка на открытую форму не «умерла» после завершения процедуры открытия.
  2. Откроем форму обычным методом Открыть().
  3. Подключим обработчик ожидания, который будет раз в секунду проверять, открыто ли окно.

Рассмотрим пример реализации в модуле обработки:


Перем СсылкаНаФормуПодчиненную; // Переменная в начале модуля

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

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

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

Важный нюанс: Процедура ПроверитьЗакрытиеФормы обязательно должна иметь признак Экспорт, иначе глобальный контекст не сможет ее вызвать по таймеру.

Сравнение методов ОткрытьФорму и ПолучитьФорму

Выясним причину, почему в коде автора возникали сложности. Автор использовал ОткрытьФорму, которая является методом глобального контекста. Для решения нашей задачи гораздо эффективнее использовать ПолучитьФорму.

Когда мы вызываем ПолучитьФорму, мы получаем объект типа Форма, с которым можем работать как с объектом: проверять его свойства (Открыта()), программно менять заголовок или состав кнопок перед открытием. При использовании ОткрытьФорму мы сразу «выбрасываем» окно на экран и теряем гибкий контроль над ним.

Почему не работают Оповещения?

Механизм Оповестить() и ОбработкаОповещения часто путают с механизмом возврата результата. Чтобы оповещение сработало, внутри подчиненной формы в событии ПриЗакрытии должен быть написан код:

Оповестить("ЗакрытиеФормыОтчета", Параметры);

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

Резюме

Для «отлова» закрытия чужой формы в обычных формах 1С 8.3:

← На главную