В процессе разработки на платформе «1С:Предприятие 8.3» часто возникает задача управления уже открытыми формами. Например, при работе в расширении нам может потребоваться изменить поведение стандартной формы подбора товаров, не изменяя при этом типовой код вызова. Рассмотрим подробно, как работает механизм уникальности форм, почему платформа иногда создает новые экземпляры вместо активации существующих и как решить задачу программного поиска открытого окна.
Разберем, как платформа 1С понимает, что форму нужно не создавать заново, а найти уже открытую. Поиск происходит по совокупности трех факторов: имени формы, владельцу и набору ключевых параметров.
Проанализируем понятие «ключевые параметры». В редакторе формы на закладке «Параметры» у каждого элемента есть свойство Ключевой. Если этот флаг установлен, значение данного параметра учитывается при поиске. Если при вызове ОткрытьФорму передается структура параметров, где значения всех «ключевых» полей совпадают с уже открытой формой, платформа активизирует старое окно.
Важный нюанс для обработок: в отличие от справочников или документов, у них нет стандартного параметра Ключ (ссылки). Чтобы обеспечить уникальность конкретного экземпляра формы обработки, разработчику нужно либо вручную пометить один из параметров как ключевой в конфигураторе, либо использовать параметр Ключ в структуре (даже если он не описан в метаданных, платформа может использовать его для идентификации).
Посмотрим на четвертый параметр функции ОткрытьФорму. Именно он часто становится причиной путаницы. Рассмотрим возможные значения:
Часто в типовых конфигурациях (например, в УТ 11.4) в этот параметр передается УникальныйИдентификатор самой формы-владельца. Это делается для того, чтобы подбор был уникальным именно для конкретного документа «Чек ККМ» или «Реализация».
Выясним причину, по которой даже при совпадении всех идентификаторов платформа может открыть новое окно. Обратим внимание на важное свойство: РежимОткрытияОкнаФормы. Если форма открыта с режимом БлокироватьОкноВладельца или БлокироватьВесьИнтерфейс, она автоматически исключается из поиска.
Это сделано для безопасности интерфейса: блокирующие окна считаются временными и модальными по своей сути, поэтому платформа не позволяет «перехватывать» их через стандартные механизмы поиска форм. Если форма подбора в вашем решении открывается как блокирующая, метод ОткрытьФорму всегда будет создавать новый экземпляр.
Если стандартный механизм поиска не подходит, рассмотрим «тяжелый», но надежный способ — перебор всех открытых окон клиентского приложения. Этот метод работает в управляемом приложении и позволяет найти форму по её содержимому.
Проанализируем пример кода для поиска и закрытия (или активации) нужной формы:
Окна = ПолучитьОкна();
Для Каждого Окно Из Окна Цикл
Содержимое = Окно.Содержимое;
Для Каждого ЭлементСодержимого Из Содержимое Цикл
// Проверяем, является ли элемент формой и совпадает ли имя
Если ТипЗнч(ЭлементСодержимого) = Тип("УправляемаяФорма")
И ЭлементСодержимого.ИмяФормы = "Обработка.ПодборТоваровВДокументПродажи.Форма" Тогда
// Здесь можно активировать форму
ЭлементСодержимого.Активизировать();
// Или закрыть её, если нужно открыть заново с новыми параметрами
// ЭлементСодержимого.Закрыть();
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Стоит помнить, что в режиме обычного приложения функция ПолучитьОкна() может возвращать Неопределено, однако для современных конфигураций на управляемых формах это основное решение для глобального поиска.
Если платформа успешно нашла форму, управление передается в обработчик ПриПовторномОткрытии(СтандартнаяОбработка, Параметры). Это критически важная точка расширения. Рассмотрим ситуацию: форма уже открыта, пользователь нажимает кнопку подбора еще раз, но с другими фильтрами. Вместо создания нового окна мы можем поймать переданные параметры и обновить текущую форму.
Важный нюанс: в этом событии доступны только те параметры, которые помечены как «Ключевые». Используйте их для изменения бизнес-логики без перезагрузки интерфейса.
В контексте задачи автора (изменение параметра СкрыватьКолонкуВидЦены в Чеке ККМ), наиболее правильным и изящным способом будет не попытка «переоткрыть» форму в &После, а перехват события создания самой формы обработки. Это позволяет не дублировать вызовы ОткрытьФорму.
Разберем реализацию в расширении для формы обработки ПодборТоваровВДокументПродажи:
&НаСервере
Процедура ИЧ_ПриСозданииНаСервереПеред(Отказ, СтандартнаяОбработка)
// Проверяем контекст вызова: открыт ли подбор из Чека ККМ
Если ТипЗнч(Параметры.Документ) = Тип("ДокументСсылка.ЧекККМ") Тогда
// Устанавливаем нужное нам значение параметра
Параметры.СкрыватьКолонкуВидЦены = Ложь;
КонецЕсли;
// Также здесь можно проверить права пользователя
Если Пользователи.РолиДоступны("ПолныеПрава") Тогда
Параметры.СкрыватьКолонкуВидЦены = Ложь;
КонецЕсли;
КонецПроцедуры
Такой подход гарантирует, что при открытии формы (независимо от того, как отработал механизм поиска) параметры будут скорректированы до того, как элементы интерфейса будут отрисованы на экране. Это избавляет от необходимости искать уже открытое окно и манипулировать им извне.
Для успешного управления формами всегда проверяйте:
ОткрытьФорму.Если же цель — модификация поведения типовой формы, используйте возможности расширений и перехватывайте событие ПриСозданииНаСервере, что является более стабильным методом, чем ручной поиск окон.