Как вывести картинки, подписи и водяные знаки под текстом при печати в 1С 7.7?

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

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

В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем исторические обходные пути и их критические недостатки, а затем детально изучим элегантное и современное решение — динамический патч библиотеки moxel.dll в оперативной памяти «на лету» без физического изменения файлов на диске.

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

Почему возникает проблема наложения слоев?

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

  1. Сначала отрисовывается координатная сетка таблицы.
  2. Затем выводится текст во всех заполненных ячейках.
  3. В последнюю очередь поверх сетки и текста накладываются графические объекты: картинки, OLE-объекты, рамки и рисунки (диаграммы).

Из-за такого порядка рендеринга графические слои всегда оказываются выше текстовых. Изменить это поведение штатными свойствами объектов «Рисунок» или «Картинка» в конфигураторе невозможно — там попросту отсутствуют настройки слоев («На задний план» / «На передний план»).

Исторические альтернативные методы и их критические минусы

Долгое время сообщество разработчиков пыталось обойти это ограничение различными «костылями». Рассмотрим подробнее три самых популярных метода прошлых лет и выясним, почему они не подходят для современных систем.

1. Использование компоненты Bmp_1c.ocx (ActiveBMP)

Этот специализированный ActiveX-элемент позволял загружать в таблицу изображения формата BMP с поддержкой прозрачности по ключевому цвету фона. Разработчики часто сочетали его с компонентой TableDoc.dll или классами «1С++». Однако при эксплуатации в современных операционных системах (Windows 7, 10, 11) у этого метода выявились серьезные проблемы:

2. Внедрение OLE-объектов пакета MS Office (Word/Excel)

Метод заключался во внедрении внутрь таблицы 1С OLE-объекта листа Word или Excel, в котором фоновое изображение было настроено средствами самого офисного пакета. Минусы этого подхода очевидны:

3. Переход на альтернативный движок Йоксель (Yoxel)

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

Революционное решение: Изменение порядка отрисовки в памяти

Автор решения (разработчик под ником MadDAD) предложил принципиально иной подход. Вместо того чтобы бороться с последствиями, мы можем изменить причину — сам алгоритм работы moxel.dll.

Если изменить всего 4 байта в коде работающей библиотеки moxel.dll, можно поменять местами вызовы функций отрисовки текста и графических объектов. В результате измененный алгоритм будет работать следующим образом:

  1. Сначала на лист выводятся все графические элементы (рисунки, картинки, OLE-объекты).
  2. В последнюю очередь поверх них накладывается сетка и текст ячеек таблицы.

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

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

Реализация динамического патча с помощью DynWrapX.dll

Самое главное достоинство этого метода — безопасность для системы. Нам не нужно физически изменять файл moxel.dll на диске компьютера (что могло бы нарушить работу других баз или вызвать проблемы с антивирусом). Модификация происходит «на лету» непосредственно в виртуальной памяти процесса 1cv7.exe.

Для осуществления записи в память процесса из среды 1С 7.7 мы используем библиотеку DynWrapX.dll (DynamicWrapperX). Она является универсальным инструментом для вызова функций Windows API напрямую из встроенного языка 1С без написания внешних компонент на C++.

Давайте рассмотрим пошаговый алгоритм, как выполнить эту процедуру:

  1. Зарегистрировать библиотеку DynWrapX.dll в операционной системе (через утилиту regsvr32).
  2. В коде формирования печатной формы инициализировать объект DynamicWrapperX.
  3. Найти базовый адрес загруженной библиотеки moxel.dll в адресном пространстве текущего процесса 1С.
  4. Разрешить запись в нужный сегмент памяти (снять защиту от записи с помощью WinAPI-функции VirtualProtect).
  5. Записать новые 4 байта, меняющие местами вызовы функций рендеринга текста и графики.
  6. Вывести документ на печать или открыть предпросмотр.
  7. После завершения операции вернуть исходные байты на место, чтобы восстановить штатный режим работы платформы.

Пример программной реализации патча памяти

Рассмотрим концептуальный пример кода на встроенном языке 1С 7.7, демонстрирующий принцип работы с памятью процесса через библиотеку DynWrapX.dll.


// Создаем объект для работы с WinAPI функциями
Попытка
    DW = СоздатьОбъект("DynamicWrapperX");
Исключение
    Предупреждение("Библиотека DynWrapX.dll не зарегистрирована в системе!");
    Возврат;
КонецПопытки;

// Регистрируем необходимые функции Windows API
DW.Register("kernel32.dll", "GetModuleHandleA", "i=s", "r=l");
DW.Register("kernel32.dll", "VirtualProtect", "i=l l l p", "r=i");
DW.Register("kernel32.dll", "GetCurrentProcess", "r=l");

// Получаем хэндл (базовый адрес) загруженной библиотеки moxel.dll
АдресMoxel = DW.GetModuleHandleA("moxel.dll");

Если АдресMoxel = 0 Тогда
    Сообщить("Библиотека moxel.dll не найдена в памяти процесса!");
    Возврат;
КонецЕсли;

// Смещение в памяти для изменения порядка вызовов функций отрисовки.
// Внимание: конкретное смещение зависит от версии (релиза) moxel.dll.
// Для примера возьмем условное смещение СмещениеПатча.
АдресТочкиПатча = АдресMoxel + СмещениеПатча; 

// Подготавливаем буфер для сохранения старых прав доступа к участку памяти
СтарыеПрава = 0;

// Разрешаем запись в защищенную область памяти (PAGE_EXECUTE_READWRITE = 0x40)
РезультатЗащиты = DW.VirtualProtect(АдресТочкиПатча, 4, 64, СтарыеПрава);

Если РезультатЗащиты <> 0 Тогда
    // Записываем новые 4 байта в память процесса "на лету"
    // Изменяем вызовы отрисовки графики и текста местами.
    // В реальной демо-обработке здесь происходит запись байтов патча.
    
    Сообщить("Патч успешно применен. Графика теперь будет печататься ПОД текстом.");
    
    // Выводим документ на печать
    Таб.Напечатать(0);
    
    // ОБЯЗАТЕЛЬНО возвращаем исходные байты обратно для стабильности системы!
    // И восстанавливаем исходные права доступа к памяти
    DW.VirtualProtect(АдресТочкиПатча, 4, СтарыеПрава, СтарыеПрава);
Иначе
    Сообщить("Не удалось получить доступ на запись к памяти moxel.dll!");
КонецЕсли;

Преимущества динамического метода

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

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

← На главную