Как вывести неблокирующее сообщение с кнопкой в обычных формах 1С?

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

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

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

Анализ системных функций: ПоказатьВопрос и ПоказатьПредупреждение

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

Поведение функции ПоказатьВопрос()

Функция ПоказатьВопрос() предназначена для создания немодального диалога, который позволяет пользователю выбрать один из предложенных вариантов ответа (кнопок). Результат выбора обрабатывается в специальной процедуре-оповещении. Рассмотрим пример ее использования:


Процедура КнопкаВыполнитьНажатие(Кнопка)
    // Создаем список кнопок для вопроса
    СписокКнопок = Новый СписокЗначений;
    СписокКнопок.Добавить(1, "Кнопка 1");
    СписокКнопок.Добавить(2, "Кнопка 2");
    СписокКнопок.Добавить(3, "Кнопка 3");

    // Создаем описание оповещения, которое будет вызвано после ответа пользователя
    // "ОбработкаОтветаНаВопрос" - имя процедуры, "ЭтаФорма" - контекст, где ее искать
    ОП = Новый ОписаниеОповещения("ОбработкаОтветаНаВопрос", ЭтаФорма);

    // Вызываем функцию ПоказатьВопрос
    // Первый параметр - описание оповещения, второй - текст вопроса, третий - список кнопок
    ПоказатьВопрос(ОП, "Текст вопроса", СписокКнопок);
КонецПроцедуры

Процедура ОбработкаОтветаНаВопрос(РезультатВопроса, ДополнительныеПараметры) Экспорт
    // Эта процедура будет вызвана после того, как пользователь нажмет кнопку.
    // РезультатВопроса будет содержать значение, связанное с выбранной кнопкой.
    Сообщить("Выбрана кнопка: " + РезультатВопроса);
КонецПроцедуры

В теории, этот подход выглядит многообещающим. Однако, как показал опыт автора темы и подтверждается практикой, в обычных формах (особенно на платформе 8.3.18 с режимом совместимости 8.3.14):

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

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

Поведение функции ПоказатьПредупреждение()

Функция ПоказатьПредупреждение() используется для вывода краткого информационного сообщения, которое автоматически закрывается через заданное время или по нажатию кнопки "ОК". Пример использования:


// Пример использования ПоказатьПредупреждение
ПоказатьПредупреждение(,"Это текст сообщения");

Или с задержкой и локализованным текстом:


ПоказатьПредупреждение(,НСтр("ru = 'Выберите документ!'; en = 'Select a document!'"), 10);

Хотя эта функция и доступна начиная с версии 8.3.3 (и, следовательно, должна работать на платформе 8.3.18), она также имеет серьезные недостатки для нашей задачи:

  1. Блокировка интерфейса: ПоказатьПредупреждение() также является блокирующим окном. Оно останавливает взаимодействие пользователя с основной формой до своего закрытия. Автор темы ясно указал: "ПоказатьПредупреждение также блокирует интерфейс".
  2. Отсутствие кастомных кнопок: Эта функция не предоставляет возможности добавить собственные кнопки с произвольным текстом. Обычно она имеет только кнопку "ОК" или закрывается по таймеру, что не соответствует требованию "с кнопкой".

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

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

Создание собственной неблокирующей формы: наиболее надежное решение

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

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

Шаг 1: Создание новой формы в конфигурации

  1. В конфигураторе создадим новый объект "Обработка" (или используем существующую, если она подходит по смыслу).
  2. Для этой обработки создадим новую форму, например, "ФормаСообщения".
  3. В свойствах формы на вкладке "Основные" убедимся, что "Основной реквизит" не ссылается на какой-либо объект данных, если форма будет использоваться исключительно для отображения сообщения.

Шаг 2: Размещение элементов управления на форме

На созданной форме нам потребуется разместить следующие элементы:

  1. Поле надписи (Надпись): Для отображения текста сообщения. Мы можем задать текст сообщения динамически при открытии формы.
  2. Кнопки (Кнопка): Необходимое количество кнопок с нужным текстом. Например, "Да", "Нет", "Отмена", или "Продолжить", "Отложить". Для каждой кнопки создадим обработчик события "Нажатие".
  3. Служебные реквизиты: Если нам нужно передать какие-либо данные из формы сообщения обратно в вызывающую форму (например, результат выбора пользователя), мы можем создать для этого реквизит формы, например, РезультатВыбора типа "Число" или "Строка".

Шаг 3: Реализация логики кнопок

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

  1. Устанавливать значение служебного реквизита РезультатВыбора в соответствии с нажатой кнопкой.
  2. Закрывать форму сообщения. Для этого используем метод Закрыть().

Пример кода для формы сообщения:


// В модуле формы "ФормаСообщения"

// Реквизит формы для хранения результата выбора
// Создайте его на форме (например, РезультатВыбора, тип Число)

Перем мТекстСообщения Экспорт; // Переменная для хранения текста сообщения

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

// Процедура, вызываемая при открытии формы
Процедура ПриОткрытии()
    // Устанавливаем текст надписи из переданного параметра
    ЭлементыФормы.НадписьСообщения.Заголовок = мТекстСообщения;
    // Если нужно, можем динамически создавать или скрывать кнопки
    // в зависимости от переданных параметров.
КонецПроцедуры

Процедура КнопкаДаНажатие(Элемент)
    ЭтотОбъект.РезультатВыбора = 1; // Например, 1 для "Да"
    Закрыть();
