При разработке функционала в режиме «Обычное приложение» (толстый клиент, обычные формы) на платформе 1С:Предприятие 8.3 нередко возникает задача: пользователь интерактивно открывает определенную обработку (встроенную или внешнюю .epf), а системе требуется зафиксировать факт открытия и выполнить экспортные методы модуля объекта этого конкретного экземпляра.
Разработчики, привыкшие к управляемым формам и интерфейсу «Такси», часто пытаются использовать метод ПолучитьОкна() или объект ОкнаКлиентскогоПриложения. Однако в обычном приложении этот механизм недоступен. Разберем особенности архитектуры толстого клиента, выясним причину ограничений и детально рассмотрим надежные способы решения поставленной задачи.
Проанализируем ключевые различия между управляемым и обычным приложением в контексте работы с формами обработок:
ЭтотОбъект (а также ОбработкаОбъект), которое возвращает прямую ссылку на экземпляр ОбработкаОбъект.<Имя> или ВнешняяОбработкаОбъект.<Имя>.ПолучитьОкна() появился для управляемого интерфейса. В обычных формах отслеживание открытых окон реализуется либо через события форм, либо через регистрацию экземпляров в общих модулях.Рассмотрим несколько практических вариантов реализации взаимодействия с открытой обработкой.
Разберем по шагам самый простой и прямой способ: при интерактивном открытии обработка сама регистрирует свой экземпляр в общедоступном месте, а при закрытии — очищает ссылку.
Создадим или выберем клиентский общий модуль (например, КонтекстСеансаКлиент) с признаком Клиент (обычное приложение) и объявим в нем экспортную переменную:
// Общий модуль: КонтекстСеансаКлиент
Перем ОткрытыйЭкземплярОбработки Экспорт;
Теперь обратимся к модулю формы самой обработки. В обработчиках событий ПриОткрытии и ПриЗакрытии пропишем регистрацию объекта:
// Модуль обычной формы обработки
Процедура ПриОткрытии()
// Сохраняем ссылку на объект обработки в глобальную переменную
КонтекстСеансаКлиент.ОткрытыйЭкземплярОбработки = ЭтотОбъект;
// Если нужно выполнить экспортный метод объекта сразу при открытии:
ЭтотОбъект.МойЭкспортныйМетод();
КонецПроцедуры
Процедура ПриЗакрытии()
// Очищаем ссылку при закрытии формы, чтобы избежать утечек памяти
КонтекстСеансаКлиент.ОткрытыйЭкземплярОбработки = Неопределено;
КонецПроцедуры
Посмотрим на пример вызова экспортного метода открытой обработки из любого другого места конфигурации (из другой формы, меню или общего модуля):
// Вызов из внешнего контекста (например, по нажатию кнопки в другой форме)
Если КонтекстСеансаКлиент.ОткрытыйЭкземплярОбработки <> Неопределено Тогда
// Объект открыт интерактивно, вызываем его метод
КонтекстСеансаКлиент.ОткрытыйЭкземплярОбработки.МойЭкспортныйМетод();
Иначе
Сообщить("Обработка в данный момент не открыта пользователем!");
КонецЕсли;
Рассмотрим более гибкий подход с использованием механизма слабой связанности. В этом случае внешнему коду не нужно хранить прямую ссылку на объект обработки — достаточно послать оповещение в систему.
Разберем реализацию по шагам:
ОбработкаОповещения.ЭтотОбъект.ИмяМетода() при получении целевого события.Оповестить(). Если форма открыта — метод выполнится, если закрыта — оповещение пройдет бесследно.Посмотрим на программный код в модуле формы обработки:
// Модуль формы обработки
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ВыполнитьДействиеВОткрытойОбработке" Тогда
// Вызываем экспортную процедуру модуля объекта
ЭтотОбъект.МойЭкспортныйМетод(Параметр);
КонецЕсли;
КонецПроцедуры
В вызывающем коде отправляем команду через глобальный метод платформы 1С:
// Вызывающий модуль
ПараметрыВызова = Новый Структура;
ПараметрыВызова.Вставить("ДатаСобытия", ТекущаяДата());
ПараметрыВызова.Вставить("Пользователь", ИмяПользователя());
Оповестить("ВыполнитьДействиеВОткрытойОбработке", ПараметрыВызова, "ГлавнаяФорма");
Проанализируем ситуацию, когда обработка является внешней (файл .epf), открывается пользователем через системное меню «Файл -> Открыть», и нам необходимо получить именно открытую форму или экземпляр объекта.
В обычной форме внешней обработки свойство ИспользуемоеИмяФайла содержит полный путь к файлу на диске. Рассмотрим пример сохранения информации о файле и повторного обращения к открытой форме:
// Модуль формы внешней обработки
Процедура ПриОткрытии()
// ИспользуемоеИмяФайла содержит путь к .epf файлу
ПутьКФайлу = ЭтотОбъект.ИспользуемоеИмяФайла;
// Регистрируем открытый файл в общем соответствии открытых обработок
КонтекстСеансаКлиент.РегистрироватьОткрытуюОбработку(ПутьКФайлу, ЭтаФорма);
КонецПроцедуры
Если нам требуется получить существующую форму внешней обработки, используем метод ВнешниеОбработки.ПолучитьФорму():
// Получение ссылки на форму уже открытой внешней обработки
ПутьКФайлу = "C:\Обработки\МояОбработка.epf";
ФормаОбработки = ВнешниеОбработки.ПолучитьФорму(ПутьКФайлу, "Форма");
Если ФормаОбработки.Открыта() Тогда
// Доступ к объекту обработки через форму
ОбъектОбработки = ФормаОбработки.ЭтотОбъект;
ОбъектОбработки.МойЭкспортныйМетод();
КонецЕсли;
Подведем итоги анализа рассмотренных способов:
ЭтотОбъект из ПриОткрытии: Идеально подходит, если экспортный метод должен вызываться сразу же в момент интерактивного открытия самой формы.Оповестить() / ОбработкаОповещения(): Наиболее надежный и безопасный вариант взаимодействия между несвязанными формами, исключающий появление «зависших» ссылок в оперативной памяти сеанса.