Как программно закрыть модальное окно в 1С?

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

В практике разработки на платформе 1С (особенно при работе с обычными формами) часто возникает сложная задача: как программно закрыть окно, которое было открыто модально? Главная трудность заключается в самой природе модальности — как только вызывается метод ОткрытьМодально(), выполнение кода в вызывающем модуле полностью останавливается до тех пор, пока пользователь не закроет форму вручную. Однако существуют сценарии, например, в обработчиках ожидания или при автоматическом завершении сеанса, когда систему нужно заставить закрыть это окно принудительно.

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

Способ 1. Использование механизма оповещений

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

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

  1. В модуле открываемой модальной формы создадим процедуру-обработчик оповещения.
  2. В этой процедуре будем проверять имя события.

Пример кода в модуле модальной формы:


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

Теперь, когда нам потребуется закрыть это окно программно из любого другого места (например, из модуля обычного приложения), мы просто вызываем команду оповещения:

Оповестить("ПринудительноеЗакрытиеОкон");

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

Способ 2. Обработчик ожидания внутри модальной формы

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

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

  1. В процедуре ПриОткрытии модальной формы подключим обработчик ожидания.
  2. В самой процедуре обработчика пропишем проверку условия.

Пример кода в модуле модальной формы:


Процедура ПриОткрытии()
    // Запускаем проверку каждые 2 секунды
    ПодключитьОбработчикОжидания("ПроверитьУсловиеЗакрытия", 2);
КонецПроцедуры

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

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

Способ 3. Использование Windows API (для продвинутых случаев)

Если штатные методы 1С по какой-то причине недоступны (например, код в форме заблокирован длительным вычислением), мы можем обратиться к средствам операционной системы. Проанализируем ситуацию, когда нам нужно найти окно 1С по заголовку и отправить ему команду закрытия через Wscript.Shell или WinAPI.

Хотя метод SendKeys("{ESC}") часто упоминается на форумах, он крайне нестабилен, так как требует, чтобы нужное окно было в фокусе. Более надежный вариант — использование внешних компонент или скриптов, которые находят дескриптор окна (HWND) по заголовку и посылают сообщение WM_CLOSE.

Пример логики на VBScript (вызывается через 1С):


Set shell = CreateObject("WScript.Shell")
' Попытка активировать окно с конкретным заголовком
Если shell.AppActivate("Внимание! Технические работы") Тогда
    shell.SendKeys "%{F4}" ' Отправка Alt+F4 для закрытия
КонецЕсли;

Рассмотрим этот способ только как крайнюю меру, так как он сильно зависит от окружения пользователя и прав доступа к процессам ОС.

Способ 4. Переход к "псевдомодальности"

Выясним причину, по которой нам вообще потребовалось модальное окно. Если цель — просто привлечь внимание пользователя и заблокировать интерфейс, современные стандарты разработки 1С рекомендуют отказываться от жесткой модальности в пользу режима "Блокировать весь интерфейс" или использования немодальных форм с флагом ПоверхВсехОкон.

Рассмотрим альтернативу:

Итоги и рекомендации

Мы разобрали основные подходы к программному управлению модальными окнами. Подведем итоги:

  1. Самый надежный метод — использование ОбработкаОповещения внутри самой модальной формы. Это позволяет внешним событиям "достучаться" до заблокированного потока кода.
  2. Метод с обработчиком ожидания идеален, если форма должна закрыться при изменении данных в информационной базе.
  3. Альтернативные интерфейсные решения (немодальные окна) позволяют избежать проблем с блокировкой кода в принципе, что является "best practice" в современной разработке.

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

← На главную