КонецПроцедуры

Процедура КнопкаНетНажатие(Элемент)
    ЭтотОбъект.РезультатВыбора = 0; // Например, 0 для "Нет"
    Закрыть();
КонецПроцедуры

Процедура КнопкаОтменаНажатие(Элемент)
    ЭтотОбъект.РезультатВыбора = -1; // Например, -1 для "Отмена"
    Закрыть();
КонецПроцедуры

Обратите внимание, что реквизит РезультатВыбора должен быть создан в свойствах формы, чтобы он был доступен после закрытия формы. Также можно использовать параметр формы для передачи текста сообщения, чтобы форма была более универсальной.

Шаг 4: Открытие формы в неблокирующем режиме

Самый важный шаг – это открытие формы сообщения таким образом, чтобы она не блокировала интерфейс вызывающей формы. Для этого используем метод ОткрытьФорму().

Ключевым моментом является правильное использование параметров метода ОткрытьФорму(), особенно в части, касающейся модальности.


// В модуле вызывающей формы (где мы хотим показать сообщение)

Процедура ПоказатьНеблокирующееСообщение()
    // Определяем имя формы, которую хотим открыть
    ИмяФормыСообщения = "Обработка.МояОбработкаСообщений.Форма.ФормаСообщения";

    // Создаем структуру параметров для передачи в форму сообщения
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ТекстСообщения", "Внимание! Это важное сообщение, но вы можете продолжить работу.");
    // Можем передать список кнопок, чтобы форма сама их отобразила,
    // или другие данные, необходимые для ее работы.

    // Создаем ОписаниеОповещения для обработки результата после закрытия формы сообщения.
    // "ОбработкаЗакрытияФормыСообщения" - имя процедуры в текущей форме,
    // которая будет вызвана при закрытии ФормыСообщения.
    Оповещение = Новый ОписаниеОповещения("ОбработкаЗакрытияФормыСообщения", ЭтаФорма);

    // Открываем форму
    // Второй параметр - владелец формы (для обычных форм часто ЭтаФорма)
    // Третий параметр - уникальный идентификатор формы (необязательно, но полезно)
    // Четвертый параметр - режим открытия (для неблокирующего - РежимОткрытияОкна.Независимый или по умолчанию)
    ОткрытьФорму(ИмяФормыСообщения, ПараметрыФормы, ЭтаФорма, , Оповещение);

    // ВНИМАНИЕ: Код после ОткрытьФорму() продолжит выполняться сразу же,
    // потому что форма открывается НЕМОДАЛЬНО!
    // Результат выбора пользователя будет доступен только в процедуре-оповещении.
    Сообщить("Код после вызова формы сообщения продолжает выполняться.");
КонецПроцедуры

// Процедура-обработчик для оповещения о закрытии формы сообщения
Процедура ОбработкаЗакрытияФормыСообщения(ЗакрытаяФорма, РезультатЗакрытия) Экспорт
    // ЗакрытаяФорма - ссылка на объект формы, которая была закрыта
    // РезультатЗакрытия - результат, переданный при закрытии формы (если он был задан)

    Если ЗакрытаяФорма.РезультатВыбора = 1 Тогда
        Сообщить("Пользователь выбрал 'Да'.");
    ИначеЕсли ЗакрытаяФорма.РезультатВыбора = 0 Тогда
        Сообщить("Пользователь выбрал 'Нет'.");
    ИначеЕсли ЗакрытаяФорма.РезультатВыбора = -1 Тогда
        Сообщить("Пользователь выбрал 'Отмена'.");
    Иначе
        Сообщить("Форма сообщения закрыта без явного выбора.");
    КонецЕсли;

    // Здесь мы можем продолжить логику, зависящую от выбора пользователя
КонецПроцедуры

Ключевые моменты при вызове ОткрытьФорму() для неблокирующего поведения:

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

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

Альтернативные способы информирования (без кнопок)

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

  1. Сообщить():

    Этот метод выводит текст в окно сообщений 1С (панель "Сообщения"). Он полностью неблокирующий и никак не прерывает работу пользователя. Однако он не предоставляет никаких кнопок для взаимодействия.

    Сообщить("Это просто информационное сообщение.");

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

  2. ПоказатьОповещениеПользователя():

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

    
    ПоказатьОповещениеПользователя("Документ проведен успешно!", "Документ", "Элемент.Наименование");
    

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

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

Резюме и рекомендации

Мы подробно рассмотрели проблему вывода неблокирующего сообщения с кнопкой в обычных формах 1С:Предприятия. Выяснили, что системные функции ПоказатьВопрос() и ПоказатьПредупреждение(), несмотря на их предназначение, в обычных формах версии 8.3.18 (и совместимости 8.3.14) демонстрируют поведение, не соответствующее требованиям: они блокируют интерфейс и/или не позволяют настроить кнопки так, как нам необходимо.

Наиболее надежным и гибким решением является создание собственной, произвольной формы. Этот подход обеспечивает полный контроль над внешним видом, логикой и, что критически важно, режимом открытия окна. Используя ОткрытьФорму() с ОписаниеОповещения, мы можем добиться полностью неблокирующего поведения и асинхронной обработки ответа пользователя.

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

Таким образом, если вы работаете с обычными формами и сталкиваетесь с задачей вывода неблокирующего диалога с настраиваемыми кнопками, создайте свою форму. Это даст вам необходимый контроль и предсказуемый результат.

← На главную