В практике разработки на платформе 1С (особенно при работе с обычными формами) часто возникает сложная задача: как программно закрыть окно, которое было открыто модально? Главная трудность заключается в самой природе модальности — как только вызывается метод ОткрытьМодально(), выполнение кода в вызывающем модуле полностью останавливается до тех пор, пока пользователь не закроет форму вручную. Однако существуют сценарии, например, в обработчиках ожидания или при автоматическом завершении сеанса, когда систему нужно заставить закрыть это окно принудительно.
В данной статье мы разберем несколько эффективных стратегий, которые позволят нам управлять жизненным циклом модального окна извне или "научить" саму форму закрываться по определенному событию.
Один из самых надежных штатных способов взаимодействия между различными объектами интерфейса — это использование метода Оповестить(). Рассмотрим ситуацию: у нас открыто модальное окно, и мы хотим закрыть его из другого фонового процесса (например, из обработчика ожидания в глобальном модуле или модуле обычного приложения).
Для того чтобы этот способ сработал, нам необходимо заранее подготовить модальную форму. Мы должны прописать логику закрытия внутри самой формы, так как именно она "слышит" события системы, пока основной код стоит на паузе. Разберем шаги реализации:
Пример кода в модуле модальной формы:
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
// Проверяем, что пришло именно наше техническое уведомление
Если ИмяСобытия = "ПринудительноеЗакрытиеОкон" Тогда
ЭтаФорма.Закрыть();
КонецЕсли;
КонецПроцедуры
Теперь, когда нам потребуется закрыть это окно программно из любого другого места (например, из модуля обычного приложения), мы просто вызываем команду оповещения:
Оповестить("ПринудительноеЗакрытиеОкон");
Важный нюанс: Оповещение должно отправляться в том же сеансе. Обратите внимание, что в обычных формах обработчик ОбработкаОповещения в модальной форме продолжает работать, что и позволяет нам реализовать эту логику.
Проанализируем другую ситуацию: нам нужно закрыть окно не по внешнему сигналу Оповестить, а при наступлении определенного условия в базе данных (например, изменился статус документа или появилась запись в регистре). В этом случае мы можем заставить форму "саму проверять", не пора ли ей закрыться.
Рассмотрим по шагам, как это реализовать:
ПриОткрытии модальной формы подключим обработчик ожидания.Пример кода в модуле модальной формы:
Процедура ПриОткрытии()
// Запускаем проверку каждые 2 секунды
ПодключитьОбработчикОжидания("ПроверитьУсловиеЗакрытия", 2);
КонецПроцедуры
Процедура ПроверитьУсловиеЗакрытия()
// Логика проверки, например, значение в хранилище настроек или константе
НужноЗакрыть = ПроверитьНеобходимостьЗакрытияНаСервере();
Если НужноЗакрыть Тогда
Отказ = Ложь;
ЭтаФорма.Закрыть();
КонецЕсли;
КонецПроцедуры
Этот метод считается одним из самых "чистых" с точки зрения архитектуры 1С, так как он не зависит от работы глобальных событий и позволяет форме самостоятельно управлять своим состоянием.
Если штатные методы 1С по какой-то причине недоступны (например, код в форме заблокирован длительным вычислением), мы можем обратиться к средствам операционной системы. Проанализируем ситуацию, когда нам нужно найти окно 1С по заголовку и отправить ему команду закрытия через Wscript.Shell или WinAPI.
Хотя метод SendKeys("{ESC}") часто упоминается на форумах, он крайне нестабилен, так как требует, чтобы нужное окно было в фокусе. Более надежный вариант — использование внешних компонент или скриптов, которые находят дескриптор окна (HWND) по заголовку и посылают сообщение WM_CLOSE.
Пример логики на VBScript (вызывается через 1С):
Set shell = CreateObject("WScript.Shell")
' Попытка активировать окно с конкретным заголовком
Если shell.AppActivate("Внимание! Технические работы") Тогда
shell.SendKeys "%{F4}" ' Отправка Alt+F4 для закрытия
КонецЕсли;
Рассмотрим этот способ только как крайнюю меру, так как он сильно зависит от окружения пользователя и прав доступа к процессам ОС.
Выясним причину, по которой нам вообще потребовалось модальное окно. Если цель — просто привлечь внимание пользователя и заблокировать интерфейс, современные стандарты разработки 1С рекомендуют отказываться от жесткой модальности в пользу режима "Блокировать весь интерфейс" или использования немодальных форм с флагом ПоверхВсехОкон.
Рассмотрим альтернативу:
ОткрытьМодально() используйте открытие формы с параметром РежимОткрытияОкнаФормы.БлокироватьВесьИнтерфейс (для управляемых форм) или программную блокировку владельца.Состояние(). Окно состояния легко закрывается программно простым вызовом Состояние("").Мы разобрали основные подходы к программному управлению модальными окнами. Подведем итоги:
ОбработкаОповещения внутри самой модальной формы. Это позволяет внешним событиям "достучаться" до заблокированного потока кода.Используя эти приемы, вы сможете сделать интерфейс вашего приложения более гибким и отзывчивым, избегая "зависших" окон, которые мешают выполнению регламентных операций или обновлению системы.