Как создать аналог рабочего стола на управляемой форме в обычном приложении 1С и заблокировать её закрытие

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

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

Однако здесь возникает серьезное техническое препятствие: штатный механизм рабочего стола в обычном приложении поддерживает работу исключительно с обычными (неуправляемыми) формами. Чтобы обойти это ограничение, разработчики запускают управляемую форму обработки программно при старте системы, максимизируют её и пытаются заблокировать её закрытие. Но как сделать так, чтобы пользователь не мог случайно закрыть эту форму «крестиком» или сочетанием клавиш, но при этом сама программа 1С закрывалась в штатном режиме? Давайте подробно разберем эту задачу и найдем элегантные решения для различных версий платформы и режимов совместимости.

Суть проблемы и почему стандартный отказ не всегда работает

Первое решение, которое приходит в голову любому разработчику — использовать предопределенное событие формы ПередЗакрытием и принудительно устанавливать параметр Отказ = Истина. Рассмотрим, как выглядит этот простой обработчик:


&НаКлиенте
Процедура ПередЗакрытием(Отказ, СтандартнаяОбработка)
    Отказ = Истина;
КонецПроцедуры

Если мы напишем такой код, то действительно полностью заблокируем закрытие формы. Пользователь не сможет закрыть её ни нажатием на крестик, ни клавишей Esc, ни через системное меню. Однако у этого подхода есть критический недостаток: пользователь не сможет закрыть саму программу 1С. При попытке выхода из системы платформа отправляет команду закрытия всем открытым окнам. Наша форма перехватывает это событие, устанавливает Отказ = Истина, и работа приложения продолжается как ни в чем не бывало.

Для решения этой проблемы в современных версиях платформы 1С (начиная с 8.3.8) в событие ПередЗакрытием были добавлены новые параметры, включая ЗавершениеРаботы. Но в конфигурациях, работающих в режиме совместимости (например, УПП), эти параметры возвращают значение Неопределено. Ниже мы детально рассмотрим, как обойти это ограничение в любом режиме.

Решение 1. Универсальный обходной путь для конфигураций в режиме совместимости (УПП 1.3 и др.)

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

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

Шаг 1. Настройка Модуля обычного приложения

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


Перем ЗакрытиеПриложения Экспорт;

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

Процедура ПриЗавершенииРаботыСистемы()
    // Сбрасываем флаг на случай, если закрытие было отменено другими модулями
    ЗакрытиеПриложения = Ложь; 
КонецПроцедуры

// Первоначальная инициализация при старте
ЗакрытиеПриложения = Ложь;

Шаг 2. Настройка обработчика в Управляемой форме нашей обработки

Теперь перейдем в модуль управляемой формы нашей обработки «Рабочий стол» и пропишем проверку нашей глобальной переменной при закрытии:


&НаКлиенте
Процедура ПередЗакрытием(Отказ, СтандартнаяОбработка)
    
    // Проверяем состояние глобальной переменной обычного приложения
    Попытка
        Если ЗакрытиеПриложения Тогда
            // Если закрывается вся система - разрешаем закрытие формы
            Отказ = Ложь;
            Возврат;
        КонецЕсли;
    Исключение
        // На случай, если переменная по какой-то причине недоступна
    КонецПопытки;
    
    // Во всех остальных случаях (нажатие крестика, Esc) блокируем закрытие
    Отказ = Истина;
    
КонецПроцедуры

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

Решение 2. Штатный механизм для современных конфигураций (без режима совместимости)

Если ваша конфигурация переведена на современную платформу и режим совместимости отключен (или установлен на версию 8.3.8 и выше), вам доступен полноценный системный механизм разделения типов закрытия. Платформа сама передает булево значение в параметр ЗавершениеРаботы.

В этом случае код управляемой формы выглядит предельно просто и лаконично:


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

Важное архитектурное ограничение платформы: Обратите внимание, что когда параметр ЗавершениеРаботы принимает значение Истина, платформа накладывает строгие требования веб-стандартов. В этот момент в коде категорически запрещено выполнять серверные вызовы (методы с директивой &НаСервере) или открывать любые новые диалоговые окна. Попытка вызвать серверную функцию приведет к аварийному завершению сеанса с ошибкой.

Решение 3. Интеграция рабочего стола в интерфейс обычного приложения

Чтобы форма автоматически открывалась при входе пользователя в систему и вела себя как полноценный рабочий стол, нам необходимо правильно её инициализировать. Открытие формы следует настроить в процедуре ПриНачалеРаботыСистемы модуля обычного приложения.

Проанализируем пример кода для программного открытия формы в развернутом виде:


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

Решение 4. Дополнительная визуальная маскировка и настройка свойств формы

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

  1. В палитре свойств управляемой формы снимите флаг Кнопка закрытия. Это уберет стандартный «крестик» в правом верхнем углу окна.
  2. Установите свойство Способ отображения окна в значение Максимизированное.
  3. В командной панели формы отключите видимость стандартных системных команд. Обязательно скройте или переопределите кнопку «Еще -> Закрыть», чтобы пользователь не путался в интерфейсе.
  4. При необходимости оставьте скрытую кнопку закрытия формы только для пользователей с ролью ПолныеПрава (Администраторы), чтобы облегчить процесс отладки и тестирования функционала.

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

← На главную