Как в 1С 7.7 программно открыть форму подчиненного справочника поверх всех окон?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При разработке конфигураций на платформе 1С:Предприятие 7.7 программисты часто сталкиваются со специфическим поведением интерфейса, которое может запутать даже опытного разработчика. Типичный пример такой ситуации — программное открытие формы списка подчиненного справочника (например, справочника «Контракты», подчиненного справочнику «Клиенты») для выбора элемента в документ. Вы используете стандартный метод ОткрытьПодбор(), форма подчиненного справочника успешно открывается с нужным фильтром, но вместо того чтобы отобразиться поверх всех окон, она мгновенно уходит на задний план, прячась за открытым окном документа.

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

Выясняем причину: почему окно уходит на задний план?

Давайте проанализируем поведение платформы 1С 7.7 изнутри. Допустим, на форме документа у нас есть реквизит «Клиент», а в его свойствах (в поле «Формула») прописан вызов пользовательской процедуры:


Процедура ПриВыбореКлиента()
    ОткрытьПодбор("Контракты", "ФормаСписка", , 0);
КонецПроцедуры

Казалось бы, код написан абсолютно верно. Однако при интерактивном выборе клиента срабатывает следующий жизненный цикл событий платформы:

  1. Пользователь изменяет значение в поле ввода «Клиент» на форме документа.
  2. Платформа 1С 7.7 перехватывает это событие и выполняет формулу реквизита — процедуру ПриВыбореКлиента().
  3. Внутри процедуры вызывается метод ОткрытьПодбор(). Он создает немодальное окно подбора.
  4. Метод ОткрытьПодбор() завершает свою работу, управление возвращается в саму формулу, а затем — обратно к обработчику поля ввода платформы.
  5. Поскольку процедура отработала, платформа считает, что интерактивное действие с полем ввода «Клиент» успешно завершено. В этот момент происходит неявная активизация этого поля ввода (или следующего элемента в порядке обхода). Фокус принудительно возвращается на форму документа.
  6. Так как окно подбора является немодальным, оно послушно уступает фокус форме документа и оказывается позади нее.

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

Решение 1. Модальный выбор через объект «Справочник» (Рекомендуемый способ)

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

Для выбора единичного значения гораздо надежнее использовать модальное окно выбора. В 1С 7.7 это реализуется через создание объекта типа «Справочник» и вызов метода Выбрать() или ВыбратьЭлемент(). Рассмотрим по шагам, как это реализовать в модуле формы документа:


Процедура ПриВыбореКлиента()
    // Создаем объект справочника "Контракты"
    СпрКонтракты = СоздатьОбъект("Справочник.Контракты");
    
    // Устанавливаем фильтр по владельцу (Клиенту)
    СпрКонтракты.ИспользоватьВладельца(Клиент);
    
    // Открываем модальное окно выбора. 
    // Первый параметр - заголовок окна, второй - идентификатор формы выбора
    Если СпрКонтракты.Выбрать("Выберите контракт для клиента!", "ФормаВыбора") = 1 Тогда
        // Если пользователь сделал выбор, записываем значение в реквизит документа
        Контракт = СпрКонтракты.ТекущийЭлемент();
    Иначе
        // Если пользователь закрыл окно или нажал Отмена
        Предупреждение("Контракт не выбран!");
    КонецЕсли;
КонецПроцедуры

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

Решение 2. Использование предопределенной процедуры ПриНачалеВыбораЗначения()

Если вы всё же хотите использовать именно стандартный немодальный подбор (например, чтобы пользователь мог параллельно просматривать документ или выбирать несколько элементов подряд), нам нужно заблокировать стандартный возврат фокуса в реквизит после выполнения формулы. Для этого в платформе 1С 7.7 предусмотрена специальная предопределенная процедура модуля формы документа — ПриНачалеВыбораЗначения().

