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

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

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

Проблема «потери» контекста при выборе значения

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

Способ 1: Использование системной функции Шаблон

Одним из самых оригинальных и «магических» способов в 1С 7.7 является использование функции Шаблон(). Эта функция вычисляет строковое выражение в контексте исполнения. Удивительно, но при вызове из глобальной процедуры, инициированной из формы, Шаблон() сохраняет доступ к локальным переменным и реквизитам этой формы.

Разберем по шагам, как вытащить конкретный реквизит или даже весь объект. Если мы просто вызовем Шаблон("[ИмяРеквизита]"), мы получим строковое представление. Чтобы получить полноценный объект (например, справочник или сам документ), нужно использовать преобразование через внутреннюю строку.

Рассмотрим пример кода в Глобальном модуле:


Процедура глПолучитьДанныеФормы() Экспорт
    // Получаем строковое значение переменной модуля формы
    ЗначениеСкладаСтр = Шаблон("[Склад]");
    Сообщить("Выбран склад (строка): " + ЗначениеСкладаСтр);

    // Получаем полноценный объект через внутреннюю строку
    // Это позволяет манипулировать объектом как ссылкой
    ВнутрСтр = Шаблон("[ЗначениеВСтрокуВнутр(Склад)]");
    ОбъектСклад = ЗначениеИзСтрокиВнутр(ВнутрСтр);

    Если ТипЗначенияСтр(ОбъектСклад) = "Справочник" Тогда
        Сообщить("Объект успешно получен: " + ОбъектСклад.Наименование);
    КонецЕсли;

    // Можно даже вызвать локальную функцию из модуля формы!
    РезультатФункции = Шаблон("[ИмяЛокальнойФункцииФормы()]");
КонецПроцедуры

Важный нюанс: Метод с Шаблон() иногда может приводить к ошибкам в BLang.dll (Access Violation), если контекст в данный момент нестабилен или занят отрисовкой. Проанализируем причину: это происходит из-за попытки прямого обращения к памяти интерпретатора. Для повышения стабильности рекомендуется использовать этот метод с осторожностью и проверять наличие окна.

Способ 2: Использование библиотеки 1С++ и класса Перехватчик

Для тех, кто использует внешние компоненты, существует более «цивилизованный» и мощный метод — Перехватчик событий (Interceptor). Это часть библиотеки 1С++, которая позволяет перехватывать системные события (такие как открытие формы, нажатие кнопок, выбор реквизита) глобально.

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

Пример логики работы с перехватчиком:

  1. В процедуре ПриНачалеРаботыСистемы создается объект класса Перехватчик.
  2. Настраивается подписка на событие ПриНачалеВыбораЗначения или ПриНажатииКнопки.
  3. В глобальный метод обработки события платформа автоматически передает контекст активной формы в качестве одного из аргументов.

Это решение является наиболее стабильным для крупных конфигураций, так как оно работает на уровне ядра 1С и не зависит от «глюков» функции Шаблон().

Способ 3: Работа через HWND и FormEx

Если нам нужно получить контекст именно того окна, которое является «родителем» для текущего, можно воспользоваться компонентой FormEx. Рассмотрим алгоритм:

  1. С помощью Сервис.АктивноеОкно() получаем дескриптор (HWND) текущего окна (например, окна выбора).
  2. Используя WinAPI-функции (через ту же FormEx), находим родительское окно (Owner).
  3. Используем метод Сервис.КонтекстПоХэндлу(), чтобы восстановить контекст 1С из идентификатора окна Windows.

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

Выводы и рекомендации

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

← На главную