Как определить активную форму внутри окна клиентского приложения 1С

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

В процессе разработки сложных интерфейсов на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда внутри одного основного окна приложения открыто несколько форм. Это типично для рабочих мест, где формы открываются через панель навигации или программно вкладываются в содержимое основного окна. Возникает закономерный вопрос: как программно понять, с какой именно формой из массива Содержимое в данный момент взаимодействует пользователь?

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

Понимание структуры окна клиентского приложения

Для начала проанализируем архитектуру окон в управляемом приложении. Когда мы обращаемся к свойству ЭтотОбъект.Окно или используем метод АктивноеОкно(), платформа возвращает объект типа ОкноКлиентскогоПриложения. Внутри этого объекта находится свойство Содержимое, которое представляет собой ФиксированныйМассив ссылок на формы.

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

Способ 1. Использование свойства АктивнаяФорма

Наиболее правильным и штатным способом решения задачи является обращение к свойству АктивнаяФорма объекта ОкноКлиентскогоПриложения. В отличие от перебора массива Содержимое, это свойство напрямую указывает на форму, которая в данный момент выбрана пользователем.

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


// Получаем основное окно приложения
Окна = ПолучитьОкнаКлиентскогоПриложения();
Для Каждого ТекущееОкно Из Окна Цикл
    Если ТекущееОкно.Основное Тогда
        // Обращаемся к свойству АктивнаяФорма
        АктивнаяФорма = ТекущееОкно.АктивнаяФорма;
        
        Если АктивнаяФорма <> Неопределено Тогда
            Сообщить("В данный момент активна форма: " + АктивнаяФорма.Заголовок);
        КонецЕсли;
        Прервать;
    КонецЕсли;
КонецЦикла;

Этот метод надежен, так как он опирается на внутренние механизмы платформы по отслеживанию фокуса. Если свойство возвращает Неопределено, это означает, что в данный момент ни одна форма внутри окна не является активной (например, фокус на системном меню или дереве функций).

Способ 2. Глобальный перебор через АктивноеОкно

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

Разберем по шагам, как добраться до нужных данных:

  1. Вызываем АктивноеОкно() для получения текущего активного контейнера.
  2. Проверяем, не является ли результат Неопределено (например, если приложение свернуто).
  3. Обращаемся к свойству АктивнаяФорма найденного окна.

ТекущееОкно = АктивноеОкно();
Если ТекущееОкно <> Неопределено Тогда
    ТекущаяФорма = ТекущееОкно.АктивнаяФорма;
    // Теперь у нас есть прямая ссылка на форму из массива Содержимое
КонецЕсли;

Способ 3. Использование события ПриАктивизации

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

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


// В модуле каждой формы, находящейся в массиве "Содержимое"
&НаКлиенте
Процедура ПриАктивизации()
    // Сохраняем ссылку на текущую форму в глобальный контекст
    ПараметрыКлиента = Новый Структура("ПоследняяАктивнаяФорма", ЭтаФорма);
    // Например, передаем информацию в модуль управляемого приложения
    УстановитьГлобальныйПараметр(ПараметрыКлиента);
КонецПроцедуры

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

Способ 4. Проверка через ТекущийЭлемент

Если мы находимся в контексте выполнения кода внутри одной из форм и хотим убедиться, что именно наша форма сейчас "в фокусе" у пользователя, можно использовать проверку свойства ТекущийЭлемент. У активной формы, с которой взаимодействуют в данный момент, свойство ЭтаФорма.ТекущийЭлемент практически всегда содержит ссылку на какой-либо элемент управления (кнопку, поле ввода, таблицу).

Рассмотрим логику проверки:


&НаКлиенте
Функция ЯвляетсяЛиФормаАктивной()
    // Если ввод доступен и есть активный элемент - форма точно активна
    Возврат ВводДоступен() И ЭтаФорма.ТекущийЭлемент <> Неопределено;
КонецФункции

Почему метод ВводДоступен() может подводить?

Проанализируем ситуацию, описанную в обсуждении: почему ВводДоступен() возвращал Ложь для всех форм в массиве? В архитектуре 1С управляемые формы, вложенные в основное окно, могут терять статус "доступности ввода" с точки зрения платформы, если фокус перемещен на командный интерфейс или вспомогательные панели. Тем не менее, форма остается выбранной в ОкноКлиентскогоПриложения. Именно поэтому связка Окно.АктивнаяФорма является более приоритетной и точной.

Резюме

Для определения активной формы в объекте ОкноКлиентскогоПриложения мы рекомендуем следовать следующим правилам:

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

← На главную