Давайте уберем вызов процедуры ПриВыбореКлиента() из свойств (формулы) реквизита на форме и перенесем логику в предопределенный обработчик событий в модуле формы:


Процедура ПриНачалеВыбораЗначения(ИдентификаторРеквизита, ФлагСтандартнойОбработки)
    Если ИдентификаторРеквизита = "Контракт" Тогда
        // Отключаем стандартный выбор значения платформой
        ФлагСтандартнойОбработки = 0;
        
        // Открываем форму списка справочника для подбора
        ОткрытьПодбор("Контракты", "ФормаСписка", , 0);
    КонецЕсли;
КонецПроцедуры

Разберем, что здесь происходит. Параметр ИдентификаторРеквизита принимает строковое имя поля формы, по кнопке выбора которого кликнул пользователь. Установив параметр ФлагСтандартнойОбработки в значение 0, мы явно командуем платформе: «Не нужно выполнять стандартный алгоритм обработки фокуса и выбора для этого реквизита». Благодаря этому фокус не возвращается принудительно на форму документа, и немодальное окно подбора остается открытым на переднем плане.

Решение 3. Перенос вызова на отдельную экранную кнопку

Еще один простой и очевидный способ избежать конфликтов с фокусом поля ввода — перенести вызов процедуры открытия подбора на отдельную кнопку на форме документа (например, кнопку с картинкой «...» или надписью «Подобрать контракт»).

В этом случае в свойствах кнопки в поле «Формула» мы пишем:

ОткрытьПодбор("Контракты", "ФормаСписка", , 0);

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

Ограничение по владельцу при использовании подбора

Раз уж мы говорим о подчиненном справочнике «Контракты», крайне важно, чтобы при открытии подбора пользователь видел договоры только выбранного на форме Клиента, а не весь массив записей справочника. При использовании метода ОткрытьПодбор() ограничение по владельцу передается через параметры.

Рассмотрим, как правильно организовать передачу владельца при инициализации подбора через параметры контекста:


Процедура ПриНачалеВыбораЗначения(ИдентификаторРеквизита, ФлагСтандартнойОбработки)
    Если ИдентификаторРеквизита = "Контракт" Тогда
        ФлагСтандартнойОбработки = 0;
        
        // В качестве четвертого параметра (Контекст) передаем нашего Клиента
        ОткрытьПодбор("Контракты", "ФормаСписка", Клиент, 0);
    КонецЕсли;
КонецПроцедуры

Затем, в модуле формы списка справочника «Контракты» в предопределенной процедуре ПриОткрытии() мы должны программно обработать переданного владельца:


Процедура ПриОткрытии()
    // Проверяем, открыта ли форма в режиме выбора или подбора
    Если Форма.РежимВыбора() = 1 Тогда
        // Если в форму был передан параметр (наш Клиент)
        Если ТипЗначенияСтр(Форма.Параметр) = "Справочник" Тогда
            ИспользоватьВладельца(Форма.Параметр);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Такой подход гарантирует, что список подбора будет отфильтрован строго по выбранному в документе контрагенту, а само окно выбора при использовании процедуры ПриНачалеВыбораЗначения() останется на переднем плане перед глазами пользователя.

Резюме

Мы подробно разобрали проблему «залипания» и ухода окон на задний план в среде 1С:Предприятие 7.7. Для решения этой интерфейсной проблемы у разработчика есть два основных пути:

  1. Если требуется выбрать только одно значение — используйте модальный метод Выбрать() у объекта справочника. Это избавит вас от любых проблем с фокусом и гарантирует простоту кода.
  2. Если необходим полноценный множественный подбор — задействуйте предопределенную процедуру формы ПриНачалеВыбораЗначения() с установкой флага стандартной обработки в значение 0.

Выбирайте наиболее подходящий для вашей бизнес-логики метод и делайте интерфейсы ваших решений на платформе 1С 7.7 удобными и предсказуемыми для пользователей!

← На главную