Как в 1С 7.7 получить список открытых окон и закрыть неактивное окно с помощью FormEx?

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

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

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

Основные методы объекта «Сервис» для работы с окнами

Для управления формами компонента FormEx предоставляет объект Сервис, содержащий следующие ключевые методы:

  1. СписокВсехОткрытыхОкон() — возвращает объект типа СписокЗначений. Значениями элементов этого списка являются контексты открытых форм, а их строковыми представлениями — системные заголовки окон.
  2. АктивныйКонтекст(Контекст) — определяет текущее активное окно. Метод принимает переменную по ссылке, в которую помещается контекст активной формы, и возвращает 1 в случае успеха или 0, если активного/контекстного окна нет.

Посмотрим на базовый пример получения активного окна и его закрытия:


Процедура ЗакрытьАктивноеОкно()
    Перем Конт;
    Сервис = СоздатьОбъект("Сервис");
    Если Сервис.АктивныйКонтекст(Конт) = 1 Тогда
        Конт.Форма.Закрыть(0);
    Иначе
        Сообщить("Активное окно не является контекстным или нет активного окна.");
    КонецЕсли;
КонецПроцедуры

Способ 1. Закрытие всех неактивных окон

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


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

Способ 2. Поиск и закрытие неактивного окна по названию (заголовку)

Выясним причину, почему прямой перебор коллекции с закрытием форм может вести себя некорректно. Когда мы закрываем окно методом Форма.Закрыть(0), внутренний список открытых окон платформы перестраивается. Чтобы безопасно обработать заголовки и закрыть только те окна, название которых содержит определенную подстроку, используем извлечение строкового представления через метод ПолучитьЗначение().

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


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

Особенности и нюансы при работе с окнами в 1С 7.7

Проанализируем практические ситуации, с которыми можно столкнуться при использовании данного подхода:

  1. Обратный порядок обхода (Для Индекс = -РС По -1): при закрытии окна список активных дескрипторов меняется. Обход списка с конца к началу исключает смещение индексов еще не обработанных окон.
  2. Конфликты в процедуре ПриВыбореСтроки: если в форме списка справочника прописано жесткое открытие формы элемента (ОткрытьФорму(ТекущийЭлемент())), то в режиме выбора открываются одновременно две формы. Попытка закрыть окно непосредственно в момент его инициализации (например, через вызов формулы реквизита на форме) может привести к блокировке родительского окна.
  3. Модальные диалоги: модальные окна блокируют поток выполнения кода. Закрыть модальное окно через контекст другого диалога невозможно до тех пор, пока модальный режим не будет завершен пользователем или системным событием.
  4. Использование расширения формы: для управления параметрами отображения окон можно также использовать объект РасширениеФормы из состава FormEx, связывая его с контекстом окна через РасшФ.УстановитьФорму(КонтФормы.Форма).
← На главную