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